diff options
Diffstat (limited to 'drivers/iio/adc')
69 files changed, 4320 insertions, 1011 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 7e3286265a38..82e33082958c 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -6,11 +6,28 @@ menu "Analog to digital converters" +config AB8500_GPADC + bool "ST-Ericsson AB8500 GPADC driver" + depends on AB8500_CORE && REGULATOR_AB8500 + default y + help + AB8500 Analog Baseband, mixed signal integrated circuit GPADC + (General Purpose Analog to Digital Converter) driver used to monitor + internal voltages, convert accessory and battery, AC (charger, mains) + and USB voltages integral to the U8500 platform. + config AD_SIGMA_DELTA tristate select IIO_BUFFER select IIO_TRIGGERED_BUFFER +config AD7091R5 + tristate "Analog Devices AD7091R5 ADC Driver" + depends on I2C + select REGMAP_I2C + help + Say yes here to build support for Analog Devices AD7091R-5 ADC. + config AD7124 tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver" depends on SPI_MASTER @@ -45,6 +62,16 @@ config AD7291 To compile this driver as a module, choose M here: the module will be called ad7291. +config AD7292 + tristate "Analog Devices AD7292 ADC driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD7292 + 8 Channel ADC with temperature sensor. + + To compile this driver as a module, choose M here: the + module will be called ad7292. + config AD7298 tristate "Analog Devices AD7298 ADC driver" depends on SPI @@ -432,6 +459,17 @@ config INGENIC_ADC This driver can also be built as a module. If so, the module will be called ingenic_adc. +config INTEL_MRFLD_ADC + tristate "Intel Merrifield Basin Cove ADC driver" + depends on INTEL_SOC_PMIC_MRFLD + help + Say yes here to have support for Basin Cove power management IC (PMIC) ADC + device. Depending on platform configuration, this general purpose ADC can + be used for sampling sensors such as thermal resistors. + + To compile this driver as a module, choose M here: the module will be + called intel_mrfld_adc. + config IMX7D_ADC tristate "Freescale IMX7D ADC driver" depends on ARCH_MXC || COMPILE_TEST @@ -492,6 +530,16 @@ config LTC2485 To compile this driver as a module, choose M here: the module will be called ltc2485. +config LTC2496 + tristate "Linear Technology LTC2496 ADC driver" + depends on SPI + help + Say yes here to build support for Linear Technology LTC2496 + 16-Bit 8-/16-Channel Delta Sigma ADC. + + To compile this driver as a module, choose M here: the module will be + called ltc2496. + config LTC2497 tristate "Linear Technology LTC2497 ADC driver" depends on I2C @@ -508,8 +556,8 @@ config MAX1027 select IIO_BUFFER select IIO_TRIGGERED_BUFFER help - Say yes here to build support for Maxim SPI ADC models - max1027, max1029 and max1031. + Say yes here to build support for Maxim SPI {10,12}-bit ADC models: + max1027, max1029, max1031, max1227, max1229 and max1231. To compile this driver as a module, choose M here: the module will be called max1027. @@ -958,7 +1006,7 @@ config TI_ADC161S626 config TI_ADS1015 tristate "Texas Instruments ADS1015 ADC" - depends on I2C && !SENSORS_ADS1015 + depends on I2C select REGMAP_I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index ef9cc485fb67..919228900df9 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -4,10 +4,13 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o +obj-$(CONFIG_AD7091R5) += ad7091r5.o ad7091r-base.o obj-$(CONFIG_AD7124) += ad7124.o obj-$(CONFIG_AD7266) += ad7266.o obj-$(CONFIG_AD7291) += ad7291.o +obj-$(CONFIG_AD7292) += ad7292.o obj-$(CONFIG_AD7298) += ad7298.o obj-$(CONFIG_AD7923) += ad7923.o obj-$(CONFIG_AD7476) += ad7476.o @@ -42,12 +45,14 @@ obj-$(CONFIG_HX711) += hx711.o obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_INGENIC_ADC) += ingenic-adc.o +obj-$(CONFIG_INTEL_MRFLD_ADC) += intel_mrfld_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_LTC2496) += ltc2496.o ltc2497-core.o +obj-$(CONFIG_LTC2497) += ltc2497.o ltc2497-core.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX1118) += max1118.o diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c new file mode 100644 index 000000000000..fd5b18d7f0c2 --- /dev/null +++ b/drivers/iio/adc/ab8500-gpadc.c @@ -0,0 +1,1218 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Arun R Murthy <arun.murthy@stericsson.com> + * Author: Daniel Willerud <daniel.willerud@stericsson.com> + * Author: Johan Palsson <johan.palsson@stericsson.com> + * Author: M'boumba Cedric Madianga + * Author: Linus Walleij <linus.walleij@linaro.org> + * + * AB8500 General Purpose ADC driver. The AB8500 uses reference voltages: + * VinVADC, and VADC relative to GND to do its job. It monitors main and backup + * battery voltages, AC (mains) voltage, USB cable voltage, as well as voltages + * representing the temperature of the chip die and battery, accessory + * detection by resistance measurements using relative voltages and GSM burst + * information. + * + * Some of the voltages are measured on external pins on the IC, such as + * battery temperature or "ADC aux" 1 and 2. Other voltages are internal rails + * from other parts of the ASIC such as main charger voltage, main and battery + * backup voltage or USB VBUS voltage. For this reason drivers for other + * parts of the system are required to obtain handles to the ADC to do work + * for them and the IIO driver provides arbitration among these consumers. + */ +#include <linux/init.h> +#include <linux/bits.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <linux/pm_runtime.h> +#include <linux/platform_device.h> +#include <linux/completion.h> +#include <linux/regulator/consumer.h> +#include <linux/random.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500.h> + +/* GPADC register offsets and bit definitions */ + +#define AB8500_GPADC_CTRL1_REG 0x00 +/* GPADC control register 1 bits */ +#define AB8500_GPADC_CTRL1_DISABLE 0x00 +#define AB8500_GPADC_CTRL1_ENABLE BIT(0) +#define AB8500_GPADC_CTRL1_TRIG_ENA BIT(1) +#define AB8500_GPADC_CTRL1_START_SW_CONV BIT(2) +#define AB8500_GPADC_CTRL1_BTEMP_PULL_UP BIT(3) +/* 0 = use rising edge, 1 = use falling edge */ +#define AB8500_GPADC_CTRL1_TRIG_EDGE BIT(4) +/* 0 = use VTVOUT, 1 = use VRTC as pull-up supply for battery temp NTC */ +#define AB8500_GPADC_CTRL1_PUPSUPSEL BIT(5) +#define AB8500_GPADC_CTRL1_BUF_ENA BIT(6) +#define AB8500_GPADC_CTRL1_ICHAR_ENA BIT(7) + +#define AB8500_GPADC_CTRL2_REG 0x01 +#define AB8500_GPADC_CTRL3_REG 0x02 +/* + * GPADC control register 2 and 3 bits + * the bit layout is the same for SW and HW conversion set-up + */ +#define AB8500_GPADC_CTRL2_AVG_1 0x00 +#define AB8500_GPADC_CTRL2_AVG_4 BIT(5) +#define AB8500_GPADC_CTRL2_AVG_8 BIT(6) +#define AB8500_GPADC_CTRL2_AVG_16 (BIT(5) | BIT(6)) + +enum ab8500_gpadc_channel { + AB8500_GPADC_CHAN_UNUSED = 0x00, + AB8500_GPADC_CHAN_BAT_CTRL = 0x01, + AB8500_GPADC_CHAN_BAT_TEMP = 0x02, + /* This is not used on AB8505 */ + AB8500_GPADC_CHAN_MAIN_CHARGER = 0x03, + AB8500_GPADC_CHAN_ACC_DET_1 = 0x04, + AB8500_GPADC_CHAN_ACC_DET_2 = 0x05, + AB8500_GPADC_CHAN_ADC_AUX_1 = 0x06, + AB8500_GPADC_CHAN_ADC_AUX_2 = 0x07, + AB8500_GPADC_CHAN_VBAT_A = 0x08, + AB8500_GPADC_CHAN_VBUS = 0x09, + AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT = 0x0a, + AB8500_GPADC_CHAN_USB_CHARGER_CURRENT = 0x0b, + AB8500_GPADC_CHAN_BACKUP_BAT = 0x0c, + /* Only on AB8505 */ + AB8505_GPADC_CHAN_DIE_TEMP = 0x0d, + AB8500_GPADC_CHAN_ID = 0x0e, + AB8500_GPADC_CHAN_INTERNAL_TEST_1 = 0x0f, + AB8500_GPADC_CHAN_INTERNAL_TEST_2 = 0x10, + AB8500_GPADC_CHAN_INTERNAL_TEST_3 = 0x11, + /* FIXME: Applicable to all ASIC variants? */ + AB8500_GPADC_CHAN_XTAL_TEMP = 0x12, + AB8500_GPADC_CHAN_VBAT_TRUE_MEAS = 0x13, + /* FIXME: Doesn't seem to work with pure AB8500 */ + AB8500_GPADC_CHAN_BAT_CTRL_AND_IBAT = 0x1c, + AB8500_GPADC_CHAN_VBAT_MEAS_AND_IBAT = 0x1d, + AB8500_GPADC_CHAN_VBAT_TRUE_MEAS_AND_IBAT = 0x1e, + AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT = 0x1f, + /* + * Virtual channel used only for ibat conversion to ampere. + * Battery current conversion (ibat) cannot be requested as a + * single conversion but it is always requested in combination + * with other input requests. + */ + AB8500_GPADC_CHAN_IBAT_VIRTUAL = 0xFF, +}; + +#define AB8500_GPADC_AUTO_TIMER_REG 0x03 + +#define AB8500_GPADC_STAT_REG 0x04 +#define AB8500_GPADC_STAT_BUSY BIT(0) + +#define AB8500_GPADC_MANDATAL_REG 0x05 +#define AB8500_GPADC_MANDATAH_REG 0x06 +#define AB8500_GPADC_AUTODATAL_REG 0x07 +#define AB8500_GPADC_AUTODATAH_REG 0x08 +#define AB8500_GPADC_MUX_CTRL_REG 0x09 +#define AB8540_GPADC_MANDATA2L_REG 0x09 +#define AB8540_GPADC_MANDATA2H_REG 0x0A +#define AB8540_GPADC_APEAAX_REG 0x10 +#define AB8540_GPADC_APEAAT_REG 0x11 +#define AB8540_GPADC_APEAAM_REG 0x12 +#define AB8540_GPADC_APEAAH_REG 0x13 +#define AB8540_GPADC_APEAAL_REG 0x14 + +/* + * OTP register offsets + * Bank : 0x15 + */ +#define AB8500_GPADC_CAL_1 0x0F +#define AB8500_GPADC_CAL_2 0x10 +#define AB8500_GPADC_CAL_3 0x11 +#define AB8500_GPADC_CAL_4 0x12 +#define AB8500_GPADC_CAL_5 0x13 +#define AB8500_GPADC_CAL_6 0x14 +#define AB8500_GPADC_CAL_7 0x15 +/* New calibration for 8540 */ +#define AB8540_GPADC_OTP4_REG_7 0x38 +#define AB8540_GPADC_OTP4_REG_6 0x39 +#define AB8540_GPADC_OTP4_REG_5 0x3A + +#define AB8540_GPADC_DIS_ZERO 0x00 +#define AB8540_GPADC_EN_VBIAS_XTAL_TEMP 0x02 + +/* GPADC constants from AB8500 spec, UM0836 */ +#define AB8500_ADC_RESOLUTION 1024 +#define AB8500_ADC_CH_BTEMP_MIN 0 +#define AB8500_ADC_CH_BTEMP_MAX 1350 +#define AB8500_ADC_CH_DIETEMP_MIN 0 +#define AB8500_ADC_CH_DIETEMP_MAX 1350 +#define AB8500_ADC_CH_CHG_V_MIN 0 +#define AB8500_ADC_CH_CHG_V_MAX 20030 +#define AB8500_ADC_CH_ACCDET2_MIN 0 +#define AB8500_ADC_CH_ACCDET2_MAX 2500 +#define AB8500_ADC_CH_VBAT_MIN 2300 +#define AB8500_ADC_CH_VBAT_MAX 4800 +#define AB8500_ADC_CH_CHG_I_MIN 0 +#define AB8500_ADC_CH_CHG_I_MAX 1500 +#define AB8500_ADC_CH_BKBAT_MIN 0 +#define AB8500_ADC_CH_BKBAT_MAX 3200 + +/* GPADC constants from AB8540 spec */ +#define AB8500_ADC_CH_IBAT_MIN (-6000) /* mA range measured by ADC for ibat */ +#define AB8500_ADC_CH_IBAT_MAX 6000 +#define AB8500_ADC_CH_IBAT_MIN_V (-60) /* mV range measured by ADC for ibat */ +#define AB8500_ADC_CH_IBAT_MAX_V 60 +#define AB8500_GPADC_IBAT_VDROP_L (-56) /* mV */ +#define AB8500_GPADC_IBAT_VDROP_H 56 + +/* This is used to not lose precision when dividing to get gain and offset */ +#define AB8500_GPADC_CALIB_SCALE 1000 +/* + * Number of bits shift used to not lose precision + * when dividing to get ibat gain. + */ +#define AB8500_GPADC_CALIB_SHIFT_IBAT 20 + +/* Time in ms before disabling regulator */ +#define AB8500_GPADC_AUTOSUSPEND_DELAY 1 + +#define AB8500_GPADC_CONVERSION_TIME 500 /* ms */ + +enum ab8500_cal_channels { + AB8500_CAL_VMAIN = 0, + AB8500_CAL_BTEMP, + AB8500_CAL_VBAT, + AB8500_CAL_IBAT, + AB8500_CAL_NR, +}; + +/** + * struct ab8500_adc_cal_data - Table for storing gain and offset for the + * calibrated ADC channels + * @gain: Gain of the ADC channel + * @offset: Offset of the ADC channel + * @otp_calib_hi: Calibration from OTP + * @otp_calib_lo: Calibration from OTP + */ +struct ab8500_adc_cal_data { + s64 gain; + s64 offset; + u16 otp_calib_hi; + u16 otp_calib_lo; +}; + +/** + * struct ab8500_gpadc_chan_info - per-channel GPADC info + * @name: name of the channel + * @id: the internal AB8500 ID number for the channel + * @hardware_control: indicate that we want to use hardware ADC control + * on this channel, the default is software ADC control. Hardware control + * is normally only used to test the battery voltage during GSM bursts + * and needs a hardware trigger on the GPADCTrig pin of the ASIC. + * @falling_edge: indicate that we want to trigger on falling edge + * rather than rising edge, rising edge is the default + * @avg_sample: how many samples to average: must be 1, 4, 8 or 16. + * @trig_timer: how long to wait for the trigger, in 32kHz periods: + * 0 .. 255 periods + */ +struct ab8500_gpadc_chan_info { + const char *name; + u8 id; + bool hardware_control; + bool falling_edge; + u8 avg_sample; + u8 trig_timer; +}; + +/** + * struct ab8500_gpadc - AB8500 GPADC device information + * @dev: pointer to the containing device + * @ab8500: pointer to the parent AB8500 device + * @chans: internal per-channel information container + * @nchans: number of channels + * @complete: pointer to the completion that indicates + * the completion of an gpadc conversion cycle + * @vddadc: pointer to the regulator supplying VDDADC + * @irq_sw: interrupt number that is used by gpadc for software ADC conversion + * @irq_hw: interrupt number that is used by gpadc for hardware ADC conversion + * @cal_data: array of ADC calibration data structs + */ +struct ab8500_gpadc { + struct device *dev; + struct ab8500 *ab8500; + struct ab8500_gpadc_chan_info *chans; + unsigned int nchans; + struct completion complete; + struct regulator *vddadc; + int irq_sw; + int irq_hw; + struct ab8500_adc_cal_data cal_data[AB8500_CAL_NR]; +}; + +static struct ab8500_gpadc_chan_info * +ab8500_gpadc_get_channel(struct ab8500_gpadc *gpadc, u8 chan) +{ + struct ab8500_gpadc_chan_info *ch; + int i; + + for (i = 0; i < gpadc->nchans; i++) { + ch = &gpadc->chans[i]; + if (ch->id == chan) + break; + } + if (i == gpadc->nchans) + return NULL; + + return ch; +} + +/** + * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage + * @gpadc: GPADC instance + * @ch: the sampled channel this raw value is coming from + * @ad_value: the raw value + */ +static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, + enum ab8500_gpadc_channel ch, + int ad_value) +{ + int res; + + switch (ch) { + case AB8500_GPADC_CHAN_MAIN_CHARGER: + /* No calibration data available: just interpolate */ + if (!gpadc->cal_data[AB8500_CAL_VMAIN].gain) { + res = AB8500_ADC_CH_CHG_V_MIN + (AB8500_ADC_CH_CHG_V_MAX - + AB8500_ADC_CH_CHG_V_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + } + /* Here we can use calibration */ + res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_VMAIN].gain + + gpadc->cal_data[AB8500_CAL_VMAIN].offset) / AB8500_GPADC_CALIB_SCALE; + break; + + case AB8500_GPADC_CHAN_BAT_CTRL: + case AB8500_GPADC_CHAN_BAT_TEMP: + case AB8500_GPADC_CHAN_ACC_DET_1: + case AB8500_GPADC_CHAN_ADC_AUX_1: + case AB8500_GPADC_CHAN_ADC_AUX_2: + case AB8500_GPADC_CHAN_XTAL_TEMP: + /* No calibration data available: just interpolate */ + if (!gpadc->cal_data[AB8500_CAL_BTEMP].gain) { + res = AB8500_ADC_CH_BTEMP_MIN + (AB8500_ADC_CH_BTEMP_MAX - + AB8500_ADC_CH_BTEMP_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + } + /* Here we can use calibration */ + res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_BTEMP].gain + + gpadc->cal_data[AB8500_CAL_BTEMP].offset) / AB8500_GPADC_CALIB_SCALE; + break; + + case AB8500_GPADC_CHAN_VBAT_A: + case AB8500_GPADC_CHAN_VBAT_TRUE_MEAS: + /* No calibration data available: just interpolate */ + if (!gpadc->cal_data[AB8500_CAL_VBAT].gain) { + res = AB8500_ADC_CH_VBAT_MIN + (AB8500_ADC_CH_VBAT_MAX - + AB8500_ADC_CH_VBAT_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + } + /* Here we can use calibration */ + res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_VBAT].gain + + gpadc->cal_data[AB8500_CAL_VBAT].offset) / AB8500_GPADC_CALIB_SCALE; + break; + + case AB8505_GPADC_CHAN_DIE_TEMP: + res = AB8500_ADC_CH_DIETEMP_MIN + + (AB8500_ADC_CH_DIETEMP_MAX - AB8500_ADC_CH_DIETEMP_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + + case AB8500_GPADC_CHAN_ACC_DET_2: + res = AB8500_ADC_CH_ACCDET2_MIN + + (AB8500_ADC_CH_ACCDET2_MAX - AB8500_ADC_CH_ACCDET2_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + + case AB8500_GPADC_CHAN_VBUS: + res = AB8500_ADC_CH_CHG_V_MIN + + (AB8500_ADC_CH_CHG_V_MAX - AB8500_ADC_CH_CHG_V_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + + case AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT: + case AB8500_GPADC_CHAN_USB_CHARGER_CURRENT: + res = AB8500_ADC_CH_CHG_I_MIN + + (AB8500_ADC_CH_CHG_I_MAX - AB8500_ADC_CH_CHG_I_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + + case AB8500_GPADC_CHAN_BACKUP_BAT: + res = AB8500_ADC_CH_BKBAT_MIN + + (AB8500_ADC_CH_BKBAT_MAX - AB8500_ADC_CH_BKBAT_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + + case AB8500_GPADC_CHAN_IBAT_VIRTUAL: + /* No calibration data available: just interpolate */ + if (!gpadc->cal_data[AB8500_CAL_IBAT].gain) { + res = AB8500_ADC_CH_IBAT_MIN + (AB8500_ADC_CH_IBAT_MAX - + AB8500_ADC_CH_IBAT_MIN) * ad_value / + AB8500_ADC_RESOLUTION; + break; + } + /* Here we can use calibration */ + res = (int) (ad_value * gpadc->cal_data[AB8500_CAL_IBAT].gain + + gpadc->cal_data[AB8500_CAL_IBAT].offset) + >> AB8500_GPADC_CALIB_SHIFT_IBAT; + break; + + default: + dev_err(gpadc->dev, + "unknown channel ID: %d, not possible to convert\n", + ch); + res = -EINVAL; + break; + + } + + return res; +} + +static int ab8500_gpadc_read(struct ab8500_gpadc *gpadc, + const struct ab8500_gpadc_chan_info *ch, + int *ibat) +{ + int ret; + int looplimit = 0; + unsigned long completion_timeout; + u8 val; + u8 low_data, high_data, low_data2, high_data2; + u8 ctrl1; + u8 ctrl23; + unsigned int delay_min = 0; + unsigned int delay_max = 0; + u8 data_low_addr, data_high_addr; + + if (!gpadc) + return -ENODEV; + + /* check if conversion is supported */ + if ((gpadc->irq_sw <= 0) && !ch->hardware_control) + return -ENOTSUPP; + if ((gpadc->irq_hw <= 0) && ch->hardware_control) + return -ENOTSUPP; + + /* Enable vddadc by grabbing PM runtime */ + pm_runtime_get_sync(gpadc->dev); + + /* Check if ADC is not busy, lock and proceed */ + do { + ret = abx500_get_register_interruptible(gpadc->dev, + AB8500_GPADC, AB8500_GPADC_STAT_REG, &val); + if (ret < 0) + goto out; + if (!(val & AB8500_GPADC_STAT_BUSY)) + break; + msleep(20); + } while (++looplimit < 10); + if (looplimit >= 10 && (val & AB8500_GPADC_STAT_BUSY)) { + dev_err(gpadc->dev, "gpadc_conversion: GPADC busy"); + ret = -EINVAL; + goto out; + } + + /* Enable GPADC */ + ctrl1 = AB8500_GPADC_CTRL1_ENABLE; + + /* Select the channel source and set average samples */ + switch (ch->avg_sample) { + case 1: + ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_1; + break; + case 4: + ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_4; + break; + case 8: + ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_8; + break; + default: + ctrl23 = ch->id | AB8500_GPADC_CTRL2_AVG_16; + break; + } + + if (ch->hardware_control) { + ret = abx500_set_register_interruptible(gpadc->dev, + AB8500_GPADC, AB8500_GPADC_CTRL3_REG, ctrl23); + ctrl1 |= AB8500_GPADC_CTRL1_TRIG_ENA; + if (ch->falling_edge) + ctrl1 |= AB8500_GPADC_CTRL1_TRIG_EDGE; + } else { + ret = abx500_set_register_interruptible(gpadc->dev, + AB8500_GPADC, AB8500_GPADC_CTRL2_REG, ctrl23); + } + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc_conversion: set avg samples failed\n"); + goto out; + } + + /* + * Enable ADC, buffering, select rising edge and enable ADC path + * charging current sense if it needed, ABB 3.0 needs some special + * treatment too. + */ + switch (ch->id) { + case AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT: + case AB8500_GPADC_CHAN_USB_CHARGER_CURRENT: + ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA | + AB8500_GPADC_CTRL1_ICHAR_ENA; + break; + case AB8500_GPADC_CHAN_BAT_TEMP: + if (!is_ab8500_2p0_or_earlier(gpadc->ab8500)) { + ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA | + AB8500_GPADC_CTRL1_BTEMP_PULL_UP; + /* + * Delay might be needed for ABB8500 cut 3.0, if not, + * remove when hardware will be available + */ + delay_min = 1000; /* Delay in micro seconds */ + delay_max = 10000; /* large range optimises sleepmode */ + break; + } + /* Fall through */ + default: + ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA; + break; + } + + /* Write configuration to control register 1 */ + ret = abx500_set_register_interruptible(gpadc->dev, + AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ctrl1); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc_conversion: set Control register failed\n"); + goto out; + } + + if (delay_min != 0) + usleep_range(delay_min, delay_max); + + if (ch->hardware_control) { + /* Set trigger delay timer */ + ret = abx500_set_register_interruptible(gpadc->dev, + AB8500_GPADC, AB8500_GPADC_AUTO_TIMER_REG, + ch->trig_timer); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc_conversion: trig timer failed\n"); + goto out; + } + completion_timeout = 2 * HZ; + data_low_addr = AB8500_GPADC_AUTODATAL_REG; + data_high_addr = AB8500_GPADC_AUTODATAH_REG; + } else { + /* Start SW conversion */ + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB8500_GPADC, AB8500_GPADC_CTRL1_REG, + AB8500_GPADC_CTRL1_START_SW_CONV, + AB8500_GPADC_CTRL1_START_SW_CONV); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc_conversion: start s/w conv failed\n"); + goto out; + } + completion_timeout = msecs_to_jiffies(AB8500_GPADC_CONVERSION_TIME); + data_low_addr = AB8500_GPADC_MANDATAL_REG; + data_high_addr = AB8500_GPADC_MANDATAH_REG; + } + + /* Wait for completion of conversion */ + if (!wait_for_completion_timeout(&gpadc->complete, + completion_timeout)) { + dev_err(gpadc->dev, + "timeout didn't receive GPADC conv interrupt\n"); + ret = -EINVAL; + goto out; + } + + /* Read the converted RAW data */ + ret = abx500_get_register_interruptible(gpadc->dev, + AB8500_GPADC, data_low_addr, &low_data); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc_conversion: read low data failed\n"); + goto out; + } + + ret = abx500_get_register_interruptible(gpadc->dev, + AB8500_GPADC, data_high_addr, &high_data); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc_conversion: read high data failed\n"); + goto out; + } + + /* Check if double conversion is required */ + if ((ch->id == AB8500_GPADC_CHAN_BAT_CTRL_AND_IBAT) || + (ch->id == AB8500_GPADC_CHAN_VBAT_MEAS_AND_IBAT) || + (ch->id == AB8500_GPADC_CHAN_VBAT_TRUE_MEAS_AND_IBAT) || + (ch->id == AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT)) { + + if (ch->hardware_control) { + /* not supported */ + ret = -ENOTSUPP; + dev_err(gpadc->dev, + "gpadc_conversion: only SW double conversion supported\n"); + goto out; + } else { + /* Read the converted RAW data 2 */ + ret = abx500_get_register_interruptible(gpadc->dev, + AB8500_GPADC, AB8540_GPADC_MANDATA2L_REG, + &low_data2); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc_conversion: read sw low data 2 failed\n"); + goto out; + } + + ret = abx500_get_register_interruptible(gpadc->dev, + AB8500_GPADC, AB8540_GPADC_MANDATA2H_REG, + &high_data2); + if (ret < 0) { + dev_err(gpadc->dev, + "gpadc_conversion: read sw high data 2 failed\n"); + goto out; + } + if (ibat != NULL) { + *ibat = (high_data2 << 8) | low_data2; + } else { + dev_warn(gpadc->dev, + "gpadc_conversion: ibat not stored\n"); + } + + } + } + + /* Disable GPADC */ + ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, + AB8500_GPADC_CTRL1_REG, AB8500_GPADC_CTRL1_DISABLE); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); + goto out; + } + + /* This eventually drops the regulator */ + pm_runtime_mark_last_busy(gpadc->dev); + pm_runtime_put_autosuspend(gpadc->dev); + + return (high_data << 8) | low_data; + +out: + /* + * It has shown to be needed to turn off the GPADC if an error occurs, + * otherwise we might have problem when waiting for the busy bit in the + * GPADC status register to go low. In V1.1 there wait_for_completion + * seems to timeout when waiting for an interrupt.. Not seen in V2.0 + */ + (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, + AB8500_GPADC_CTRL1_REG, AB8500_GPADC_CTRL1_DISABLE); + pm_runtime_put(gpadc->dev); + dev_err(gpadc->dev, + "gpadc_conversion: Failed to AD convert channel %d\n", ch->id); + + return ret; +} + +/** + * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion + * @irq: irq number + * @data: pointer to the data passed during request irq + * + * This is a interrupt service routine for gpadc conversion completion. + * Notifies the gpadc completion is completed and the converted raw value + * can be read from the registers. + * Returns IRQ status(IRQ_HANDLED) + */ +static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *data) +{ + struct ab8500_gpadc *gpadc = data; + + complete(&gpadc->complete); + + return IRQ_HANDLED; +} + +static int otp_cal_regs[] = { + AB8500_GPADC_CAL_1, + AB8500_GPADC_CAL_2, + AB8500_GPADC_CAL_3, + AB8500_GPADC_CAL_4, + AB8500_GPADC_CAL_5, + AB8500_GPADC_CAL_6, + AB8500_GPADC_CAL_7, +}; + +static int otp4_cal_regs[] = { + AB8540_GPADC_OTP4_REG_7, + AB8540_GPADC_OTP4_REG_6, + AB8540_GPADC_OTP4_REG_5, +}; + +static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) +{ + int i; + int ret[ARRAY_SIZE(otp_cal_regs)]; + u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)]; + int ret_otp4[ARRAY_SIZE(otp4_cal_regs)]; + u8 gpadc_otp4[ARRAY_SIZE(otp4_cal_regs)]; + int vmain_high, vmain_low; + int btemp_high, btemp_low; + int vbat_high, vbat_low; + int ibat_high, ibat_low; + s64 V_gain, V_offset, V2A_gain, V2A_offset; + + /* First we read all OTP registers and store the error code */ + for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) { + ret[i] = abx500_get_register_interruptible(gpadc->dev, + AB8500_OTP_EMUL, otp_cal_regs[i], &gpadc_cal[i]); + if (ret[i] < 0) { + /* Continue anyway: maybe the other registers are OK */ + dev_err(gpadc->dev, "%s: read otp reg 0x%02x failed\n", + __func__, otp_cal_regs[i]); + } else { + /* Put this in the entropy pool as device-unique */ + add_device_randomness(&ret[i], sizeof(ret[i])); + } + } + + /* + * The ADC calibration data is stored in OTP registers. + * The layout of the calibration data is outlined below and a more + * detailed description can be found in UM0836 + * + * vm_h/l = vmain_high/low + * bt_h/l = btemp_high/low + * vb_h/l = vbat_high/low + * + * Data bits 8500/9540: + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | | vm_h9 | vm_h8 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | + * |.......|.......|.......|.......|.......|.......|.......|....... + * + * Data bits 8540: + * OTP2 + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | + * |.......|.......|.......|.......|.......|.......|.......|....... + * | vm_h9 | vm_h8 | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | + * |.......|.......|.......|.......|.......|.......|.......|....... + * + * Data bits 8540: + * OTP4 + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | | ib_h9 | ib_h8 | ib_h7 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | ib_h6 | ib_h5 | ib_h4 | ib_h3 | ib_h2 | ib_h1 | ib_h0 | ib_l5 + * |.......|.......|.......|.......|.......|.......|.......|....... + * | ib_l4 | ib_l3 | ib_l2 | ib_l1 | ib_l0 | + * + * + * Ideal output ADC codes corresponding to injected input voltages + * during manufacturing is: + * + * vmain_high: Vin = 19500mV / ADC ideal code = 997 + * vmain_low: Vin = 315mV / ADC ideal code = 16 + * btemp_high: Vin = 1300mV / ADC ideal code = 985 + * btemp_low: Vin = 21mV / ADC ideal code = 16 + * vbat_high: Vin = 4700mV / ADC ideal code = 982 + * vbat_low: Vin = 2380mV / ADC ideal code = 33 + */ + + if (is_ab8540(gpadc->ab8500)) { + /* Calculate gain and offset for VMAIN if all reads succeeded*/ + if (!(ret[1] < 0 || ret[2] < 0)) { + vmain_high = (((gpadc_cal[1] & 0xFF) << 2) | + ((gpadc_cal[2] & 0xC0) >> 6)); + vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); + + gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_hi = + (u16)vmain_high; + gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_lo = + (u16)vmain_low; + + gpadc->cal_data[AB8500_CAL_VMAIN].gain = AB8500_GPADC_CALIB_SCALE * + (19500 - 315) / (vmain_high - vmain_low); + gpadc->cal_data[AB8500_CAL_VMAIN].offset = AB8500_GPADC_CALIB_SCALE * + 19500 - (AB8500_GPADC_CALIB_SCALE * (19500 - 315) / + (vmain_high - vmain_low)) * vmain_high; + } else { + gpadc->cal_data[AB8500_CAL_VMAIN].gain = 0; + } + + /* Read IBAT calibration Data */ + for (i = 0; i < ARRAY_SIZE(otp4_cal_regs); i++) { + ret_otp4[i] = abx500_get_register_interruptible( + gpadc->dev, AB8500_OTP_EMUL, + otp4_cal_regs[i], &gpadc_otp4[i]); + if (ret_otp4[i] < 0) + dev_err(gpadc->dev, + "%s: read otp4 reg 0x%02x failed\n", + __func__, otp4_cal_regs[i]); + } + + /* Calculate gain and offset for IBAT if all reads succeeded */ + if (!(ret_otp4[0] < 0 || ret_otp4[1] < 0 || ret_otp4[2] < 0)) { + ibat_high = (((gpadc_otp4[0] & 0x07) << 7) | + ((gpadc_otp4[1] & 0xFE) >> 1)); + ibat_low = (((gpadc_otp4[1] & 0x01) << 5) | + ((gpadc_otp4[2] & 0xF8) >> 3)); + + gpadc->cal_data[AB8500_CAL_IBAT].otp_calib_hi = + (u16)ibat_high; + gpadc->cal_data[AB8500_CAL_IBAT].otp_calib_lo = + (u16)ibat_low; + + V_gain = ((AB8500_GPADC_IBAT_VDROP_H - AB8500_GPADC_IBAT_VDROP_L) + << AB8500_GPADC_CALIB_SHIFT_IBAT) / (ibat_high - ibat_low); + + V_offset = (AB8500_GPADC_IBAT_VDROP_H << AB8500_GPADC_CALIB_SHIFT_IBAT) - + (((AB8500_GPADC_IBAT_VDROP_H - AB8500_GPADC_IBAT_VDROP_L) << + AB8500_GPADC_CALIB_SHIFT_IBAT) / (ibat_high - ibat_low)) + * ibat_high; + /* + * Result obtained is in mV (at a scale factor), + * we need to calculate gain and offset to get mA + */ + V2A_gain = (AB8500_ADC_CH_IBAT_MAX - AB8500_ADC_CH_IBAT_MIN)/ + (AB8500_ADC_CH_IBAT_MAX_V - AB8500_ADC_CH_IBAT_MIN_V); + V2A_offset = ((AB8500_ADC_CH_IBAT_MAX_V * AB8500_ADC_CH_IBAT_MIN - + AB8500_ADC_CH_IBAT_MAX * AB8500_ADC_CH_IBAT_MIN_V) + << AB8500_GPADC_CALIB_SHIFT_IBAT) + / (AB8500_ADC_CH_IBAT_MAX_V - AB8500_ADC_CH_IBAT_MIN_V); + + gpadc->cal_data[AB8500_CAL_IBAT].gain = + V_gain * V2A_gain; + gpadc->cal_data[AB8500_CAL_IBAT].offset = + V_offset * V2A_gain + V2A_offset; + } else { + gpadc->cal_data[AB8500_CAL_IBAT].gain = 0; + } + } else { + /* Calculate gain and offset for VMAIN if all reads succeeded */ + if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) { + vmain_high = (((gpadc_cal[0] & 0x03) << 8) | + ((gpadc_cal[1] & 0x3F) << 2) | + ((gpadc_cal[2] & 0xC0) >> 6)); + vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); + + gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_hi = + (u16)vmain_high; + gpadc->cal_data[AB8500_CAL_VMAIN].otp_calib_lo = + (u16)vmain_low; + + gpadc->cal_data[AB8500_CAL_VMAIN].gain = AB8500_GPADC_CALIB_SCALE * + (19500 - 315) / (vmain_high - vmain_low); + + gpadc->cal_data[AB8500_CAL_VMAIN].offset = AB8500_GPADC_CALIB_SCALE * + 19500 - (AB8500_GPADC_CALIB_SCALE * (19500 - 315) / + (vmain_high - vmain_low)) * vmain_high; + } else { + gpadc->cal_data[AB8500_CAL_VMAIN].gain = 0; + } + } + + /* Calculate gain and offset for BTEMP if all reads succeeded */ + if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) { + btemp_high = (((gpadc_cal[2] & 0x01) << 9) | + (gpadc_cal[3] << 1) | ((gpadc_cal[4] & 0x80) >> 7)); + btemp_low = ((gpadc_cal[4] & 0x7C) >> 2); + + gpadc->cal_data[AB8500_CAL_BTEMP].otp_calib_hi = (u16)btemp_high; + gpadc->cal_data[AB8500_CAL_BTEMP].otp_calib_lo = (u16)btemp_low; + + gpadc->cal_data[AB8500_CAL_BTEMP].gain = + AB8500_GPADC_CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low); + gpadc->cal_data[AB8500_CAL_BTEMP].offset = AB8500_GPADC_CALIB_SCALE * 1300 - + (AB8500_GPADC_CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low)) + * btemp_high; + } else { + gpadc->cal_data[AB8500_CAL_BTEMP].gain = 0; + } + + /* Calculate gain and offset for VBAT if all reads succeeded */ + if (!(ret[4] < 0 || ret[5] < 0 || ret[6] < 0)) { + vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]); + vbat_low = ((gpadc_cal[6] & 0xFC) >> 2); + + gpadc->cal_data[AB8500_CAL_VBAT].otp_calib_hi = (u16)vbat_high; + gpadc->cal_data[AB8500_CAL_VBAT].otp_calib_lo = (u16)vbat_low; + + gpadc->cal_data[AB8500_CAL_VBAT].gain = AB8500_GPADC_CALIB_SCALE * + (4700 - 2380) / (vbat_high - vbat_low); + gpadc->cal_data[AB8500_CAL_VBAT].offset = AB8500_GPADC_CALIB_SCALE * 4700 - + (AB8500_GPADC_CALIB_SCALE * (4700 - 2380) / + (vbat_high - vbat_low)) * vbat_high; + } else { + gpadc->cal_data[AB8500_CAL_VBAT].gain = 0; + } +} + +static int ab8500_gpadc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); + const struct ab8500_gpadc_chan_info *ch; + int raw_val; + int processed; + + ch = ab8500_gpadc_get_channel(gpadc, chan->address); + if (!ch) { + dev_err(gpadc->dev, "no such channel %lu\n", + chan->address); + return -EINVAL; + } + + raw_val = ab8500_gpadc_read(gpadc, ch, NULL); + if (raw_val < 0) + return raw_val; + + if (mask == IIO_CHAN_INFO_RAW) { + *val = raw_val; + return IIO_VAL_INT; + } + + if (mask == IIO_CHAN_INFO_PROCESSED) { + processed = ab8500_gpadc_ad_to_voltage(gpadc, ch->id, raw_val); + if (processed < 0) + return processed; + + /* Return millivolt or milliamps or millicentigrades */ + *val = processed * 1000; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static int ab8500_gpadc_of_xlate(struct iio_dev *indio_dev, + const struct of_phandle_args *iiospec) +{ + int i; + + for (i = 0; i < indio_dev->num_channels; i++) + if (indio_dev->channels[i].channel == iiospec->args[0]) + return i; + + return -EINVAL; +} + +static const struct iio_info ab8500_gpadc_info = { + .of_xlate = ab8500_gpadc_of_xlate, + .read_raw = ab8500_gpadc_read_raw, +}; + +#ifdef CONFIG_PM +static int ab8500_gpadc_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); + + regulator_disable(gpadc->vddadc); + + return 0; +} + +static int ab8500_gpadc_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(gpadc->vddadc); + if (ret) + dev_err(dev, "Failed to enable vddadc: %d\n", ret); + + return ret; +} +#endif + +/** + * ab8500_gpadc_parse_channel() - process devicetree channel configuration + * @dev: pointer to containing device + * @np: device tree node for the channel to configure + * @ch: channel info to fill in + * @iio_chan: IIO channel specification to fill in + * + * The devicetree will set up the channel for use with the specific device, + * and define usage for things like AUX GPADC inputs more precisely. + */ +static int ab8500_gpadc_parse_channel(struct device *dev, + struct device_node *np, + struct ab8500_gpadc_chan_info *ch, + struct iio_chan_spec *iio_chan) +{ + const char *name = np->name; + u32 chan; + int ret; + + ret = of_property_read_u32(np, "reg", &chan); + if (ret) { + dev_err(dev, "invalid channel number %s\n", name); + return ret; + } + if (chan > AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT) { + dev_err(dev, "%s channel number out of range %d\n", name, chan); + return -EINVAL; + } + + iio_chan->channel = chan; + iio_chan->datasheet_name = name; + iio_chan->indexed = 1; + iio_chan->address = chan; + iio_chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_PROCESSED); + /* Most are voltages (also temperatures), some are currents */ + if ((chan == AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT) || + (chan == AB8500_GPADC_CHAN_USB_CHARGER_CURRENT)) + iio_chan->type = IIO_CURRENT; + else + iio_chan->type = IIO_VOLTAGE; + + ch->id = chan; + + /* Sensible defaults */ + ch->avg_sample = 16; + ch->hardware_control = false; + ch->falling_edge = false; + ch->trig_timer = 0; + + return 0; +} + +/** + * ab8500_gpadc_parse_channels() - Parse the GPADC channels from DT + * @gpadc: the GPADC to configure the channels for + * @np: device tree node containing the channel configurations + * @chans: the IIO channels we parsed + * @nchans: the number of IIO channels we parsed + */ +static int ab8500_gpadc_parse_channels(struct ab8500_gpadc *gpadc, + struct device_node *np, + struct iio_chan_spec **chans_parsed, + unsigned int *nchans_parsed) +{ + struct device_node *child; + struct ab8500_gpadc_chan_info *ch; + struct iio_chan_spec *iio_chans; + unsigned int nchans; + int i; + + nchans = of_get_available_child_count(np); + if (!nchans) { + dev_err(gpadc->dev, "no channel children\n"); + return -ENODEV; + } + dev_info(gpadc->dev, "found %d ADC channels\n", nchans); + + iio_chans = devm_kcalloc(gpadc->dev, nchans, + sizeof(*iio_chans), GFP_KERNEL); + if (!iio_chans) + return -ENOMEM; + + gpadc->chans = devm_kcalloc(gpadc->dev, nchans, + sizeof(*gpadc->chans), GFP_KERNEL); + if (!gpadc->chans) + return -ENOMEM; + + i = 0; + for_each_available_child_of_node(np, child) { + struct iio_chan_spec *iio_chan; + int ret; + + ch = &gpadc->chans[i]; + iio_chan = &iio_chans[i]; + + ret = ab8500_gpadc_parse_channel(gpadc->dev, child, ch, + iio_chan); + if (ret) { + of_node_put(child); + return ret; + } + i++; + } + gpadc->nchans = nchans; + *chans_parsed = iio_chans; + *nchans_parsed = nchans; + + return 0; +} + +static int ab8500_gpadc_probe(struct platform_device *pdev) +{ + struct ab8500_gpadc *gpadc; + struct iio_dev *indio_dev; + struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; + struct iio_chan_spec *iio_chans; + unsigned int n_iio_chans; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc)); + if (!indio_dev) + return -ENOMEM; + + platform_set_drvdata(pdev, indio_dev); + gpadc = iio_priv(indio_dev); + + gpadc->dev = dev; + gpadc->ab8500 = dev_get_drvdata(dev->parent); + + ret = ab8500_gpadc_parse_channels(gpadc, np, &iio_chans, &n_iio_chans); + if (ret) + return ret; + + gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END"); + if (gpadc->irq_sw < 0) { + dev_err(dev, "failed to get platform sw_conv_end irq\n"); + return gpadc->irq_sw; + } + + gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END"); + if (gpadc->irq_hw < 0) { + dev_err(dev, "failed to get platform hw_conv_end irq\n"); + return gpadc->irq_hw; + } + + /* Initialize completion used to notify completion of conversion */ + init_completion(&gpadc->complete); + + /* Request interrupts */ + ret = devm_request_threaded_irq(dev, gpadc->irq_sw, NULL, + ab8500_bm_gpadcconvend_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT, + "ab8500-gpadc-sw", gpadc); + if (ret < 0) { + dev_err(dev, + "failed to request sw conversion irq %d\n", + gpadc->irq_sw); + return ret; + } + + ret = devm_request_threaded_irq(dev, gpadc->irq_hw, NULL, + ab8500_bm_gpadcconvend_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT, + "ab8500-gpadc-hw", gpadc); + if (ret < 0) { + dev_err(dev, + "Failed to request hw conversion irq: %d\n", + gpadc->irq_hw); + return ret; + } + + /* The VTVout LDO used to power the AB8500 GPADC */ + gpadc->vddadc = devm_regulator_get(dev, "vddadc"); + if (IS_ERR(gpadc->vddadc)) { + ret = PTR_ERR(gpadc->vddadc); + dev_err(dev, "failed to get vddadc\n"); + return ret; + } + + ret = regulator_enable(gpadc->vddadc); + if (ret) { + dev_err(dev, "failed to enable vddadc: %d\n", ret); + return ret; + } + + /* Enable runtime PM */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, AB8500_GPADC_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(dev); + + ab8500_gpadc_read_calibration_data(gpadc); + + pm_runtime_put(dev); + + indio_dev->dev.parent = dev; + indio_dev->dev.of_node = np; + indio_dev->name = "ab8500-gpadc"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &ab8500_gpadc_info; + indio_dev->channels = iio_chans; + indio_dev->num_channels = n_iio_chans; + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + goto out_dis_pm; + + return 0; + +out_dis_pm: + pm_runtime_get_sync(dev); + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + regulator_disable(gpadc->vddadc); + + return ret; +} + +static int ab8500_gpadc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); + + pm_runtime_get_sync(gpadc->dev); + pm_runtime_put_noidle(gpadc->dev); + pm_runtime_disable(gpadc->dev); + regulator_disable(gpadc->vddadc); + + return 0; +} + +static const struct dev_pm_ops ab8500_gpadc_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, + ab8500_gpadc_runtime_resume, + NULL) +}; + +static struct platform_driver ab8500_gpadc_driver = { + .probe = ab8500_gpadc_probe, + .remove = ab8500_gpadc_remove, + .driver = { + .name = "ab8500-gpadc", + .pm = &ab8500_gpadc_pm_ops, + }, +}; +builtin_platform_driver(ab8500_gpadc_driver); diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c new file mode 100644 index 000000000000..33c40357bd5e --- /dev/null +++ b/drivers/iio/adc/ad7091r-base.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7091RX Analog to Digital converter driver + * + * Copyright 2014-2019 Analog Devices Inc. + */ + +#include <linux/bitops.h> +#include <linux/iio/events.h> +#include <linux/iio/iio.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> + +#include "ad7091r-base.h" + +#define AD7091R_REG_RESULT 0 +#define AD7091R_REG_CHANNEL 1 +#define AD7091R_REG_CONF 2 +#define AD7091R_REG_ALERT 3 +#define AD7091R_REG_CH_LOW_LIMIT(ch) ((ch) * 3 + 4) +#define AD7091R_REG_CH_HIGH_LIMIT(ch) ((ch) * 3 + 5) +#define AD7091R_REG_CH_HYSTERESIS(ch) ((ch) * 3 + 6) + +/* AD7091R_REG_RESULT */ +#define AD7091R_REG_RESULT_CH_ID(x) (((x) >> 13) & 0x3) +#define AD7091R_REG_RESULT_CONV_RESULT(x) ((x) & 0xfff) + +/* AD7091R_REG_CONF */ +#define AD7091R_REG_CONF_AUTO BIT(8) +#define AD7091R_REG_CONF_CMD BIT(10) + +#define AD7091R_REG_CONF_MODE_MASK \ + (AD7091R_REG_CONF_AUTO | AD7091R_REG_CONF_CMD) + +enum ad7091r_mode { + AD7091R_MODE_SAMPLE, + AD7091R_MODE_COMMAND, + AD7091R_MODE_AUTOCYCLE, +}; + +struct ad7091r_state { + struct device *dev; + struct regmap *map; + struct regulator *vref; + const struct ad7091r_chip_info *chip_info; + enum ad7091r_mode mode; + struct mutex lock; /*lock to prevent concurent reads */ +}; + +static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode) +{ + int ret, conf; + + switch (mode) { + case AD7091R_MODE_SAMPLE: + conf = 0; + break; + case AD7091R_MODE_COMMAND: + conf = AD7091R_REG_CONF_CMD; + break; + case AD7091R_MODE_AUTOCYCLE: + conf = AD7091R_REG_CONF_AUTO; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(st->map, AD7091R_REG_CONF, + AD7091R_REG_CONF_MODE_MASK, conf); + if (ret) + return ret; + + st->mode = mode; + + return 0; +} + +static int ad7091r_set_channel(struct ad7091r_state *st, unsigned int channel) +{ + unsigned int dummy; + int ret; + + /* AD7091R_REG_CHANNEL specified which channels to be converted */ + ret = regmap_write(st->map, AD7091R_REG_CHANNEL, + BIT(channel) | (BIT(channel) << 8)); + if (ret) + return ret; + + /* + * There is a latency of one conversion before the channel conversion + * sequence is updated + */ + return regmap_read(st->map, AD7091R_REG_RESULT, &dummy); +} + +static int ad7091r_read_one(struct iio_dev *iio_dev, + unsigned int channel, unsigned int *read_val) +{ + struct ad7091r_state *st = iio_priv(iio_dev); + unsigned int val; + int ret; + + ret = ad7091r_set_channel(st, channel); + if (ret) + return ret; + + ret = regmap_read(st->map, AD7091R_REG_RESULT, &val); + if (ret) + return ret; + + if (AD7091R_REG_RESULT_CH_ID(val) != channel) + return -EIO; + + *read_val = AD7091R_REG_RESULT_CONV_RESULT(val); + + return 0; +} + +static int ad7091r_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct ad7091r_state *st = iio_priv(iio_dev); + unsigned int read_val; + int ret; + + mutex_lock(&st->lock); + + switch (m) { + case IIO_CHAN_INFO_RAW: + if (st->mode != AD7091R_MODE_COMMAND) { + ret = -EBUSY; + goto unlock; + } + + ret = ad7091r_read_one(iio_dev, chan->channel, &read_val); + if (ret) + goto unlock; + + *val = read_val; + ret = IIO_VAL_INT; + break; + + case IIO_CHAN_INFO_SCALE: + if (st->vref) { + ret = regulator_get_voltage(st->vref); + if (ret < 0) + goto unlock; + + *val = ret / 1000; + } else { + *val = st->chip_info->vref_mV; + } + + *val2 = chan->scan_type.realbits; + ret = IIO_VAL_FRACTIONAL_LOG2; + break; + + default: + ret = -EINVAL; + break; + } + +unlock: + mutex_unlock(&st->lock); + return ret; +} + +static const struct iio_info ad7091r_info = { + .read_raw = ad7091r_read_raw, +}; + +static irqreturn_t ad7091r_event_handler(int irq, void *private) +{ + struct ad7091r_state *st = (struct ad7091r_state *) private; + struct iio_dev *iio_dev = dev_get_drvdata(st->dev); + unsigned int i, read_val; + int ret; + s64 timestamp = iio_get_time_ns(iio_dev); + + ret = regmap_read(st->map, AD7091R_REG_ALERT, &read_val); + if (ret) + return IRQ_HANDLED; + + for (i = 0; i < st->chip_info->num_channels; i++) { + if (read_val & BIT(i * 2)) + iio_push_event(iio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), timestamp); + if (read_val & BIT(i * 2 + 1)) + iio_push_event(iio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), timestamp); + } + + return IRQ_HANDLED; +} + +static void ad7091r_remove(void *data) +{ + struct ad7091r_state *st = data; + + regulator_disable(st->vref); +} + +int ad7091r_probe(struct device *dev, const char *name, + const struct ad7091r_chip_info *chip_info, + struct regmap *map, int irq) +{ + struct iio_dev *iio_dev; + struct ad7091r_state *st; + int ret; + + iio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!iio_dev) + return -ENOMEM; + + st = iio_priv(iio_dev); + st->dev = dev; + st->chip_info = chip_info; + st->map = map; + + iio_dev->dev.parent = dev; + iio_dev->name = name; + iio_dev->info = &ad7091r_info; + iio_dev->modes = INDIO_DIRECT_MODE; + + iio_dev->num_channels = chip_info->num_channels; + iio_dev->channels = chip_info->channels; + + if (irq) { + ret = devm_request_threaded_irq(dev, irq, NULL, + ad7091r_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, st); + if (ret) + return ret; + } + + st->vref = devm_regulator_get_optional(dev, "vref"); + if (IS_ERR(st->vref)) { + if (PTR_ERR(st->vref) == -EPROBE_DEFER) + return -EPROBE_DEFER; + st->vref = NULL; + } else { + ret = regulator_enable(st->vref); + if (ret) + return ret; + ret = devm_add_action_or_reset(dev, ad7091r_remove, st); + if (ret) + return ret; + } + + /* Use command mode by default to convert only desired channels*/ + ret = ad7091r_set_mode(st, AD7091R_MODE_COMMAND); + if (ret) + return ret; + + return devm_iio_device_register(dev, iio_dev); +} +EXPORT_SYMBOL_GPL(ad7091r_probe); + +static bool ad7091r_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AD7091R_REG_RESULT: + case AD7091R_REG_ALERT: + return false; + default: + return true; + } +} + +static bool ad7091r_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AD7091R_REG_RESULT: + case AD7091R_REG_ALERT: + return true; + default: + return false; + } +} + +const struct regmap_config ad7091r_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .writeable_reg = ad7091r_writeable_reg, + .volatile_reg = ad7091r_volatile_reg, +}; +EXPORT_SYMBOL_GPL(ad7091r_regmap_config); + +MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>"); +MODULE_DESCRIPTION("Analog Devices AD7091Rx multi-channel converters"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h new file mode 100644 index 000000000000..509748aef9b1 --- /dev/null +++ b/drivers/iio/adc/ad7091r-base.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * AD7091RX Analog to Digital converter driver + * + * Copyright 2014-2019 Analog Devices Inc. + */ + +#ifndef __DRIVERS_IIO_ADC_AD7091R_BASE_H__ +#define __DRIVERS_IIO_ADC_AD7091R_BASE_H__ + +struct device; +struct ad7091r_state; + +struct ad7091r_chip_info { + unsigned int num_channels; + const struct iio_chan_spec *channels; + unsigned int vref_mV; +}; + +extern const struct regmap_config ad7091r_regmap_config; + +int ad7091r_probe(struct device *dev, const char *name, + const struct ad7091r_chip_info *chip_info, + struct regmap *map, int irq); + +#endif /* __DRIVERS_IIO_ADC_AD7091R_BASE_H__ */ diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c new file mode 100644 index 000000000000..9665679c3ea6 --- /dev/null +++ b/drivers/iio/adc/ad7091r5.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7091R5 Analog to Digital converter driver + * + * Copyright 2014-2019 Analog Devices Inc. + */ + +#include <linux/i2c.h> +#include <linux/iio/iio.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#include "ad7091r-base.h" + +static const struct iio_event_spec ad7091r5_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) | + BIT(IIO_EV_INFO_ENABLE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), + }, +}; + +#define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \ + .type = IIO_VOLTAGE, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .indexed = 1, \ + .channel = idx, \ + .event_spec = ev, \ + .num_event_specs = num_ev, \ + .scan_type.storagebits = 16, \ + .scan_type.realbits = bits, \ +} +static const struct iio_chan_spec ad7091r5_channels_irq[] = { + AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), + AD7091R_CHANNEL(1, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), + AD7091R_CHANNEL(2, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), + AD7091R_CHANNEL(3, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), +}; + +static const struct iio_chan_spec ad7091r5_channels_noirq[] = { + AD7091R_CHANNEL(0, 12, NULL, 0), + AD7091R_CHANNEL(1, 12, NULL, 0), + AD7091R_CHANNEL(2, 12, NULL, 0), + AD7091R_CHANNEL(3, 12, NULL, 0), +}; + +static const struct ad7091r_chip_info ad7091r5_chip_info_irq = { + .channels = ad7091r5_channels_irq, + .num_channels = ARRAY_SIZE(ad7091r5_channels_irq), + .vref_mV = 2500, +}; + +static const struct ad7091r_chip_info ad7091r5_chip_info_noirq = { + .channels = ad7091r5_channels_noirq, + .num_channels = ARRAY_SIZE(ad7091r5_channels_noirq), + .vref_mV = 2500, +}; + +static int ad7091r5_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + const struct ad7091r_chip_info *chip_info; + struct regmap *map = devm_regmap_init_i2c(i2c, &ad7091r_regmap_config); + + if (IS_ERR(map)) + return PTR_ERR(map); + + if (i2c->irq) + chip_info = &ad7091r5_chip_info_irq; + else + chip_info = &ad7091r5_chip_info_noirq; + + return ad7091r_probe(&i2c->dev, id->name, chip_info, map, i2c->irq); +} + +static const struct of_device_id ad7091r5_dt_ids[] = { + { .compatible = "adi,ad7091r5" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ad7091r5_dt_ids); + +static const struct i2c_device_id ad7091r5_i2c_ids[] = { + {"ad7091r5", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, ad7091r5_i2c_ids); + +static struct i2c_driver ad7091r5_driver = { + .driver = { + .name = "ad7091r5", + .of_match_table = ad7091r5_dt_ids, + }, + .probe = ad7091r5_i2c_probe, + .id_table = ad7091r5_i2c_ids, +}; +module_i2c_driver(ad7091r5_driver); + +MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>"); +MODULE_DESCRIPTION("Analog Devices AD7091R5 multi-channel ADC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index edc6f1cc90b2..d9915dc71d1e 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -9,6 +9,7 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/regulator/consumer.h> @@ -39,6 +40,8 @@ #define AD7124_STATUS_POR_FLAG_MSK BIT(4) /* AD7124_ADC_CONTROL */ +#define AD7124_ADC_CTRL_REF_EN_MSK BIT(8) +#define AD7124_ADC_CTRL_REF_EN(x) FIELD_PREP(AD7124_ADC_CTRL_REF_EN_MSK, x) #define AD7124_ADC_CTRL_PWR_MSK GENMASK(7, 6) #define AD7124_ADC_CTRL_PWR(x) FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x) #define AD7124_ADC_CTRL_MODE_MSK GENMASK(5, 2) @@ -222,6 +225,7 @@ static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { .addr_shift = 0, .read_mask = BIT(6), .data_reg = AD7124_DATA, + .irq_flags = IRQF_TRIGGER_FALLING, }; static int ad7124_set_channel_odr(struct ad7124_state *st, @@ -424,7 +428,10 @@ static int ad7124_init_channel_vref(struct ad7124_state *st, break; case AD7124_INT_REF: st->channel_config[channel_number].vref_mv = 2500; - break; + st->adc_control &= ~AD7124_ADC_CTRL_REF_EN_MSK; + st->adc_control |= AD7124_ADC_CTRL_REF_EN(1); + return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, + 2, st->adc_control); default: dev_err(&st->sd.spi->dev, "Invalid reference %d\n", refsel); return -EINVAL; @@ -489,13 +496,11 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev, st->channel_config[channel].buf_negative = of_property_read_bool(child, "adi,buffered-negative"); - *chan = ad7124_channel_template; - chan->address = channel; - chan->scan_index = channel; - chan->channel = ain[0]; - chan->channel2 = ain[1]; - - chan++; + chan[channel] = ad7124_channel_template; + chan[channel].address = channel; + chan[channel].scan_index = channel; + chan[channel].channel = ain[0]; + chan[channel].channel2 = ain[1]; } return 0; diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index c31b8eabb894..c8524f098883 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -11,7 +11,7 @@ #include <linux/spi/spi.h> #include <linux/regulator/consumer.h> #include <linux/err.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/interrupt.h> @@ -34,7 +34,7 @@ struct ad7266_state { enum ad7266_range range; enum ad7266_mode mode; bool fixed_addr; - struct gpio gpios[3]; + struct gpio_desc *gpios[3]; /* * DMA (thus cache coherency maintenance) requires the @@ -117,7 +117,7 @@ static void ad7266_select_input(struct ad7266_state *st, unsigned int nr) } for (i = 0; i < 3; ++i) - gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i))); + gpiod_set_value(st->gpios[i], (bool)(nr & BIT(i))); } static int ad7266_update_scan_mode(struct iio_dev *indio_dev, @@ -376,7 +376,7 @@ static void ad7266_init_channels(struct iio_dev *indio_dev) } static const char * const ad7266_gpio_labels[] = { - "AD0", "AD1", "AD2", + "ad0", "ad1", "ad2", }; static int ad7266_probe(struct spi_device *spi) @@ -419,14 +419,14 @@ static int ad7266_probe(struct spi_device *spi) if (!st->fixed_addr) { for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) { - st->gpios[i].gpio = pdata->addr_gpios[i]; - st->gpios[i].flags = GPIOF_OUT_INIT_LOW; - st->gpios[i].label = ad7266_gpio_labels[i]; + st->gpios[i] = devm_gpiod_get(&spi->dev, + ad7266_gpio_labels[i], + GPIOD_OUT_LOW); + if (IS_ERR(st->gpios[i])) { + ret = PTR_ERR(st->gpios[i]); + goto error_disable_reg; + } } - ret = gpio_request_array(st->gpios, - ARRAY_SIZE(st->gpios)); - if (ret) - goto error_disable_reg; } } else { st->fixed_addr = true; @@ -465,7 +465,7 @@ static int ad7266_probe(struct spi_device *spi) ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, &ad7266_trigger_handler, &iio_triggered_buffer_setup_ops); if (ret) - goto error_free_gpios; + goto error_disable_reg; ret = iio_device_register(indio_dev); if (ret) @@ -475,9 +475,6 @@ static int ad7266_probe(struct spi_device *spi) error_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); -error_free_gpios: - if (!st->fixed_addr) - gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); @@ -492,8 +489,6 @@ static int ad7266_remove(struct spi_device *spi) iio_device_unregister(indio_dev); iio_triggered_buffer_cleanup(indio_dev); - if (!st->fixed_addr) - gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); if (!IS_ERR(st->reg)) regulator_disable(st->reg); diff --git a/drivers/iio/adc/ad7292.c b/drivers/iio/adc/ad7292.c new file mode 100644 index 000000000000..a6798f7dfdb8 --- /dev/null +++ b/drivers/iio/adc/ad7292.c @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices AD7292 SPI ADC driver + * + * Copyright 2019 Analog Devices Inc. + */ + +#include <linux/bitfield.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> + +#include <linux/iio/iio.h> + +#define ADI_VENDOR_ID 0x0018 + +/* AD7292 registers definition */ +#define AD7292_REG_VENDOR_ID 0x00 +#define AD7292_REG_CONF_BANK 0x05 +#define AD7292_REG_CONV_COMM 0x0E +#define AD7292_REG_ADC_CH(x) (0x10 + (x)) + +/* AD7292 configuration bank subregisters definition */ +#define AD7292_BANK_REG_VIN_RNG0 0x10 +#define AD7292_BANK_REG_VIN_RNG1 0x11 +#define AD7292_BANK_REG_SAMP_MODE 0x12 + +#define AD7292_RD_FLAG_MSK(x) (BIT(7) | ((x) & 0x3F)) + +/* AD7292_REG_ADC_CONVERSION */ +#define AD7292_ADC_DATA_MASK GENMASK(15, 6) +#define AD7292_ADC_DATA(x) FIELD_GET(AD7292_ADC_DATA_MASK, x) + +/* AD7292_CHANNEL_SAMPLING_MODE */ +#define AD7292_CH_SAMP_MODE(reg, ch) (((reg) >> 8) & BIT(ch)) + +/* AD7292_CHANNEL_VIN_RANGE */ +#define AD7292_CH_VIN_RANGE(reg, ch) ((reg) & BIT(ch)) + +#define AD7292_VOLTAGE_CHAN(_chan) \ +{ \ + .type = IIO_VOLTAGE, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .indexed = 1, \ + .channel = _chan, \ +} + +static const struct iio_chan_spec ad7292_channels[] = { + AD7292_VOLTAGE_CHAN(0), + AD7292_VOLTAGE_CHAN(1), + AD7292_VOLTAGE_CHAN(2), + AD7292_VOLTAGE_CHAN(3), + AD7292_VOLTAGE_CHAN(4), + AD7292_VOLTAGE_CHAN(5), + AD7292_VOLTAGE_CHAN(6), + AD7292_VOLTAGE_CHAN(7) +}; + +static const struct iio_chan_spec ad7292_channels_diff[] = { + { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .indexed = 1, + .differential = 1, + .channel = 0, + .channel2 = 1, + }, + AD7292_VOLTAGE_CHAN(2), + AD7292_VOLTAGE_CHAN(3), + AD7292_VOLTAGE_CHAN(4), + AD7292_VOLTAGE_CHAN(5), + AD7292_VOLTAGE_CHAN(6), + AD7292_VOLTAGE_CHAN(7) +}; + +struct ad7292_state { + struct spi_device *spi; + struct regulator *reg; + unsigned short vref_mv; + + __be16 d16 ____cacheline_aligned; + u8 d8[2]; +}; + +static int ad7292_spi_reg_read(struct ad7292_state *st, unsigned int addr) +{ + int ret; + + st->d8[0] = AD7292_RD_FLAG_MSK(addr); + + ret = spi_write_then_read(st->spi, st->d8, 1, &st->d16, 2); + if (ret < 0) + return ret; + + return be16_to_cpu(st->d16); +} + +static int ad7292_spi_subreg_read(struct ad7292_state *st, unsigned int addr, + unsigned int sub_addr, unsigned int len) +{ + unsigned int shift = 16 - (8 * len); + int ret; + + st->d8[0] = AD7292_RD_FLAG_MSK(addr); + st->d8[1] = sub_addr; + + ret = spi_write_then_read(st->spi, st->d8, 2, &st->d16, len); + if (ret < 0) + return ret; + + return (be16_to_cpu(st->d16) >> shift); +} + +static int ad7292_single_conversion(struct ad7292_state *st, + unsigned int chan_addr) +{ + int ret; + + struct spi_transfer t[] = { + { + .tx_buf = &st->d8, + .len = 4, + .delay_usecs = 6, + }, { + .rx_buf = &st->d16, + .len = 2, + }, + }; + + st->d8[0] = chan_addr; + st->d8[1] = AD7292_RD_FLAG_MSK(AD7292_REG_CONV_COMM); + + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); + + if (ret < 0) + return ret; + + return be16_to_cpu(st->d16); +} + +static int ad7292_vin_range_multiplier(struct ad7292_state *st, int channel) +{ + int samp_mode, range0, range1, factor = 1; + + /* + * Every AD7292 ADC channel may have its input range adjusted according + * to the settings at the ADC sampling mode and VIN range subregisters. + * For a given channel, the minimum input range is equal to Vref, and it + * may be increased by a multiplier factor of 2 or 4 according to the + * following rule: + * If channel is being sampled with respect to AGND: + * factor = 4 if VIN range0 and VIN range1 equal 0 + * factor = 2 if only one of VIN ranges equal 1 + * factor = 1 if both VIN range0 and VIN range1 equal 1 + * If channel is being sampled with respect to AVDD: + * factor = 4 if VIN range0 and VIN range1 equal 0 + * Behavior is undefined if any of VIN range doesn't equal 0 + */ + + samp_mode = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK, + AD7292_BANK_REG_SAMP_MODE, 2); + + if (samp_mode < 0) + return samp_mode; + + range0 = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK, + AD7292_BANK_REG_VIN_RNG0, 2); + + if (range0 < 0) + return range0; + + range1 = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK, + AD7292_BANK_REG_VIN_RNG1, 2); + + if (range1 < 0) + return range1; + + if (AD7292_CH_SAMP_MODE(samp_mode, channel)) { + /* Sampling with respect to AGND */ + if (!AD7292_CH_VIN_RANGE(range0, channel)) + factor *= 2; + + if (!AD7292_CH_VIN_RANGE(range1, channel)) + factor *= 2; + + } else { + /* Sampling with respect to AVDD */ + if (AD7292_CH_VIN_RANGE(range0, channel) || + AD7292_CH_VIN_RANGE(range1, channel)) + return -EPERM; + + factor = 4; + } + + return factor; +} + +static int ad7292_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long info) +{ + struct ad7292_state *st = iio_priv(indio_dev); + unsigned int ch_addr; + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: + ch_addr = AD7292_REG_ADC_CH(chan->channel); + ret = ad7292_single_conversion(st, ch_addr); + if (ret < 0) + return ret; + + *val = AD7292_ADC_DATA(ret); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* + * To convert a raw value to standard units, the IIO defines + * this formula: Scaled value = (raw + offset) * scale. + * For the scale to be a correct multiplier for (raw + offset), + * it must be calculated as the input range divided by the + * number of possible distinct input values. Given the ADC data + * is 10 bit long, it may assume 2^10 distinct values. + * Hence, scale = range / 2^10. The IIO_VAL_FRACTIONAL_LOG2 + * return type indicates to the IIO API to divide *val by 2 to + * the power of *val2 when returning from read_raw. + */ + + ret = ad7292_vin_range_multiplier(st, chan->channel); + if (ret < 0) + return ret; + + *val = st->vref_mv * ret; + *val2 = 10; + return IIO_VAL_FRACTIONAL_LOG2; + default: + break; + } + return -EINVAL; +} + +static const struct iio_info ad7292_info = { + .read_raw = ad7292_read_raw, +}; + +static void ad7292_regulator_disable(void *data) +{ + struct ad7292_state *st = data; + + regulator_disable(st->reg); +} + +static int ad7292_probe(struct spi_device *spi) +{ + struct ad7292_state *st; + struct iio_dev *indio_dev; + struct device_node *child; + bool diff_channels = 0; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->spi = spi; + + ret = ad7292_spi_reg_read(st, AD7292_REG_VENDOR_ID); + if (ret != ADI_VENDOR_ID) { + dev_err(&spi->dev, "Wrong vendor id 0x%x\n", ret); + return -EINVAL; + } + + spi_set_drvdata(spi, indio_dev); + + st->reg = devm_regulator_get_optional(&spi->dev, "vref"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) { + dev_err(&spi->dev, + "Failed to enable external vref supply\n"); + return ret; + } + + ret = devm_add_action_or_reset(&spi->dev, + ad7292_regulator_disable, st); + if (ret) { + regulator_disable(st->reg); + return ret; + } + + ret = regulator_get_voltage(st->reg); + if (ret < 0) + return ret; + + st->vref_mv = ret / 1000; + } else { + /* Use the internal voltage reference. */ + st->vref_mv = 1250; + } + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &ad7292_info; + + for_each_available_child_of_node(spi->dev.of_node, child) { + diff_channels = of_property_read_bool(child, "diff-channels"); + if (diff_channels) + break; + } + + if (diff_channels) { + indio_dev->num_channels = ARRAY_SIZE(ad7292_channels_diff); + indio_dev->channels = ad7292_channels_diff; + } else { + indio_dev->num_channels = ARRAY_SIZE(ad7292_channels); + indio_dev->channels = ad7292_channels; + } + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct spi_device_id ad7292_id_table[] = { + { "ad7292", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, ad7292_id_table); + +static const struct of_device_id ad7292_of_match[] = { + { .compatible = "adi,ad7292" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7292_of_match); + +static struct spi_driver ad7292_driver = { + .driver = { + .name = "ad7292", + .of_match_table = ad7292_of_match, + }, + .probe = ad7292_probe, + .id_table = ad7292_id_table, +}; +module_spi_driver(ad7292_driver); + +MODULE_AUTHOR("Marcelo Schmitt <marcelo.schmitt1@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices AD7292 ADC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index aba0fd123a51..e4683a68522a 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -35,6 +35,11 @@ static const unsigned int ad7606_scale_avail[2] = { 152588, 305176 }; + +static const unsigned int ad7616_sw_scale_avail[3] = { + 76293, 152588, 305176 +}; + static const unsigned int ad7606_oversampling_avail[7] = { 1, 2, 4, 8, 16, 32, 64, }; @@ -55,9 +60,32 @@ static int ad7606_reset(struct ad7606_state *st) return -ENODEV; } +static int ad7606_reg_access(struct iio_dev *indio_dev, + unsigned int reg, + unsigned int writeval, + unsigned int *readval) +{ + struct ad7606_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + if (readval) { + ret = st->bops->reg_read(st, reg); + if (ret < 0) + goto err_unlock; + *readval = ret; + ret = 0; + } else { + ret = st->bops->reg_write(st, reg, writeval); + } +err_unlock: + mutex_unlock(&st->lock); + return ret; +} + static int ad7606_read_samples(struct ad7606_state *st) { - unsigned int num = st->chip_info->num_channels; + unsigned int num = st->chip_info->num_channels - 1; u16 *data = st->data; int ret; @@ -308,29 +336,6 @@ static const struct attribute_group ad7606_attribute_group_range = { .attrs = ad7606_attributes_range, }; -#define AD760X_CHANNEL(num, mask) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = num, \ - .address = num, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ - .info_mask_shared_by_all = mask, \ - .scan_index = num, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ - .endianness = IIO_CPU, \ - }, \ -} - -#define AD7605_CHANNEL(num) \ - AD760X_CHANNEL(num, 0) - -#define AD7606_CHANNEL(num) \ - AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) - static const struct iio_chan_spec ad7605_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(4), AD7605_CHANNEL(0), @@ -405,12 +410,19 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), }, + [ID_AD7606B] = { + .channels = ad7606_channels, + .num_channels = 9, + .oversampling_avail = ad7606_oversampling_avail, + .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), + }, [ID_AD7616] = { .channels = ad7616_channels, .num_channels = 17, .oversampling_avail = ad7616_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), .os_req_reset = true, + .init_delay_ms = 15, }, }; @@ -519,6 +531,14 @@ static const struct iio_info ad7606_info_os_and_range = { .validate_trigger = &ad7606_validate_trigger, }; +static const struct iio_info ad7606_info_os_range_and_debug = { + .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, + .debugfs_reg_access = &ad7606_reg_access, + .attrs = &ad7606_attribute_group_os_and_range, + .validate_trigger = &ad7606_validate_trigger, +}; + static const struct iio_info ad7606_info_os = { .read_raw = &ad7606_read_raw, .write_raw = &ad7606_write_raw, @@ -617,35 +637,29 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); + /* AD7616 requires al least 15ms to reconfigure after a reset */ + if (st->chip_info->init_delay_ms) { + if (msleep_interruptible(st->chip_info->init_delay_ms)) + return -ERESTARTSYS; + } + st->write_scale = ad7606_write_scale_hw; st->write_os = ad7606_write_os_hw; - if (st->chip_info->sw_mode_config) + if (st->bops->sw_mode_config) st->sw_mode_en = device_property_present(st->dev, "adi,sw-mode"); if (st->sw_mode_en) { + /* Scale of 0.076293 is only available in sw mode */ + st->scale_avail = ad7616_sw_scale_avail; + st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail); + /* After reset, in software mode, ±10 V is set by default */ memset32(st->range, 2, ARRAY_SIZE(st->range)); - indio_dev->info = &ad7606_info_os_and_range; - - /* - * In software mode, the range gpio has no longer its function. - * Instead, the scale can be configured individually for each - * channel from the range registers. - */ - if (st->chip_info->write_scale_sw) - st->write_scale = st->chip_info->write_scale_sw; - - /* - * In software mode, the oversampling is no longer configured - * with GPIO pins. Instead, the oversampling can be configured - * in configuratiion register. - */ - if (st->chip_info->write_os_sw) - st->write_os = st->chip_info->write_os_sw; - - ret = st->chip_info->sw_mode_config(indio_dev); + indio_dev->info = &ad7606_info_os_range_and_debug; + + ret = st->bops->sw_mode_config(indio_dev); if (ret < 0) return ret; } diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index d8a509c2c428..9350ef1f63b5 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -8,6 +8,36 @@ #ifndef IIO_ADC_AD7606_H_ #define IIO_ADC_AD7606_H_ +#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num, \ + .address = num, \ + .info_mask_separate = mask_sep, \ + .info_mask_shared_by_type = mask_type, \ + .info_mask_shared_by_all = mask_all, \ + .scan_index = num, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +#define AD7605_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ + BIT(IIO_CHAN_INFO_SCALE), 0) + +#define AD7606_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ + BIT(IIO_CHAN_INFO_SCALE), \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) + +#define AD7616_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\ + 0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) + /** * struct ad7606_chip_info - chip specific information * @channels: channel specification @@ -16,12 +46,8 @@ * oversampling ratios. * @oversampling_num number of elements stored in oversampling_avail array * @os_req_reset some devices require a reset to update oversampling - * @write_scale_sw pointer to the function which writes the scale via spi - in software mode - * @write_os_sw pointer to the function which writes the os via spi - in software mode - * @sw_mode_config: pointer to a function which configured the device - * for software mode + * @init_delay_ms required delay in miliseconds for initialization + * after a restart */ struct ad7606_chip_info { const struct iio_chan_spec *channels; @@ -29,9 +55,7 @@ struct ad7606_chip_info { const unsigned int *oversampling_avail; unsigned int oversampling_num; bool os_req_reset; - int (*write_scale_sw)(struct iio_dev *indio_dev, int ch, int val); - int (*write_os_sw)(struct iio_dev *indio_dev, int val); - int (*sw_mode_config)(struct iio_dev *indio_dev); + unsigned long init_delay_ms; }; /** @@ -63,6 +87,7 @@ struct ad7606_chip_info { * @complete completion to indicate end of conversion * @trig The IIO trigger associated with the device. * @data buffer for reading data from the device + * @d16 be16 buffer for reading data from the device */ struct ad7606_state { struct device *dev; @@ -96,15 +121,32 @@ struct ad7606_state { * 16 * 16-bit samples + 64-bit timestamp */ unsigned short data[20] ____cacheline_aligned; + __be16 d16[2]; }; /** * struct ad7606_bus_ops - driver bus operations * @read_block function pointer for reading blocks of data + * @sw_mode_config: pointer to a function which configured the device + * for software mode + * @reg_read function pointer for reading spi register + * @reg_write function pointer for writing spi register + * @write_mask function pointer for write spi register with mask + * @rd_wr_cmd pointer to the function which calculates the spi address */ struct ad7606_bus_ops { /* more methods added in future? */ int (*read_block)(struct device *dev, int num, void *data); + int (*sw_mode_config)(struct iio_dev *indio_dev); + int (*reg_read)(struct ad7606_state *st, unsigned int addr); + int (*reg_write)(struct ad7606_state *st, + unsigned int addr, + unsigned int val); + int (*write_mask)(struct ad7606_state *st, + unsigned int addr, + unsigned long mask, + unsigned int val); + u16 (*rd_wr_cmd)(int addr, char isWriteOp); }; int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, @@ -116,6 +158,7 @@ enum ad7606_supported_device_ids { ID_AD7606_8, ID_AD7606_6, ID_AD7606_4, + ID_AD7606B, ID_AD7616, }; diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c index 1b08028facde..f732b3ac7878 100644 --- a/drivers/iio/adc/ad7606_par.c +++ b/drivers/iio/adc/ad7606_par.c @@ -53,10 +53,8 @@ static int ad7606_par_probe(struct platform_device *pdev) int irq; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); addr = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index b7faef69a58f..29945ad07dca 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -15,6 +15,91 @@ #define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ +#define AD7616_CONFIGURATION_REGISTER 0x02 +#define AD7616_OS_MASK GENMASK(4, 2) +#define AD7616_BURST_MODE BIT(6) +#define AD7616_SEQEN_MODE BIT(5) +#define AD7616_RANGE_CH_A_ADDR_OFF 0x04 +#define AD7616_RANGE_CH_B_ADDR_OFF 0x06 +/* + * Range of channels from a group are stored in 2 registers. + * 0, 1, 2, 3 in a register followed by 4, 5, 6, 7 in second register. + * For channels from second group(8-15) the order is the same, only with + * an offset of 2 for register address. + */ +#define AD7616_RANGE_CH_ADDR(ch) ((ch) >> 2) +/* The range of the channel is stored in 2 bits */ +#define AD7616_RANGE_CH_MSK(ch) (0b11 << (((ch) & 0b11) * 2)) +#define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2)) + +#define AD7606_CONFIGURATION_REGISTER 0x02 +#define AD7606_SINGLE_DOUT 0x00 + +/* + * Range for AD7606B channels are stored in registers starting with address 0x3. + * Each register stores range for 2 channels(4 bits per channel). + */ +#define AD7606_RANGE_CH_MSK(ch) (GENMASK(3, 0) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_MODE(ch, mode) \ + ((GENMASK(3, 0) & mode) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_ADDR(ch) (0x03 + ((ch) >> 1)) +#define AD7606_OS_MODE 0x08 + +static const struct iio_chan_spec ad7616_sw_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(16), + AD7616_CHANNEL(0), + AD7616_CHANNEL(1), + AD7616_CHANNEL(2), + AD7616_CHANNEL(3), + AD7616_CHANNEL(4), + AD7616_CHANNEL(5), + AD7616_CHANNEL(6), + AD7616_CHANNEL(7), + AD7616_CHANNEL(8), + AD7616_CHANNEL(9), + AD7616_CHANNEL(10), + AD7616_CHANNEL(11), + AD7616_CHANNEL(12), + AD7616_CHANNEL(13), + AD7616_CHANNEL(14), + AD7616_CHANNEL(15), +}; + +static const struct iio_chan_spec ad7606b_sw_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(8), + AD7616_CHANNEL(0), + AD7616_CHANNEL(1), + AD7616_CHANNEL(2), + AD7616_CHANNEL(3), + AD7616_CHANNEL(4), + AD7616_CHANNEL(5), + AD7616_CHANNEL(6), + AD7616_CHANNEL(7), +}; + +static const unsigned int ad7606B_oversampling_avail[9] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256 +}; + +static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) +{ + /* + * The address of register consist of one w/r bit + * 6 bits of address followed by one reserved bit. + */ + return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7); +} + +static u16 ad7606B_spi_rd_wr_cmd(int addr, char is_write_op) +{ + /* + * The address of register consists of one bit which + * specifies a read command placed in bit 6, followed by + * 6 bits of address. + */ + return (addr & 0x3F) | (((~is_write_op) & 0x1) << 6); +} + static int ad7606_spi_read_block(struct device *dev, int count, void *buf) { @@ -35,17 +120,210 @@ static int ad7606_spi_read_block(struct device *dev, return 0; } +static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr) +{ + struct spi_device *spi = to_spi_device(st->dev); + struct spi_transfer t[] = { + { + .tx_buf = &st->d16[0], + .len = 2, + .cs_change = 0, + }, { + .rx_buf = &st->d16[1], + .len = 2, + }, + }; + int ret; + + st->d16[0] = cpu_to_be16(st->bops->rd_wr_cmd(addr, 0) << 8); + + ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t)); + if (ret < 0) + return ret; + + return be16_to_cpu(st->d16[1]); +} + +static int ad7606_spi_reg_write(struct ad7606_state *st, + unsigned int addr, + unsigned int val) +{ + struct spi_device *spi = to_spi_device(st->dev); + + st->d16[0] = cpu_to_be16((st->bops->rd_wr_cmd(addr, 1) << 8) | + (val & 0x1FF)); + + return spi_write(spi, &st->d16[0], sizeof(st->d16[0])); +} + +static int ad7606_spi_write_mask(struct ad7606_state *st, + unsigned int addr, + unsigned long mask, + unsigned int val) +{ + int readval; + + readval = st->bops->reg_read(st, addr); + if (readval < 0) + return readval; + + readval &= ~mask; + readval |= val; + + return st->bops->reg_write(st, addr, readval); +} + +static int ad7616_write_scale_sw(struct iio_dev *indio_dev, int ch, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + unsigned int ch_addr, mode, ch_index; + + + /* + * Ad7616 has 16 channels divided in group A and group B. + * The range of channels from A are stored in registers with address 4 + * while channels from B are stored in register with address 6. + * The last bit from channels determines if it is from group A or B + * because the order of channels in iio is 0A, 0B, 1A, 1B... + */ + ch_index = ch >> 1; + + ch_addr = AD7616_RANGE_CH_ADDR(ch_index); + + if ((ch & 0x1) == 0) /* channel A */ + ch_addr += AD7616_RANGE_CH_A_ADDR_OFF; + else /* channel B */ + ch_addr += AD7616_RANGE_CH_B_ADDR_OFF; + + /* 0b01 for 2.5v, 0b10 for 5v and 0b11 for 10v */ + mode = AD7616_RANGE_CH_MODE(ch_index, ((val + 1) & 0b11)); + return st->bops->write_mask(st, ch_addr, AD7616_RANGE_CH_MSK(ch_index), + mode); +} + +static int ad7616_write_os_sw(struct iio_dev *indio_dev, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return st->bops->write_mask(st, AD7616_CONFIGURATION_REGISTER, + AD7616_OS_MASK, val << 2); +} + +static int ad7606_write_scale_sw(struct iio_dev *indio_dev, int ch, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_spi_write_mask(st, + AD7606_RANGE_CH_ADDR(ch), + AD7606_RANGE_CH_MSK(ch), + AD7606_RANGE_CH_MODE(ch, val)); +} + +static int ad7606_write_os_sw(struct iio_dev *indio_dev, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_spi_reg_write(st, AD7606_OS_MODE, val); +} + +static int ad7616_sw_mode_config(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + /* + * Scale can be configured individually for each channel + * in software mode. + */ + indio_dev->channels = ad7616_sw_channels; + + st->write_scale = ad7616_write_scale_sw; + st->write_os = &ad7616_write_os_sw; + + /* Activate Burst mode and SEQEN MODE */ + return st->bops->write_mask(st, + AD7616_CONFIGURATION_REGISTER, + AD7616_BURST_MODE | AD7616_SEQEN_MODE, + AD7616_BURST_MODE | AD7616_SEQEN_MODE); +} + +static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + unsigned long os[3] = {1}; + + /* + * Software mode is enabled when all three oversampling + * pins are set to high. If oversampling gpios are defined + * in the device tree, then they need to be set to high, + * otherwise, they must be hardwired to VDD + */ + if (st->gpio_os) { + gpiod_set_array_value(ARRAY_SIZE(os), + st->gpio_os->desc, st->gpio_os->info, os); + } + /* OS of 128 and 256 are available only in software mode */ + st->oversampling_avail = ad7606B_oversampling_avail; + st->num_os_ratios = ARRAY_SIZE(ad7606B_oversampling_avail); + + st->write_scale = ad7606_write_scale_sw; + st->write_os = &ad7606_write_os_sw; + + /* Configure device spi to output on a single channel */ + st->bops->reg_write(st, + AD7606_CONFIGURATION_REGISTER, + AD7606_SINGLE_DOUT); + + /* + * Scale can be configured individually for each channel + * in software mode. + */ + indio_dev->channels = ad7606b_sw_channels; + + return 0; +} + static const struct ad7606_bus_ops ad7606_spi_bops = { .read_block = ad7606_spi_read_block, }; +static const struct ad7606_bus_ops ad7616_spi_bops = { + .read_block = ad7606_spi_read_block, + .reg_read = ad7606_spi_reg_read, + .reg_write = ad7606_spi_reg_write, + .write_mask = ad7606_spi_write_mask, + .rd_wr_cmd = ad7616_spi_rd_wr_cmd, + .sw_mode_config = ad7616_sw_mode_config, +}; + +static const struct ad7606_bus_ops ad7606B_spi_bops = { + .read_block = ad7606_spi_read_block, + .reg_read = ad7606_spi_reg_read, + .reg_write = ad7606_spi_reg_write, + .write_mask = ad7606_spi_write_mask, + .rd_wr_cmd = ad7606B_spi_rd_wr_cmd, + .sw_mode_config = ad7606B_sw_mode_config, +}; + static int ad7606_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); + const struct ad7606_bus_ops *bops; + + switch (id->driver_data) { + case ID_AD7616: + bops = &ad7616_spi_bops; + break; + case ID_AD7606B: + bops = &ad7606B_spi_bops; + break; + default: + bops = &ad7606_spi_bops; + break; + } return ad7606_probe(&spi->dev, spi->irq, NULL, id->name, id->driver_data, - &ad7606_spi_bops); + bops); } static const struct spi_device_id ad7606_id_table[] = { @@ -53,6 +331,7 @@ static const struct spi_device_id ad7606_id_table[] = { { "ad7606-4", ID_AD7606_4 }, { "ad7606-6", ID_AD7606_6 }, { "ad7606-8", ID_AD7606_8 }, + { "ad7606b", ID_AD7606B }, { "ad7616", ID_AD7616 }, {} }; @@ -63,6 +342,7 @@ static const struct of_device_id ad7606_of_match[] = { { .compatible = "adi,ad7606-4" }, { .compatible = "adi,ad7606-6" }, { .compatible = "adi,ad7606-8" }, + { .compatible = "adi,ad7606b" }, { .compatible = "adi,ad7616" }, { }, }; diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c index 217a5a5c3c6d..291c1a898129 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -203,6 +203,7 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = { .set_mode = ad7780_set_mode, .postprocess_sample = ad7780_postprocess_sample, .has_registers = false, + .irq_flags = IRQF_TRIGGER_LOW, }; #define AD7780_CHANNEL(bits, wordsize) \ diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 54025ea10239..abb239392631 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -205,6 +205,7 @@ static const struct ad_sigma_delta_info ad7791_sigma_delta_info = { .has_registers = true, .addr_shift = 4, .read_mask = BIT(3), + .irq_flags = IRQF_TRIGGER_LOW, }; static int ad7791_read_raw(struct iio_dev *indio_dev, diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index bbc41ecf0d2f..b747db97f78a 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -206,6 +206,7 @@ static const struct ad_sigma_delta_info ad7793_sigma_delta_info = { .has_registers = true, .addr_shift = 3, .read_mask = BIT(6), + .irq_flags = IRQF_TRIGGER_LOW, }; static const struct ad_sd_calib_data ad7793_calib_arr[6] = { diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c index 6223043e432b..c6a3428e950a 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -43,11 +43,17 @@ enum ad7887_channels { /** * struct ad7887_chip_info - chip specifc information * @int_vref_mv: the internal reference voltage - * @channel: channel specification + * @channels: channels specification + * @num_channels: number of channels + * @dual_channels: channels specification in dual mode + * @num_dual_channels: number of channels in dual mode */ struct ad7887_chip_info { u16 int_vref_mv; - struct iio_chan_spec channel[3]; + const struct iio_chan_spec *channels; + unsigned int num_channels; + const struct iio_chan_spec *dual_channels; + unsigned int num_dual_channels; }; struct ad7887_state { @@ -183,45 +189,43 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, return -EINVAL; } +#define AD7887_CHANNEL(x) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (x), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .address = (x), \ + .scan_index = (x), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 0, \ + .endianness = IIO_BE, \ + }, \ +} + +static const struct iio_chan_spec ad7887_channels[] = { + AD7887_CHANNEL(0), + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static const struct iio_chan_spec ad7887_dual_channels[] = { + AD7887_CHANNEL(0), + AD7887_CHANNEL(1), + IIO_CHAN_SOFT_TIMESTAMP(2), +}; static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { /* * More devices added in future */ [ID_AD7887] = { - .channel[0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .address = 1, - .scan_index = 1, - .scan_type = { - .sign = 'u', - .realbits = 12, - .storagebits = 16, - .shift = 0, - .endianness = IIO_BE, - }, - }, - .channel[1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .address = 0, - .scan_index = 0, - .scan_type = { - .sign = 'u', - .realbits = 12, - .storagebits = 16, - .shift = 0, - .endianness = IIO_BE, - }, - }, - .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2), + .channels = ad7887_channels, + .num_channels = ARRAY_SIZE(ad7887_channels), + .dual_channels = ad7887_dual_channels, + .num_dual_channels = ARRAY_SIZE(ad7887_dual_channels), .int_vref_mv = 2500, }, }; @@ -306,11 +310,11 @@ static int ad7887_probe(struct spi_device *spi) spi_message_init(&st->msg[AD7887_CH1]); spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]); - indio_dev->channels = st->chip_info->channel; - indio_dev->num_channels = 3; + indio_dev->channels = st->chip_info->dual_channels; + indio_dev->num_channels = st->chip_info->num_dual_channels; } else { - indio_dev->channels = &st->chip_info->channel[1]; - indio_dev->num_channels = 2; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; } ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index 3212eb4c0f25..1d124c87c6ac 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * AD7904/AD7914/AD7923/AD7924 SPI ADC driver + * AD7904/AD7914/AD7923/AD7924/AD7908/AD7918/AD7928 SPI ADC driver * * Copyright 2011 Analog Devices Inc (from AD7923 Driver) * Copyright 2012 CS Systemes d'Information @@ -29,15 +29,10 @@ #define AD7923_PM_MODE_AS (1) /* auto shutdown */ #define AD7923_PM_MODE_FS (2) /* full shutdown */ #define AD7923_PM_MODE_OPS (3) /* normal operation */ -#define AD7923_CHANNEL_0 (0) /* analog input 0 */ -#define AD7923_CHANNEL_1 (1) /* analog input 1 */ -#define AD7923_CHANNEL_2 (2) /* analog input 2 */ -#define AD7923_CHANNEL_3 (3) /* analog input 3 */ #define AD7923_SEQUENCE_OFF (0) /* no sequence fonction */ #define AD7923_SEQUENCE_PROTECT (2) /* no interrupt write cycle */ #define AD7923_SEQUENCE_ON (3) /* continuous sequence */ -#define AD7923_MAX_CHAN 4 #define AD7923_PM_MODE_WRITE(mode) ((mode) << 4) /* write mode */ #define AD7923_CHANNEL_WRITE(channel) ((channel) << 6) /* write channel */ @@ -78,6 +73,9 @@ enum ad7923_id { AD7904, AD7914, AD7924, + AD7908, + AD7918, + AD7928 }; #define AD7923_V_CHAN(index, bits) \ @@ -106,9 +104,25 @@ const struct iio_chan_spec name ## _channels[] = { \ IIO_CHAN_SOFT_TIMESTAMP(4), \ } +#define DECLARE_AD7908_CHANNELS(name, bits) \ +const struct iio_chan_spec name ## _channels[] = { \ + AD7923_V_CHAN(0, bits), \ + AD7923_V_CHAN(1, bits), \ + AD7923_V_CHAN(2, bits), \ + AD7923_V_CHAN(3, bits), \ + AD7923_V_CHAN(4, bits), \ + AD7923_V_CHAN(5, bits), \ + AD7923_V_CHAN(6, bits), \ + AD7923_V_CHAN(7, bits), \ + IIO_CHAN_SOFT_TIMESTAMP(8), \ +} + static DECLARE_AD7923_CHANNELS(ad7904, 8); static DECLARE_AD7923_CHANNELS(ad7914, 10); static DECLARE_AD7923_CHANNELS(ad7924, 12); +static DECLARE_AD7908_CHANNELS(ad7908, 8); +static DECLARE_AD7908_CHANNELS(ad7918, 10); +static DECLARE_AD7908_CHANNELS(ad7928, 12); static const struct ad7923_chip_info ad7923_chip_info[] = { [AD7904] = { @@ -123,6 +137,18 @@ static const struct ad7923_chip_info ad7923_chip_info[] = { .channels = ad7924_channels, .num_channels = ARRAY_SIZE(ad7924_channels), }, + [AD7908] = { + .channels = ad7908_channels, + .num_channels = ARRAY_SIZE(ad7908_channels), + }, + [AD7918] = { + .channels = ad7918_channels, + .num_channels = ARRAY_SIZE(ad7918_channels), + }, + [AD7928] = { + .channels = ad7928_channels, + .num_channels = ARRAY_SIZE(ad7928_channels), + }, }; /** @@ -135,7 +161,11 @@ static int ad7923_update_scan_mode(struct iio_dev *indio_dev, int i, cmd, len; len = 0; - for_each_set_bit(i, active_scan_mask, AD7923_MAX_CHAN) { + /* + * For this driver the last channel is always the software timestamp so + * skip that one. + */ + for_each_set_bit(i, active_scan_mask, indio_dev->num_channels - 1) { cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(i) | AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) | st->settings; @@ -188,7 +218,7 @@ done: return IRQ_HANDLED; } -static int ad7923_scan_direct(struct ad7923_state *st, unsigned ch) +static int ad7923_scan_direct(struct ad7923_state *st, unsigned int ch) { int ret, cmd; @@ -348,13 +378,29 @@ static const struct spi_device_id ad7923_id[] = { {"ad7914", AD7914}, {"ad7923", AD7924}, {"ad7924", AD7924}, + {"ad7908", AD7908}, + {"ad7918", AD7918}, + {"ad7928", AD7928}, {} }; MODULE_DEVICE_TABLE(spi, ad7923_id); +static const struct of_device_id ad7923_of_match[] = { + { .compatible = "adi,ad7904", }, + { .compatible = "adi,ad7914", }, + { .compatible = "adi,ad7923", }, + { .compatible = "adi,ad7924", }, + { .compatible = "adi,ad7908", }, + { .compatible = "adi,ad7918", }, + { .compatible = "adi,ad7928", }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7923_of_match); + static struct spi_driver ad7923_driver = { .driver = { .name = "ad7923", + .of_match_table = ad7923_of_match, }, .probe = ad7923_probe, .remove = ad7923_remove, @@ -364,5 +410,5 @@ module_spi_driver(ad7923_driver); MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_AUTHOR("Patrick Vasseur <patrick.vasseur@c-s.fr>"); -MODULE_DESCRIPTION("Analog Devices AD7904/AD7914/AD7923/AD7924 ADC"); +MODULE_DESCRIPTION("Analog Devices AD7923 and similar ADC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index ac0ffff6c5ae..2c6f60edb7ce 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -54,38 +54,20 @@ struct ad7949_adc_chip { u8 resolution; u16 cfg; unsigned int current_channel; - u32 buffer ____cacheline_aligned; + u16 buffer ____cacheline_aligned; }; -static bool ad7949_spi_cfg_is_read_back(struct ad7949_adc_chip *ad7949_adc) -{ - if (!(ad7949_adc->cfg & AD7949_CFG_READ_BACK)) - return true; - - return false; -} - -static int ad7949_spi_bits_per_word(struct ad7949_adc_chip *ad7949_adc) -{ - int ret = ad7949_adc->resolution; - - if (ad7949_spi_cfg_is_read_back(ad7949_adc)) - ret += AD7949_CFG_REG_SIZE_BITS; - - return ret; -} - static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val, u16 mask) { int ret; - int bits_per_word = ad7949_spi_bits_per_word(ad7949_adc); + int bits_per_word = ad7949_adc->resolution; int shift = bits_per_word - AD7949_CFG_REG_SIZE_BITS; struct spi_message msg; struct spi_transfer tx[] = { { .tx_buf = &ad7949_adc->buffer, - .len = 4, + .len = 2, .bits_per_word = bits_per_word, }, }; @@ -107,23 +89,35 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val, unsigned int channel) { int ret; - int bits_per_word = ad7949_spi_bits_per_word(ad7949_adc); + int i; + int bits_per_word = ad7949_adc->resolution; int mask = GENMASK(ad7949_adc->resolution, 0); struct spi_message msg; struct spi_transfer tx[] = { { .rx_buf = &ad7949_adc->buffer, - .len = 4, + .len = 2, .bits_per_word = bits_per_word, }, }; - ret = ad7949_spi_write_cfg(ad7949_adc, - channel << AD7949_OFFSET_CHANNEL_SEL, - AD7949_MASK_CHANNEL_SEL); - if (ret) - return ret; + /* + * 1: write CFG for sample N and read old data (sample N-2) + * 2: if CFG was not changed since sample N-1 then we'll get good data + * at the next xfer, so we bail out now, otherwise we write something + * and we read garbage (sample N-1 configuration). + */ + for (i = 0; i < 2; i++) { + ret = ad7949_spi_write_cfg(ad7949_adc, + channel << AD7949_OFFSET_CHANNEL_SEL, + AD7949_MASK_CHANNEL_SEL); + if (ret) + return ret; + if (channel == ad7949_adc->current_channel) + break; + } + /* 3: write something and read actual data */ ad7949_adc->buffer = 0; spi_message_init_with_transfers(&msg, tx, 1); ret = spi_sync(ad7949_adc->spi, &msg); @@ -138,10 +132,7 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val, ad7949_adc->current_channel = channel; - if (ad7949_spi_cfg_is_read_back(ad7949_adc)) - *val = (ad7949_adc->buffer >> AD7949_CFG_REG_SIZE_BITS) & mask; - else - *val = ad7949_adc->buffer & mask; + *val = ad7949_adc->buffer & mask; return 0; } diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 5a3ca5904ded..ef013af1aec0 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -167,6 +167,21 @@ static int ad799x_read_config(struct ad799x_state *st) } } +static int ad799x_update_config(struct ad799x_state *st, u16 config) +{ + int ret; + + ret = ad799x_write_config(st, config); + if (ret < 0) + return ret; + ret = ad799x_read_config(st); + if (ret < 0) + return ret; + st->config = ret; + + return 0; +} + /** * ad799x_trigger_handler() bh of trigger launched polling to ring buffer * @@ -808,13 +823,9 @@ static int ad799x_probe(struct i2c_client *client, indio_dev->channels = st->chip_config->channel; indio_dev->num_channels = chip_info->num_channels; - ret = ad799x_write_config(st, st->chip_config->default_config); - if (ret < 0) - goto error_disable_reg; - ret = ad799x_read_config(st); - if (ret < 0) - goto error_disable_reg; - st->config = ret; + ret = ad799x_update_config(st, st->chip_config->default_config); + if (ret) + goto error_disable_vref; ret = iio_triggered_buffer_setup(indio_dev, NULL, &ad799x_trigger_handler, NULL); @@ -864,6 +875,48 @@ static int ad799x_remove(struct i2c_client *client) return 0; } +static int __maybe_unused ad799x_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct ad799x_state *st = iio_priv(indio_dev); + + regulator_disable(st->vref); + regulator_disable(st->reg); + + return 0; +} + +static int __maybe_unused ad799x_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct ad799x_state *st = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(st->reg); + if (ret) { + dev_err(dev, "Unable to enable vcc regulator\n"); + return ret; + } + ret = regulator_enable(st->vref); + if (ret) { + regulator_disable(st->reg); + dev_err(dev, "Unable to enable vref regulator\n"); + return ret; + } + + /* resync config */ + ret = ad799x_update_config(st, st->config); + if (ret) { + regulator_disable(st->vref); + regulator_disable(st->reg); + return ret; + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(ad799x_pm_ops, ad799x_suspend, ad799x_resume); + static const struct i2c_device_id ad799x_id[] = { { "ad7991", ad7991 }, { "ad7995", ad7995 }, @@ -881,6 +934,7 @@ MODULE_DEVICE_TABLE(i2c, ad799x_id); static struct i2c_driver ad799x_driver = { .driver = { .name = "ad799x", + .pm = &ad799x_pm_ops, }, .probe = ad799x_probe, .remove = ad799x_remove, diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 2640b75fb774..8115b6de1d6c 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -205,7 +205,7 @@ int ad_sd_reset(struct ad_sigma_delta *sigma_delta, } EXPORT_SYMBOL_GPL(ad_sd_reset); -static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, +int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, unsigned int mode, unsigned int channel) { int ret; @@ -242,6 +242,7 @@ out: return ret; } +EXPORT_SYMBOL_GPL(ad_sd_calibrate); /** * ad_sd_calibrate_all() - Performs channel calibration @@ -499,7 +500,7 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev) ret = request_irq(sigma_delta->spi->irq, ad_sd_data_rdy_trig_poll, - IRQF_TRIGGER_LOW, + sigma_delta->info->irq_flags, indio_dev->name, sigma_delta); if (ret) diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index d3fc39df535d..1e5375235cfe 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -173,7 +173,6 @@ static int aspeed_adc_probe(struct platform_device *pdev) struct iio_dev *indio_dev; struct aspeed_adc_data *data; const struct aspeed_adc_model_data *model_data; - struct resource *res; const char *clk_parent_name; int ret; u32 adc_engine_control_reg_val; @@ -185,8 +184,7 @@ static int aspeed_adc_probe(struct platform_device *pdev) data = iio_priv(indio_dev); data->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->base = devm_ioremap_resource(&pdev->dev, res); + data->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->base)) return PTR_ERR(data->base); diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index a2837a0e7cba..a5c7771227d5 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -1444,10 +1444,10 @@ static void at91_adc_dma_init(struct platform_device *pdev) if (st->dma_st.dma_chan) return; - st->dma_st.dma_chan = dma_request_slave_channel(&pdev->dev, "rx"); - - if (!st->dma_st.dma_chan) { + st->dma_st.dma_chan = dma_request_chan(&pdev->dev, "rx"); + if (IS_ERR(st->dma_st.dma_chan)) { dev_info(&pdev->dev, "can't get DMA channel\n"); + st->dma_st.dma_chan = NULL; goto dma_exit; } @@ -1483,7 +1483,7 @@ dma_free_area: st->dma_st.rx_buf, st->dma_st.rx_dma_buf); dma_chan_disable: dma_release_channel(st->dma_st.dma_chan); - st->dma_st.dma_chan = 0; + st->dma_st.dma_chan = NULL; dma_exit: dev_info(&pdev->dev, "continuing without DMA support\n"); } @@ -1506,7 +1506,7 @@ static void at91_adc_dma_disable(struct platform_device *pdev) dma_free_coherent(st->dma_st.dma_chan->device->dev, pages * PAGE_SIZE, st->dma_st.rx_buf, st->dma_st.rx_dma_buf); dma_release_channel(st->dma_st.dma_chan); - st->dma_st.dma_chan = 0; + st->dma_st.dma_chan = NULL; dev_info(&pdev->dev, "continuing without DMA support\n"); } diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 32f1c4a33b20..abe99856c823 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -1179,10 +1179,8 @@ static int at91_adc_probe(struct platform_device *pdev) idev->info = &at91_adc_info; st->irq = platform_get_irq(pdev, 0); - if (st->irq < 0) { - dev_err(&pdev->dev, "No IRQ ID is designated\n"); + if (st->irq < 0) return -ENODEV; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 31d51bcc5f2c..8ea2aed6d6f5 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -7,6 +7,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#include <linux/dmi.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> @@ -25,6 +26,11 @@ #define AXP288_ADC_EN_MASK 0xF0 #define AXP288_ADC_TS_ENABLE 0x01 +#define AXP288_ADC_TS_BIAS_MASK GENMASK(5, 4) +#define AXP288_ADC_TS_BIAS_20UA (0 << 4) +#define AXP288_ADC_TS_BIAS_40UA (1 << 4) +#define AXP288_ADC_TS_BIAS_60UA (2 << 4) +#define AXP288_ADC_TS_BIAS_80UA (3 << 4) #define AXP288_ADC_TS_CURRENT_ON_OFF_MASK GENMASK(1, 0) #define AXP288_ADC_TS_CURRENT_OFF (0 << 0) #define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING (1 << 0) @@ -177,10 +183,36 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, return ret; } +/* + * We rely on the machine's firmware to correctly setup the TS pin bias current + * at boot. This lists systems with broken fw where we need to set it ourselves. + */ +static const struct dmi_system_id axp288_adc_ts_bias_override[] = { + { + /* Lenovo Ideapad 100S (11 inch) */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 100S-11IBY"), + }, + .driver_data = (void *)(uintptr_t)AXP288_ADC_TS_BIAS_80UA, + }, + {} +}; + static int axp288_adc_initialize(struct axp288_adc_info *info) { + const struct dmi_system_id *bias_override; int ret, adc_enable_val; + bias_override = dmi_first_match(axp288_adc_ts_bias_override); + if (bias_override) { + ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL, + AXP288_ADC_TS_BIAS_MASK, + (uintptr_t)bias_override->driver_data); + if (ret) + return ret; + } + /* * Determine if the TS pin is enabled and set the TS current-source * accordingly. @@ -225,10 +257,8 @@ static int axp288_adc_probe(struct platform_device *pdev) info = iio_priv(indio_dev); info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (info->irq < 0) return info->irq; - } platform_set_drvdata(pdev, indio_dev); info->regmap = axp20x->regmap; /* diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c index c46c0aa15376..5e396104ac86 100644 --- a/drivers/iio/adc/bcm_iproc_adc.c +++ b/drivers/iio/adc/bcm_iproc_adc.c @@ -308,7 +308,7 @@ static int iproc_adc_do_read(struct iio_dev *indio_dev, "IntMask set failed. Read will likely fail."); read_len = -EIO; goto adc_err; - }; + } } regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check); @@ -540,11 +540,8 @@ static int iproc_adc_probe(struct platform_device *pdev) } adc_priv->irqno = platform_get_irq(pdev, 0); - if (adc_priv->irqno <= 0) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); - ret = -ENODEV; - return ret; - } + if (adc_priv->irqno <= 0) + return -ENODEV; ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, IPROC_ADC_AUXIN_SCAN_ENA, 0); diff --git a/drivers/iio/adc/cc10001_adc.c b/drivers/iio/adc/cc10001_adc.c index f93f1d93b80d..fe9257624f16 100644 --- a/drivers/iio/adc/cc10001_adc.c +++ b/drivers/iio/adc/cc10001_adc.c @@ -310,7 +310,6 @@ static int cc10001_adc_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; struct cc10001_adc_device *adc_dev; unsigned long adc_clk_rate; - struct resource *res; struct iio_dev *indio_dev; unsigned long channel_map; int ret; @@ -340,8 +339,7 @@ static int cc10001_adc_probe(struct platform_device *pdev) indio_dev->info = &cc10001_adc_info; indio_dev->modes = INDIO_DIRECT_MODE; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res); + adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adc_dev->reg_base)) { ret = PTR_ERR(adc_dev->reg_base); goto err_disable_reg; diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index 2d616cafe75f..5086a337f4c9 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -1008,7 +1008,7 @@ static int cpcap_adc_probe(struct platform_device *pdev) error = devm_request_threaded_irq(&pdev->dev, ddata->irq, NULL, cpcap_adc_irq_thread, - IRQF_TRIGGER_NONE, + IRQF_TRIGGER_NONE | IRQF_ONESHOT, "cpcap-adc", indio_dev); if (error) { dev_err(&pdev->dev, "could not get irq: %i\n", diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c index 354433996101..ae8bcc32f63d 100644 --- a/drivers/iio/adc/da9150-gpadc.c +++ b/drivers/iio/adc/da9150-gpadc.c @@ -337,10 +337,8 @@ static int da9150_gpadc_probe(struct platform_device *pdev) init_completion(&gpadc->complete); irq = platform_get_irq_byname(pdev, "GPADC"); - if (irq < 0) { - dev_err(dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq, IRQF_ONESHOT, "GPADC", gpadc); diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c index 5fa78c273a25..65c7c9329b1c 100644 --- a/drivers/iio/adc/dln2-adc.c +++ b/drivers/iio/adc/dln2-adc.c @@ -524,6 +524,10 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) u16 conflict; unsigned int trigger_chan; + ret = iio_triggered_buffer_postenable(indio_dev); + if (ret) + return ret; + mutex_lock(&dln2->mutex); /* Enable ADC */ @@ -537,6 +541,7 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) (int)conflict); ret = -EBUSY; } + iio_triggered_buffer_predisable(indio_dev); return ret; } @@ -550,6 +555,7 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) mutex_unlock(&dln2->mutex); if (ret < 0) { dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); + iio_triggered_buffer_predisable(indio_dev); return ret; } } else { @@ -557,12 +563,12 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev) mutex_unlock(&dln2->mutex); } - return iio_triggered_buffer_postenable(indio_dev); + return 0; } static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev) { - int ret; + int ret, ret2; struct dln2_adc *dln2 = iio_priv(indio_dev); mutex_lock(&dln2->mutex); @@ -577,12 +583,14 @@ static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev) ret = dln2_adc_set_port_enabled(dln2, false, NULL); mutex_unlock(&dln2->mutex); - if (ret < 0) { + if (ret < 0) dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__); - return ret; - } - return iio_triggered_buffer_predisable(indio_dev); + ret2 = iio_triggered_buffer_predisable(indio_dev); + if (ret == 0) + ret = ret2; + + return ret; } static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = { diff --git a/drivers/iio/adc/envelope-detector.c b/drivers/iio/adc/envelope-detector.c index 2f2b563c1162..28f3d6758eb5 100644 --- a/drivers/iio/adc/envelope-detector.c +++ b/drivers/iio/adc/envelope-detector.c @@ -357,11 +357,8 @@ static int envelope_detector_probe(struct platform_device *pdev) } env->comp_irq = platform_get_irq_byname(pdev, "comp"); - if (env->comp_irq < 0) { - if (env->comp_irq != -EPROBE_DEFER) - dev_err(dev, "failed to get compare interrupt\n"); + if (env->comp_irq < 0) return env->comp_irq; - } ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr, 0, "envelope-detector", env); diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index d4c3ece21679..2df7d057b249 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -651,7 +651,7 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id) input_sync(info->input); usleep_range(1000, 1100); - }; + } writel(0, ADC_V1_CLRINTPNDNUP(info->regs)); @@ -769,7 +769,6 @@ static int exynos_adc_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct s3c2410_ts_mach_info *pdata = dev_get_platdata(&pdev->dev); struct iio_dev *indio_dev = NULL; - struct resource *mem; bool has_ts = false; int ret = -ENODEV; int irq; @@ -788,8 +787,7 @@ static int exynos_adc_probe(struct platform_device *pdev) return -EINVAL; } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - info->regs = devm_ioremap_resource(&pdev->dev, mem); + info->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(info->regs)) return PTR_ERR(info->regs); @@ -805,10 +803,8 @@ static int exynos_adc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } info->irq = irq; irq = platform_get_irq(pdev, 1); diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index df19ecae52f7..fa71489195c6 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -340,7 +340,6 @@ static int mx25_gcq_probe(struct platform_device *pdev) priv->irq = platform_get_irq(pdev, 0); if (priv->irq <= 0) { - dev_err(dev, "Failed to get IRQ\n"); ret = priv->irq; if (!ret) ret = -ENXIO; diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 35951c47004e..8da45bf36d36 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -456,6 +456,11 @@ err_read: return IRQ_HANDLED; } +static void hi8435_triggered_event_cleanup(void *data) +{ + iio_triggered_event_cleanup(data); +} + static int hi8435_probe(struct spi_device *spi) { struct iio_dev *idev; @@ -477,7 +482,7 @@ static int hi8435_probe(struct spi_device *spi) hi8435_writeb(priv, HI8435_CTRL_REG, 0); } else { udelay(5); - gpiod_set_value(reset_gpio, 1); + gpiod_set_value_cansleep(reset_gpio, 1); } spi_set_drvdata(spi, idev); @@ -513,27 +518,13 @@ static int hi8435_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_device_register(idev); - if (ret < 0) { - dev_err(&spi->dev, "unable to register device\n"); - goto unregister_triggered_event; - } - - return 0; - -unregister_triggered_event: - iio_triggered_event_cleanup(idev); - return ret; -} - -static int hi8435_remove(struct spi_device *spi) -{ - struct iio_dev *idev = spi_get_drvdata(spi); - - iio_device_unregister(idev); - iio_triggered_event_cleanup(idev); + ret = devm_add_action_or_reset(&spi->dev, + hi8435_triggered_event_cleanup, + idev); + if (ret) + return ret; - return 0; + return devm_iio_device_register(&spi->dev, idev); } static const struct of_device_id hi8435_dt_ids[] = { @@ -554,7 +545,6 @@ static struct spi_driver hi8435_driver = { .of_match_table = of_match_ptr(hi8435_dt_ids), }, .probe = hi8435_probe, - .remove = hi8435_remove, .id_table = hi8435_id, }; module_spi_driver(hi8435_driver); diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index 88c7fe15003b..c8686558429b 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -23,6 +23,7 @@ /* gain to pulse and scale conversion */ #define HX711_GAIN_MAX 3 +#define HX711_RESET_GAIN 128 struct hx711_gain_to_scale { int gain; @@ -100,14 +101,14 @@ struct hx711_data { static int hx711_cycle(struct hx711_data *hx711_data) { - int val; + unsigned long flags; /* * if preempted for more then 60us while PD_SCK is high: * hx711 is going in reset * ==> measuring is false */ - preempt_disable(); + local_irq_save(flags); gpiod_set_value(hx711_data->gpiod_pd_sck, 1); /* @@ -117,7 +118,6 @@ static int hx711_cycle(struct hx711_data *hx711_data) */ ndelay(hx711_data->data_ready_delay_ns); - val = gpiod_get_value(hx711_data->gpiod_dout); /* * here we are not waiting for 0.2 us as suggested by the datasheet, * because the oscilloscope showed in a test scenario @@ -125,7 +125,7 @@ static int hx711_cycle(struct hx711_data *hx711_data) * and 0.56 us for PD_SCK low on TI Sitara with 800 MHz */ gpiod_set_value(hx711_data->gpiod_pd_sck, 0); - preempt_enable(); + local_irq_restore(flags); /* * make it a square wave for addressing cases with capacitance on @@ -133,7 +133,8 @@ static int hx711_cycle(struct hx711_data *hx711_data) */ ndelay(hx711_data->data_ready_delay_ns); - return val; + /* sample as late as possible */ + return gpiod_get_value(hx711_data->gpiod_dout); } static int hx711_read(struct hx711_data *hx711_data) @@ -185,8 +186,7 @@ static int hx711_wait_for_ready(struct hx711_data *hx711_data) static int hx711_reset(struct hx711_data *hx711_data) { - int ret; - int val = gpiod_get_value(hx711_data->gpiod_dout); + int val = hx711_wait_for_ready(hx711_data); if (val) { /* @@ -202,22 +202,10 @@ static int hx711_reset(struct hx711_data *hx711_data) msleep(10); gpiod_set_value(hx711_data->gpiod_pd_sck, 0); - ret = hx711_wait_for_ready(hx711_data); - if (ret) - return ret; - /* - * after a reset the gain is 128 so we do a dummy read - * to set the gain for the next read - */ - ret = hx711_read(hx711_data); - if (ret < 0) - return ret; - - /* - * after a dummy read we need to wait vor readiness - * for not mixing gain pulses with the clock - */ val = hx711_wait_for_ready(hx711_data); + + /* after a reset the gain is 128 */ + hx711_data->gain_set = HX711_RESET_GAIN; } return val; diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c index 26a7bbe4d534..2a2fbf788e95 100644 --- a/drivers/iio/adc/imx7d_adc.c +++ b/drivers/iio/adc/imx7d_adc.c @@ -492,10 +492,8 @@ static int imx7d_adc_probe(struct platform_device *pdev) return PTR_ERR(info->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "No irq resource?\n"); + if (irq < 0) return irq; - } info->clk = devm_clk_get(dev, "adc"); if (IS_ERR(info->clk)) { diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c index e234970b7150..39c0a609fc94 100644 --- a/drivers/iio/adc/ingenic-adc.c +++ b/drivers/iio/adc/ingenic-adc.c @@ -25,9 +25,13 @@ #define JZ_ADC_REG_ADSDAT 0x20 #define JZ_ADC_REG_ADCLK 0x28 +#define JZ_ADC_REG_ENABLE_PD BIT(7) +#define JZ_ADC_REG_CFG_AUX_MD (BIT(0) | BIT(1)) #define JZ_ADC_REG_CFG_BAT_MD BIT(4) #define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0 -#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB 16 +#define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB 16 +#define JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB 8 +#define JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB 16 #define JZ_ADC_AUX_VREF 3300 #define JZ_ADC_AUX_VREF_BITS 12 @@ -37,6 +41,8 @@ #define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS 10 #define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986) #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12 +#define JZ4770_ADC_BATTERY_VREF 6600 +#define JZ4770_ADC_BATTERY_VREF_BITS 12 struct ingenic_adc; @@ -47,6 +53,8 @@ struct ingenic_adc_soc_data { size_t battery_raw_avail_size; const int *battery_scale_avail; size_t battery_scale_avail_size; + unsigned int battery_vref_mode: 1; + unsigned int has_aux2: 1; int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc); }; @@ -54,6 +62,7 @@ struct ingenic_adc { void __iomem *base; struct clk *clk; struct mutex lock; + struct mutex aux_lock; const struct ingenic_adc_soc_data *soc_data; bool low_vref_mode; }; @@ -120,6 +129,8 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->channel) { case INGENIC_ADC_BATTERY: + if (!adc->soc_data->battery_vref_mode) + return -EINVAL; if (val > JZ_ADC_BATTERY_LOW_VREF) { ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_BAT_MD, @@ -158,6 +169,14 @@ static const int jz4740_adc_battery_scale_avail[] = { JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS, }; +static const int jz4770_adc_battery_raw_avail[] = { + 0, 1, (1 << JZ4770_ADC_BATTERY_VREF_BITS) - 1, +}; + +static const int jz4770_adc_battery_scale_avail[] = { + JZ4770_ADC_BATTERY_VREF, JZ4770_ADC_BATTERY_VREF_BITS, +}; + static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc) { struct clk *parent_clk; @@ -187,7 +206,45 @@ static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc) /* We also need a divider that produces a 10us clock. */ div_10us = DIV_ROUND_UP(rate, 100000); - writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) | + writel(((div_10us - 1) << JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB) | + (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, + adc->base + JZ_ADC_REG_ADCLK); + + return 0; +} + +static int jz4770_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc) +{ + struct clk *parent_clk; + unsigned long parent_rate, rate; + unsigned int div_main, div_ms, div_10us; + + parent_clk = clk_get_parent(adc->clk); + if (!parent_clk) { + dev_err(dev, "ADC clock has no parent\n"); + return -ENODEV; + } + parent_rate = clk_get_rate(parent_clk); + + /* + * The JZ4770 ADC works at 20 kHz to 200 kHz. + * We pick the highest rate possible. + */ + div_main = DIV_ROUND_UP(parent_rate, 200000); + div_main = clamp(div_main, 1u, 256u); + rate = parent_rate / div_main; + if (rate < 20000 || rate > 200000) { + dev_err(dev, "No valid divider for ADC main clock\n"); + return -EINVAL; + } + + /* We also need a divider that produces a 10us clock. */ + div_10us = DIV_ROUND_UP(rate, 10000); + /* And another, which produces a 1ms clock. */ + div_ms = DIV_ROUND_UP(rate, 1000); + + writel(((div_ms - 1) << JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB) | + ((div_10us - 1) << JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB) | (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, adc->base + JZ_ADC_REG_ADCLK); @@ -201,6 +258,8 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = { .battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail), .battery_scale_avail = jz4725b_adc_battery_scale_avail, .battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail), + .battery_vref_mode = true, + .has_aux2 = false, .init_clk_div = jz4725b_adc_init_clk_div, }; @@ -211,9 +270,23 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = { .battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail), .battery_scale_avail = jz4740_adc_battery_scale_avail, .battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail), + .battery_vref_mode = true, + .has_aux2 = false, .init_clk_div = NULL, /* no ADCLK register on JZ4740 */ }; +static const struct ingenic_adc_soc_data jz4770_adc_soc_data = { + .battery_high_vref = JZ4770_ADC_BATTERY_VREF, + .battery_high_vref_bits = JZ4770_ADC_BATTERY_VREF_BITS, + .battery_raw_avail = jz4770_adc_battery_raw_avail, + .battery_raw_avail_size = ARRAY_SIZE(jz4770_adc_battery_raw_avail), + .battery_scale_avail = jz4770_adc_battery_scale_avail, + .battery_scale_avail_size = ARRAY_SIZE(jz4770_adc_battery_scale_avail), + .battery_vref_mode = false, + .has_aux2 = true, + .init_clk_div = jz4770_adc_init_clk_div, +}; + static int ingenic_adc_read_avail(struct iio_dev *iio_dev, struct iio_chan_spec const *chan, const int **vals, @@ -239,6 +312,42 @@ static int ingenic_adc_read_avail(struct iio_dev *iio_dev, }; } +static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc, + struct iio_chan_spec const *chan, + int *val) +{ + int bit, ret, engine = (chan->channel == INGENIC_ADC_BATTERY); + + /* We cannot sample AUX/AUX2 in parallel. */ + mutex_lock(&adc->aux_lock); + if (adc->soc_data->has_aux2 && engine == 0) { + bit = BIT(chan->channel == INGENIC_ADC_AUX2); + ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit); + } + + clk_enable(adc->clk); + ret = ingenic_adc_capture(adc, engine); + if (ret) + goto out; + + switch (chan->channel) { + case INGENIC_ADC_AUX: + case INGENIC_ADC_AUX2: + *val = readw(adc->base + JZ_ADC_REG_ADSDAT); + break; + case INGENIC_ADC_BATTERY: + *val = readw(adc->base + JZ_ADC_REG_ADBDAT); + break; + } + + ret = IIO_VAL_INT; +out: + clk_disable(adc->clk); + mutex_unlock(&adc->aux_lock); + + return ret; +} + static int ingenic_adc_read_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *chan, int *val, @@ -246,32 +355,14 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev, long m) { struct ingenic_adc *adc = iio_priv(iio_dev); - int ret; switch (m) { case IIO_CHAN_INFO_RAW: - clk_enable(adc->clk); - ret = ingenic_adc_capture(adc, chan->channel); - if (ret) { - clk_disable(adc->clk); - return ret; - } - - switch (chan->channel) { - case INGENIC_ADC_AUX: - *val = readw(adc->base + JZ_ADC_REG_ADSDAT); - break; - case INGENIC_ADC_BATTERY: - *val = readw(adc->base + JZ_ADC_REG_ADBDAT); - break; - } - - clk_disable(adc->clk); - - return IIO_VAL_INT; + return ingenic_adc_read_chan_info_raw(adc, chan, val); case IIO_CHAN_INFO_SCALE: switch (chan->channel) { case INGENIC_ADC_AUX: + case INGENIC_ADC_AUX2: *val = JZ_ADC_AUX_VREF; *val2 = JZ_ADC_AUX_VREF_BITS; break; @@ -322,6 +413,14 @@ static const struct iio_chan_spec ingenic_channels[] = { .indexed = 1, .channel = INGENIC_ADC_BATTERY, }, + { /* Must always be last in the array. */ + .extend_name = "aux2", + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, + .channel = INGENIC_ADC_AUX2, + }, }; static int ingenic_adc_probe(struct platform_device *pdev) @@ -329,7 +428,6 @@ static int ingenic_adc_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct iio_dev *iio_dev; struct ingenic_adc *adc; - struct resource *mem_base; const struct ingenic_adc_soc_data *soc_data; int ret; @@ -343,10 +441,10 @@ static int ingenic_adc_probe(struct platform_device *pdev) adc = iio_priv(iio_dev); mutex_init(&adc->lock); + mutex_init(&adc->aux_lock); adc->soc_data = soc_data; - mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); - adc->base = devm_ioremap_resource(dev, mem_base); + adc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adc->base)) return PTR_ERR(adc->base); @@ -374,6 +472,7 @@ static int ingenic_adc_probe(struct platform_device *pdev) /* Put hardware in a known passive state. */ writeb(0x00, adc->base + JZ_ADC_REG_ENABLE); writeb(0xff, adc->base + JZ_ADC_REG_CTRL); + usleep_range(2000, 3000); /* Must wait at least 2ms. */ clk_disable(adc->clk); ret = devm_add_action_or_reset(dev, ingenic_adc_clk_cleanup, adc->clk); @@ -387,6 +486,9 @@ static int ingenic_adc_probe(struct platform_device *pdev) iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->channels = ingenic_channels; iio_dev->num_channels = ARRAY_SIZE(ingenic_channels); + /* Remove AUX2 from the list of supported channels. */ + if (!adc->soc_data->has_aux2) + iio_dev->num_channels -= 1; iio_dev->info = &ingenic_adc_info; ret = devm_iio_device_register(dev, iio_dev); @@ -400,6 +502,7 @@ static int ingenic_adc_probe(struct platform_device *pdev) static const struct of_device_id ingenic_adc_of_match[] = { { .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, }, { .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, }, + { .compatible = "ingenic,jz4770-adc", .data = &jz4770_adc_soc_data, }, { }, }; MODULE_DEVICE_TABLE(of, ingenic_adc_of_match); diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c new file mode 100644 index 000000000000..c35a1beb817c --- /dev/null +++ b/drivers/iio/adc/intel_mrfld_adc.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ADC driver for Basin Cove PMIC + * + * Copyright (C) 2012 Intel Corporation + * Author: Bin Yang <bin.yang@intel.com> + * + * Rewritten for upstream by: + * Vincent Pelletier <plr.vincent@gmail.com> + * Andy Shevchenko <andriy.shevchenko@linux.intel.com> + */ + +#include <linux/bitops.h> +#include <linux/completion.h> +#include <linux/interrupt.h> +#include <linux/mfd/intel_soc_pmic.h> +#include <linux/mfd/intel_soc_pmic_mrfld.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include <linux/iio/driver.h> +#include <linux/iio/iio.h> +#include <linux/iio/machine.h> + +#include <asm/unaligned.h> + +#define BCOVE_GPADCREQ 0xDC +#define BCOVE_GPADCREQ_BUSY BIT(0) +#define BCOVE_GPADCREQ_IRQEN BIT(1) + +#define BCOVE_ADCIRQ_ALL ( \ + BCOVE_ADCIRQ_BATTEMP | \ + BCOVE_ADCIRQ_SYSTEMP | \ + BCOVE_ADCIRQ_BATTID | \ + BCOVE_ADCIRQ_VIBATT | \ + BCOVE_ADCIRQ_CCTICK) + +#define BCOVE_ADC_TIMEOUT msecs_to_jiffies(1000) + +static const u8 mrfld_adc_requests[] = { + BCOVE_ADCIRQ_VIBATT, + BCOVE_ADCIRQ_BATTID, + BCOVE_ADCIRQ_VIBATT, + BCOVE_ADCIRQ_SYSTEMP, + BCOVE_ADCIRQ_BATTEMP, + BCOVE_ADCIRQ_BATTEMP, + BCOVE_ADCIRQ_SYSTEMP, + BCOVE_ADCIRQ_SYSTEMP, + BCOVE_ADCIRQ_SYSTEMP, +}; + +struct mrfld_adc { + struct regmap *regmap; + struct completion completion; + /* Lock to protect the IPC transfers */ + struct mutex lock; +}; + +static irqreturn_t mrfld_adc_thread_isr(int irq, void *data) +{ + struct iio_dev *indio_dev = data; + struct mrfld_adc *adc = iio_priv(indio_dev); + + complete(&adc->completion); + return IRQ_HANDLED; +} + +static int mrfld_adc_single_conv(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *result) +{ + struct mrfld_adc *adc = iio_priv(indio_dev); + struct regmap *regmap = adc->regmap; + unsigned int req; + long timeout; + u8 buf[2]; + int ret; + + reinit_completion(&adc->completion); + + regmap_update_bits(regmap, BCOVE_MADCIRQ, BCOVE_ADCIRQ_ALL, 0); + regmap_update_bits(regmap, BCOVE_MIRQLVL1, BCOVE_LVL1_ADC, 0); + + ret = regmap_read_poll_timeout(regmap, BCOVE_GPADCREQ, req, + !(req & BCOVE_GPADCREQ_BUSY), + 2000, 1000000); + if (ret) + goto done; + + req = mrfld_adc_requests[chan->channel]; + ret = regmap_write(regmap, BCOVE_GPADCREQ, BCOVE_GPADCREQ_IRQEN | req); + if (ret) + goto done; + + timeout = wait_for_completion_interruptible_timeout(&adc->completion, + BCOVE_ADC_TIMEOUT); + if (timeout < 0) { + ret = timeout; + goto done; + } + if (timeout == 0) { + ret = -ETIMEDOUT; + goto done; + } + + ret = regmap_bulk_read(regmap, chan->address, buf, 2); + if (ret) + goto done; + + *result = get_unaligned_be16(buf); + ret = IIO_VAL_INT; + +done: + regmap_update_bits(regmap, BCOVE_MIRQLVL1, BCOVE_LVL1_ADC, 0xff); + regmap_update_bits(regmap, BCOVE_MADCIRQ, BCOVE_ADCIRQ_ALL, 0xff); + + return ret; +} + +static int mrfld_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mrfld_adc *adc = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&adc->lock); + ret = mrfld_adc_single_conv(indio_dev, chan, val); + mutex_unlock(&adc->lock); + return ret; + default: + return -EINVAL; + } +} + +static const struct iio_info mrfld_adc_iio_info = { + .read_raw = &mrfld_adc_read_raw, +}; + +#define BCOVE_ADC_CHANNEL(_type, _channel, _datasheet_name, _address) \ + { \ + .indexed = 1, \ + .type = _type, \ + .channel = _channel, \ + .address = _address, \ + .datasheet_name = _datasheet_name, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + } + +static const struct iio_chan_spec mrfld_adc_channels[] = { + BCOVE_ADC_CHANNEL(IIO_VOLTAGE, 0, "CH0", 0xE9), + BCOVE_ADC_CHANNEL(IIO_RESISTANCE, 1, "CH1", 0xEB), + BCOVE_ADC_CHANNEL(IIO_CURRENT, 2, "CH2", 0xED), + BCOVE_ADC_CHANNEL(IIO_TEMP, 3, "CH3", 0xCC), + BCOVE_ADC_CHANNEL(IIO_TEMP, 4, "CH4", 0xC8), + BCOVE_ADC_CHANNEL(IIO_TEMP, 5, "CH5", 0xCA), + BCOVE_ADC_CHANNEL(IIO_TEMP, 6, "CH6", 0xC2), + BCOVE_ADC_CHANNEL(IIO_TEMP, 7, "CH7", 0xC4), + BCOVE_ADC_CHANNEL(IIO_TEMP, 8, "CH8", 0xC6), +}; + +static struct iio_map iio_maps[] = { + IIO_MAP("CH0", "bcove-battery", "VBATRSLT"), + IIO_MAP("CH1", "bcove-battery", "BATTID"), + IIO_MAP("CH2", "bcove-battery", "IBATRSLT"), + IIO_MAP("CH3", "bcove-temp", "PMICTEMP"), + IIO_MAP("CH4", "bcove-temp", "BATTEMP0"), + IIO_MAP("CH5", "bcove-temp", "BATTEMP1"), + IIO_MAP("CH6", "bcove-temp", "SYSTEMP0"), + IIO_MAP("CH7", "bcove-temp", "SYSTEMP1"), + IIO_MAP("CH8", "bcove-temp", "SYSTEMP2"), + {} +}; + +static int mrfld_adc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent); + struct iio_dev *indio_dev; + struct mrfld_adc *adc; + int irq; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(struct mrfld_adc)); + if (!indio_dev) + return -ENOMEM; + + adc = iio_priv(indio_dev); + + mutex_init(&adc->lock); + init_completion(&adc->completion); + adc->regmap = pmic->regmap; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(dev, irq, NULL, mrfld_adc_thread_isr, + IRQF_ONESHOT | IRQF_SHARED, pdev->name, + indio_dev); + if (ret) + return ret; + + platform_set_drvdata(pdev, indio_dev); + + indio_dev->dev.parent = dev; + indio_dev->name = pdev->name; + + indio_dev->channels = mrfld_adc_channels; + indio_dev->num_channels = ARRAY_SIZE(mrfld_adc_channels); + indio_dev->info = &mrfld_adc_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_map_array_register(indio_dev, iio_maps); + if (ret) + return ret; + + ret = devm_iio_device_register(dev, indio_dev); + if (ret < 0) + goto err_array_unregister; + + return 0; + +err_array_unregister: + iio_map_array_unregister(indio_dev); + return ret; +} + +static int mrfld_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + + iio_map_array_unregister(indio_dev); + + return 0; +} + +static const struct platform_device_id mrfld_adc_id_table[] = { + { .name = "mrfld_bcove_adc" }, + {} +}; +MODULE_DEVICE_TABLE(platform, mrfld_adc_id_table); + +static struct platform_driver mrfld_adc_driver = { + .driver = { + .name = "mrfld_bcove_adc", + }, + .probe = mrfld_adc_probe, + .remove = mrfld_adc_remove, + .id_table = mrfld_adc_id_table, +}; +module_platform_driver(mrfld_adc_driver); + +MODULE_AUTHOR("Bin Yang <bin.yang@intel.com>"); +MODULE_AUTHOR("Vincent Pelletier <plr.vincent@gmail.com>"); +MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); +MODULE_DESCRIPTION("ADC driver for Basin Cove PMIC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c index e400a95f553d..4c6ac6644dc0 100644 --- a/drivers/iio/adc/lpc18xx_adc.c +++ b/drivers/iio/adc/lpc18xx_adc.c @@ -119,7 +119,6 @@ static int lpc18xx_adc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; struct lpc18xx_adc *adc; - struct resource *res; unsigned int clkdiv; unsigned long rate; int ret; @@ -133,8 +132,7 @@ static int lpc18xx_adc_probe(struct platform_device *pdev) adc->dev = &pdev->dev; mutex_init(&adc->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - adc->base = devm_ioremap_resource(&pdev->dev, res); + adc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adc->base)) return PTR_ERR(adc->base); diff --git a/drivers/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c index a6ee1c3a9064..b896f7ff4572 100644 --- a/drivers/iio/adc/lpc32xx_adc.c +++ b/drivers/iio/adc/lpc32xx_adc.c @@ -172,10 +172,8 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "failed getting interrupt resource\n"); + if (irq <= 0) return -ENXIO; - } retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, LPC32XXAD_NAME, st); diff --git a/drivers/iio/adc/ltc2496.c b/drivers/iio/adc/ltc2496.c new file mode 100644 index 000000000000..88a30156a849 --- /dev/null +++ b/drivers/iio/adc/ltc2496.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ltc2496.c - Driver for Analog Devices/Linear Technology LTC2496 ADC + * + * Based on ltc2497.c which has + * Copyright (C) 2017 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/2496fc.pdf + */ + +#include <linux/spi/spi.h> +#include <linux/iio/iio.h> +#include <linux/iio/driver.h> +#include <linux/module.h> +#include <linux/of.h> + +#include "ltc2497.h" + +struct ltc2496_driverdata { + /* this must be the first member */ + struct ltc2497core_driverdata common_ddata; + struct spi_device *spi; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + unsigned char rxbuf[3] ____cacheline_aligned; + unsigned char txbuf[3]; +}; + +static int ltc2496_result_and_measure(struct ltc2497core_driverdata *ddata, + u8 address, int *val) +{ + struct ltc2496_driverdata *st = + container_of(ddata, struct ltc2496_driverdata, common_ddata); + struct spi_transfer t = { + .tx_buf = st->txbuf, + .rx_buf = st->rxbuf, + .len = sizeof(st->txbuf), + }; + int ret; + + st->txbuf[0] = LTC2497_ENABLE | address; + + ret = spi_sync_transfer(st->spi, &t, 1); + if (ret < 0) { + dev_err(&st->spi->dev, "spi_sync_transfer failed: %pe\n", + ERR_PTR(ret)); + return ret; + } + + if (val) + *val = ((st->rxbuf[0] & 0x3f) << 12 | + st->rxbuf[1] << 4 | st->rxbuf[2] >> 4) - + (1 << 17); + + return 0; +} + +static int ltc2496_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ltc2496_driverdata *st; + struct device *dev = &spi->dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->common_ddata.result_and_measure = ltc2496_result_and_measure; + + return ltc2497core_probe(dev, indio_dev); +} + +static int ltc2496_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + ltc2497core_remove(indio_dev); + + return 0; +} + +static const struct of_device_id ltc2496_of_match[] = { + { .compatible = "lltc,ltc2496", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltc2496_of_match); + +static struct spi_driver ltc2496_driver = { + .driver = { + .name = "ltc2496", + .of_match_table = of_match_ptr(ltc2496_of_match), + }, + .probe = ltc2496_probe, + .remove = ltc2496_remove, +}; +module_spi_driver(ltc2496_driver); + +MODULE_AUTHOR("Uwe Kleine-König <u.kleine-könig@pengutronix.de>"); +MODULE_DESCRIPTION("Linear Technology LTC2496 ADC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c new file mode 100644 index 000000000000..f5f7039caacc --- /dev/null +++ b/drivers/iio/adc/ltc2497-core.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ltc2497-core.c - Common code for Analog Devices/Linear Technology + * LTC2496 and LTC2497 ADCs + * + * Copyright (C) 2017 Analog Devices Inc. + */ + +#include <linux/delay.h> +#include <linux/iio/iio.h> +#include <linux/iio/driver.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> + +#include "ltc2497.h" + +#define LTC2497_SGL BIT(4) +#define LTC2497_DIFF 0 +#define LTC2497_SIGN BIT(3) + +static int ltc2497core_wait_conv(struct ltc2497core_driverdata *ddata) +{ + s64 time_elapsed; + + time_elapsed = ktime_ms_delta(ktime_get(), ddata->time_prev); + + if (time_elapsed < LTC2497_CONVERSION_TIME_MS) { + /* delay if conversion time not passed + * since last read or write + */ + if (msleep_interruptible( + LTC2497_CONVERSION_TIME_MS - time_elapsed)) + return -ERESTARTSYS; + + return 0; + } + + if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) { + /* We're in automatic mode - + * so the last reading is still not outdated + */ + return 0; + } + + return 1; +} + +static int ltc2497core_read(struct ltc2497core_driverdata *ddata, u8 address, int *val) +{ + int ret; + + ret = ltc2497core_wait_conv(ddata); + if (ret < 0) + return ret; + + if (ret || ddata->addr_prev != address) { + ret = ddata->result_and_measure(ddata, address, NULL); + if (ret < 0) + return ret; + ddata->addr_prev = address; + + if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS)) + return -ERESTARTSYS; + } + + ret = ddata->result_and_measure(ddata, address, val); + if (ret < 0) + return ret; + + ddata->time_prev = ktime_get(); + + return ret; +} + +static int ltc2497core_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&indio_dev->mlock); + ret = ltc2497core_read(ddata, chan->address, val); + mutex_unlock(&indio_dev->mlock); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + ret = regulator_get_voltage(ddata->ref); + if (ret < 0) + return ret; + + *val = ret / 1000; + *val2 = 17; + + return IIO_VAL_FRACTIONAL_LOG2; + + default: + return -EINVAL; + } +} + +#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) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \ + .channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\ + .address = (_addr | _chan), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .differential = 1, \ +} + +static const struct iio_chan_spec ltc2497core_channel[] = { + 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), + LTC2497_CHAN_DIFF(3, LTC2497_DIFF), + LTC2497_CHAN_DIFF(4, LTC2497_DIFF), + LTC2497_CHAN_DIFF(5, LTC2497_DIFF), + LTC2497_CHAN_DIFF(6, LTC2497_DIFF), + LTC2497_CHAN_DIFF(7, LTC2497_DIFF), + LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN), +}; + +static const struct iio_info ltc2497core_info = { + .read_raw = ltc2497core_read_raw, +}; + +int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) +{ + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); + int ret; + + indio_dev->dev.parent = dev; + indio_dev->name = dev_name(dev); + indio_dev->info = <c2497core_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ltc2497core_channel; + indio_dev->num_channels = ARRAY_SIZE(ltc2497core_channel); + + ret = ddata->result_and_measure(ddata, LTC2497_CONFIG_DEFAULT, NULL); + if (ret < 0) + return ret; + + ddata->ref = devm_regulator_get(dev, "vref"); + if (IS_ERR(ddata->ref)) { + if (PTR_ERR(ddata->ref) != -EPROBE_DEFER) + dev_err(dev, "Failed to get vref regulator: %pe\n", + ddata->ref); + + return PTR_ERR(ddata->ref); + } + + ret = regulator_enable(ddata->ref); + if (ret < 0) { + dev_err(dev, "Failed to enable vref regulator: %pe\n", + ERR_PTR(ret)); + return ret; + } + + if (dev->platform_data) { + struct iio_map *plat_data; + + plat_data = (struct iio_map *)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; + } + } + + ddata->addr_prev = LTC2497_CONFIG_DEFAULT; + ddata->time_prev = ktime_get(); + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto err_array_unregister; + + return 0; + +err_array_unregister: + iio_map_array_unregister(indio_dev); + +err_regulator_disable: + regulator_disable(ddata->ref); + + return ret; +} +EXPORT_SYMBOL_NS(ltc2497core_probe, LTC2497); + +void ltc2497core_remove(struct iio_dev *indio_dev) +{ + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + iio_map_array_unregister(indio_dev); + + regulator_disable(ddata->ref); +} +EXPORT_SYMBOL_NS(ltc2497core_remove, LTC2497); + +MODULE_DESCRIPTION("common code for LTC2496/LTC2497 drivers"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c index 470406032720..5db63d7c6bc5 100644 --- a/drivers/iio/adc/ltc2497.c +++ b/drivers/iio/adc/ltc2497.c @@ -7,27 +7,18 @@ * Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf */ -#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> -#include <linux/regulator/consumer.h> -#define LTC2497_ENABLE 0xA0 -#define LTC2497_SGL BIT(4) -#define LTC2497_DIFF 0 -#define LTC2497_SIGN BIT(3) -#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE -#define LTC2497_CONVERSION_TIME_MS 150ULL +#include "ltc2497.h" -struct ltc2497_st { +struct ltc2497_driverdata { + /* this must be the first member */ + struct ltc2497core_driverdata common_ddata; struct i2c_client *client; - struct regulator *ref; - ktime_t time_prev; - u8 addr_prev; /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. @@ -35,232 +26,59 @@ struct ltc2497_st { __be32 buf ____cacheline_aligned; }; -static int ltc2497_wait_conv(struct ltc2497_st *st) +static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata, + u8 address, int *val) { - s64 time_elapsed; - - time_elapsed = ktime_ms_delta(ktime_get(), st->time_prev); - - if (time_elapsed < LTC2497_CONVERSION_TIME_MS) { - /* delay if conversion time not passed - * since last read or write - */ - if (msleep_interruptible( - LTC2497_CONVERSION_TIME_MS - time_elapsed)) - return -ERESTARTSYS; - - return 0; - } - - if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) { - /* We're in automatic mode - - * so the last reading is stil not outdated - */ - return 0; - } - - return 1; -} - -static int ltc2497_read(struct ltc2497_st *st, u8 address, int *val) -{ - struct i2c_client *client = st->client; - int ret; - - ret = ltc2497_wait_conv(st); - if (ret < 0) - return ret; - - if (ret || st->addr_prev != address) { - ret = i2c_smbus_write_byte(st->client, - LTC2497_ENABLE | address); - if (ret < 0) - return ret; - st->addr_prev = address; - if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS)) - return -ERESTARTSYS; - } - ret = i2c_master_recv(client, (char *)&st->buf, 3); - if (ret < 0) { - dev_err(&client->dev, "i2c_master_recv failed\n"); - return ret; - } - st->time_prev = ktime_get(); - - /* convert and shift the result, - * and finally convert from offset binary to signed integer - */ - *val = (be32_to_cpu(st->buf) >> 14) - (1 << 17); - - return ret; -} - -static int ltc2497_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) -{ - struct ltc2497_st *st = iio_priv(indio_dev); + struct ltc2497_driverdata *st = + container_of(ddata, struct ltc2497_driverdata, common_ddata); int ret; - switch (mask) { - case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - ret = ltc2497_read(st, chan->address, val); - mutex_unlock(&indio_dev->mlock); - if (ret < 0) - return ret; - - return IIO_VAL_INT; - - case IIO_CHAN_INFO_SCALE: - ret = regulator_get_voltage(st->ref); - if (ret < 0) + if (val) { + ret = i2c_master_recv(st->client, (char *)&st->buf, 3); + if (ret < 0) { + dev_err(&st->client->dev, "i2c_master_recv failed\n"); return ret; + } - *val = ret / 1000; - *val2 = 17; - - return IIO_VAL_FRACTIONAL_LOG2; - - default: - return -EINVAL; + *val = (be32_to_cpu(st->buf) >> 14) - (1 << 17); } -} -#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) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \ - .channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\ - .address = (_addr | _chan), \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .differential = 1, \ + ret = i2c_smbus_write_byte(st->client, + LTC2497_ENABLE | address); + if (ret) + dev_err(&st->client->dev, "i2c transfer failed: %pe\n", + ERR_PTR(ret)); + return ret; } -static const struct iio_chan_spec ltc2497_channel[] = { - 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), - LTC2497_CHAN_DIFF(3, LTC2497_DIFF), - LTC2497_CHAN_DIFF(4, LTC2497_DIFF), - LTC2497_CHAN_DIFF(5, LTC2497_DIFF), - LTC2497_CHAN_DIFF(6, LTC2497_DIFF), - LTC2497_CHAN_DIFF(7, LTC2497_DIFF), - LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN), -}; - -static const struct iio_info ltc2497_info = { - .read_raw = ltc2497_read_raw, -}; - static int ltc2497_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct iio_dev *indio_dev; - struct ltc2497_st *st; - struct iio_map *plat_data; - int ret; + struct ltc2497_driverdata *st; + struct device *dev = &client->dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE)) return -EOPNOTSUPP; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); st->client = client; + st->common_ddata.result_and_measure = ltc2497_result_and_measure; - indio_dev->dev.parent = &client->dev; - indio_dev->name = id->name; - indio_dev->info = <c2497_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ltc2497_channel; - indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel); - - st->ref = devm_regulator_get(&client->dev, "vref"); - if (IS_ERR(st->ref)) - return PTR_ERR(st->ref); - - ret = regulator_enable(st->ref); - 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_array_unregister; - - st->addr_prev = LTC2497_CONFIG_DEFAULT; - st->time_prev = ktime_get(); - - ret = iio_device_register(indio_dev); - if (ret < 0) - goto err_array_unregister; - - return 0; - -err_array_unregister: - iio_map_array_unregister(indio_dev); - -err_regulator_disable: - regulator_disable(st->ref); - - return ret; + return ltc2497core_probe(dev, indio_dev); } 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); + ltc2497core_remove(indio_dev); return 0; } diff --git a/drivers/iio/adc/ltc2497.h b/drivers/iio/adc/ltc2497.h new file mode 100644 index 000000000000..d0b42dd6b8ad --- /dev/null +++ b/drivers/iio/adc/ltc2497.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#define LTC2497_ENABLE 0xA0 +#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE +#define LTC2497_CONVERSION_TIME_MS 150ULL + +struct ltc2497core_driverdata { + struct regulator *ref; + ktime_t time_prev; + u8 addr_prev; + int (*result_and_measure)(struct ltc2497core_driverdata *ddata, + u8 address, int *val); +}; + +int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev); +void ltc2497core_remove(struct iio_dev *indio_dev); + +MODULE_IMPORT_NS(LTC2497); diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index da84adfdb819..02834ca3e1ce 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -63,12 +63,18 @@ enum max1027_id { max1027, max1029, max1031, + max1227, + max1229, + max1231, }; static const struct spi_device_id max1027_id[] = { {"max1027", max1027}, {"max1029", max1029}, {"max1031", max1031}, + {"max1227", max1227}, + {"max1229", max1229}, + {"max1231", max1231}, {} }; MODULE_DEVICE_TABLE(spi, max1027_id); @@ -78,12 +84,15 @@ static const struct of_device_id max1027_adc_dt_ids[] = { { .compatible = "maxim,max1027" }, { .compatible = "maxim,max1029" }, { .compatible = "maxim,max1031" }, + { .compatible = "maxim,max1227" }, + { .compatible = "maxim,max1229" }, + { .compatible = "maxim,max1231" }, {}, }; MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids); #endif -#define MAX1027_V_CHAN(index) \ +#define MAX1027_V_CHAN(index, depth) \ { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ @@ -93,7 +102,7 @@ MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids); .scan_index = index + 1, \ .scan_type = { \ .sign = 'u', \ - .realbits = 10, \ + .realbits = depth, \ .storagebits = 16, \ .shift = 2, \ .endianness = IIO_BE, \ @@ -115,52 +124,54 @@ MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids); }, \ } +#define MAX1X27_CHANNELS(depth) \ + MAX1027_T_CHAN, \ + MAX1027_V_CHAN(0, depth), \ + MAX1027_V_CHAN(1, depth), \ + MAX1027_V_CHAN(2, depth), \ + MAX1027_V_CHAN(3, depth), \ + MAX1027_V_CHAN(4, depth), \ + MAX1027_V_CHAN(5, depth), \ + MAX1027_V_CHAN(6, depth), \ + MAX1027_V_CHAN(7, depth) + +#define MAX1X29_CHANNELS(depth) \ + MAX1X27_CHANNELS(depth), \ + MAX1027_V_CHAN(8, depth), \ + MAX1027_V_CHAN(9, depth), \ + MAX1027_V_CHAN(10, depth), \ + MAX1027_V_CHAN(11, depth) + +#define MAX1X31_CHANNELS(depth) \ + MAX1X27_CHANNELS(depth), \ + MAX1X29_CHANNELS(depth), \ + MAX1027_V_CHAN(12, depth), \ + MAX1027_V_CHAN(13, depth), \ + MAX1027_V_CHAN(14, depth), \ + MAX1027_V_CHAN(15, depth) + static const struct iio_chan_spec max1027_channels[] = { - MAX1027_T_CHAN, - MAX1027_V_CHAN(0), - MAX1027_V_CHAN(1), - MAX1027_V_CHAN(2), - MAX1027_V_CHAN(3), - MAX1027_V_CHAN(4), - MAX1027_V_CHAN(5), - MAX1027_V_CHAN(6), - MAX1027_V_CHAN(7) + MAX1X27_CHANNELS(10), }; static const struct iio_chan_spec max1029_channels[] = { - MAX1027_T_CHAN, - MAX1027_V_CHAN(0), - MAX1027_V_CHAN(1), - MAX1027_V_CHAN(2), - MAX1027_V_CHAN(3), - MAX1027_V_CHAN(4), - MAX1027_V_CHAN(5), - MAX1027_V_CHAN(6), - MAX1027_V_CHAN(7), - MAX1027_V_CHAN(8), - MAX1027_V_CHAN(9), - MAX1027_V_CHAN(10), - MAX1027_V_CHAN(11) + MAX1X29_CHANNELS(10), }; static const struct iio_chan_spec max1031_channels[] = { - MAX1027_T_CHAN, - MAX1027_V_CHAN(0), - MAX1027_V_CHAN(1), - MAX1027_V_CHAN(2), - MAX1027_V_CHAN(3), - MAX1027_V_CHAN(4), - MAX1027_V_CHAN(5), - MAX1027_V_CHAN(6), - MAX1027_V_CHAN(7), - MAX1027_V_CHAN(8), - MAX1027_V_CHAN(9), - MAX1027_V_CHAN(10), - MAX1027_V_CHAN(11), - MAX1027_V_CHAN(12), - MAX1027_V_CHAN(13), - MAX1027_V_CHAN(14), - MAX1027_V_CHAN(15) + MAX1X31_CHANNELS(10), +}; + +static const struct iio_chan_spec max1227_channels[] = { + MAX1X27_CHANNELS(12), +}; + +static const struct iio_chan_spec max1229_channels[] = { + MAX1X29_CHANNELS(12), +}; + +static const struct iio_chan_spec max1231_channels[] = { + MAX1X31_CHANNELS(12), }; static const unsigned long max1027_available_scan_masks[] = { @@ -200,6 +211,21 @@ static const struct max1027_chip_info max1027_chip_info_tbl[] = { .num_channels = ARRAY_SIZE(max1031_channels), .available_scan_masks = max1031_available_scan_masks, }, + [max1227] = { + .channels = max1227_channels, + .num_channels = ARRAY_SIZE(max1227_channels), + .available_scan_masks = max1027_available_scan_masks, + }, + [max1229] = { + .channels = max1229_channels, + .num_channels = ARRAY_SIZE(max1229_channels), + .available_scan_masks = max1029_available_scan_masks, + }, + [max1231] = { + .channels = max1231_channels, + .num_channels = ARRAY_SIZE(max1231_channels), + .available_scan_masks = max1031_available_scan_masks, + }, }; struct max1027_state { @@ -284,7 +310,7 @@ static int max1027_read_raw(struct iio_dev *indio_dev, break; case IIO_VOLTAGE: *val = 2500; - *val2 = 10; + *val2 = chan->scan_type.realbits; ret = IIO_VAL_FRACTIONAL_LOG2; break; default: @@ -309,8 +335,11 @@ static int max1027_debugfs_reg_access(struct iio_dev *indio_dev, struct max1027_state *st = iio_priv(indio_dev); u8 *val = (u8 *)st->buffer; - if (readval != NULL) - return -EINVAL; + if (readval) { + int ret = spi_read(st->spi, val, 2); + *readval = be16_to_cpu(st->buffer[0]); + return ret; + } *val = (u8)writeval; return spi_write(st->spi, val, 1); @@ -427,34 +456,54 @@ static int max1027_probe(struct spi_device *spi) return -ENOMEM; } - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - &max1027_trigger_handler, NULL); - if (ret < 0) { - dev_err(&indio_dev->dev, "Failed to setup buffer\n"); - return ret; - } + if (spi->irq) { + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + &iio_pollfunc_store_time, + &max1027_trigger_handler, + NULL); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed to setup buffer\n"); + return ret; + } - st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-trigger", - indio_dev->name); - if (st->trig == NULL) { - ret = -ENOMEM; - dev_err(&indio_dev->dev, "Failed to allocate iio trigger\n"); - goto fail_trigger_alloc; - } + st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-trigger", + indio_dev->name); + if (st->trig == NULL) { + ret = -ENOMEM; + dev_err(&indio_dev->dev, + "Failed to allocate iio trigger\n"); + return ret; + } - st->trig->ops = &max1027_trigger_ops; - st->trig->dev.parent = &spi->dev; - iio_trigger_set_drvdata(st->trig, indio_dev); - iio_trigger_register(st->trig); + st->trig->ops = &max1027_trigger_ops; + st->trig->dev.parent = &spi->dev; + iio_trigger_set_drvdata(st->trig, indio_dev); + ret = devm_iio_trigger_register(&indio_dev->dev, + st->trig); + if (ret < 0) { + dev_err(&indio_dev->dev, + "Failed to register iio trigger\n"); + return ret; + } + + ret = devm_request_threaded_irq(&spi->dev, spi->irq, + iio_trigger_generic_data_rdy_poll, + NULL, + IRQF_TRIGGER_FALLING, + spi->dev.driver->name, + st->trig); + if (ret < 0) { + dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n"); + return ret; + } + } - ret = devm_request_threaded_irq(&spi->dev, spi->irq, - iio_trigger_generic_data_rdy_poll, - NULL, - IRQF_TRIGGER_FALLING, - spi->dev.driver->name, st->trig); + /* Internal reset */ + st->reg = MAX1027_RST_REG; + ret = spi_write(st->spi, &st->reg, 1); if (ret < 0) { - dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n"); - goto fail_dev_register; + dev_err(&indio_dev->dev, "Failed to reset the ADC\n"); + return ret; } /* Disable averaging */ @@ -462,34 +511,10 @@ static int max1027_probe(struct spi_device *spi) ret = spi_write(st->spi, &st->reg, 1); if (ret < 0) { dev_err(&indio_dev->dev, "Failed to configure averaging register\n"); - goto fail_dev_register; - } - - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&indio_dev->dev, "Failed to register iio device\n"); - goto fail_dev_register; + return ret; } - return 0; - -fail_dev_register: -fail_trigger_alloc: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; -} - -static int max1027_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - pr_debug("%s: remove(spi = 0x%p)\n", __func__, spi); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static struct spi_driver max1027_driver = { @@ -498,11 +523,10 @@ static struct spi_driver max1027_driver = { .of_match_table = of_match_ptr(max1027_adc_dt_ids), }, .probe = max1027_probe, - .remove = max1027_remove, .id_table = max1027_id, }; module_spi_driver(max1027_driver); MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>"); -MODULE_DESCRIPTION("MAX1027/MAX1029/MAX1031 ADC"); +MODULE_DESCRIPTION("MAX1X27/MAX1X29/MAX1X31 ADC"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c index da073d72f649..04d5ff7d2c8e 100644 --- a/drivers/iio/adc/max9611.c +++ b/drivers/iio/adc/max9611.c @@ -89,6 +89,12 @@ #define MAX9611_TEMP_SCALE_NUM 1000000 #define MAX9611_TEMP_SCALE_DIV 2083 +/* + * Conversion time is 2 ms (typically) at Ta=25 degreeC + * No maximum value is known, so play it safe. + */ +#define MAX9611_CONV_TIME_US_RANGE 3000, 3300 + struct max9611_dev { struct device *dev; struct i2c_client *i2c_client; @@ -109,22 +115,17 @@ enum max9611_conf_ids { * where data shall be read from */ static const unsigned int max9611_mux_conf[][2] = { - /* CONF_SENSE_1x */ - { MAX9611_MUX_SENSE_1x, MAX9611_REG_CSA_DATA }, - /* CONF_SENSE_4x */ - { MAX9611_MUX_SENSE_4x, MAX9611_REG_CSA_DATA }, - /* CONF_SENSE_8x */ - { MAX9611_MUX_SENSE_8x, MAX9611_REG_CSA_DATA }, - /* CONF_IN_VOLT */ - { MAX9611_INPUT_VOLT, MAX9611_REG_RS_DATA }, - /* CONF_TEMP */ - { MAX9611_MUX_TEMP, MAX9611_REG_TEMP_DATA }, + [CONF_SENSE_1x] = { MAX9611_MUX_SENSE_1x, MAX9611_REG_CSA_DATA }, + [CONF_SENSE_4x] = { MAX9611_MUX_SENSE_4x, MAX9611_REG_CSA_DATA }, + [CONF_SENSE_8x] = { MAX9611_MUX_SENSE_8x, MAX9611_REG_CSA_DATA }, + [CONF_IN_VOLT] = { MAX9611_INPUT_VOLT, MAX9611_REG_RS_DATA }, + [CONF_TEMP] = { MAX9611_MUX_TEMP, MAX9611_REG_TEMP_DATA }, }; enum max9611_csa_gain { - CSA_GAIN_1x, - CSA_GAIN_4x, - CSA_GAIN_8x, + CSA_GAIN_1x = CONF_SENSE_1x, + CSA_GAIN_4x = CONF_SENSE_4x, + CSA_GAIN_8x = CONF_SENSE_8x, }; enum max9611_csa_gain_params { @@ -142,18 +143,9 @@ enum max9611_csa_gain_params { * value; use this structure to retrieve the correct LSB and offset values. */ static const unsigned int max9611_gain_conf[][2] = { - { /* [0] CSA_GAIN_1x */ - MAX9611_CSA_1X_LSB_nV, - MAX9611_CSA_1X_OFFS_RAW, - }, - { /* [1] CSA_GAIN_4x */ - MAX9611_CSA_4X_LSB_nV, - MAX9611_CSA_4X_OFFS_RAW, - }, - { /* [2] CSA_GAIN_8x */ - MAX9611_CSA_8X_LSB_nV, - MAX9611_CSA_8X_OFFS_RAW, - }, + [CSA_GAIN_1x] = { MAX9611_CSA_1X_LSB_nV, MAX9611_CSA_1X_OFFS_RAW, }, + [CSA_GAIN_4x] = { MAX9611_CSA_4X_LSB_nV, MAX9611_CSA_4X_OFFS_RAW, }, + [CSA_GAIN_8x] = { MAX9611_CSA_8X_LSB_nV, MAX9611_CSA_8X_OFFS_RAW, }, }; enum max9611_chan_addrs { @@ -236,11 +228,9 @@ static int max9611_read_single(struct max9611_dev *max9611, return ret; } - /* - * need a delay here to make register configuration - * stabilize. 1 msec at least, from empirical testing. - */ - usleep_range(1000, 2000); + /* need a delay here to make register configuration stabilize. */ + + usleep_range(MAX9611_CONV_TIME_US_RANGE); ret = i2c_smbus_read_word_swapped(max9611->i2c_client, reg_addr); if (ret < 0) { @@ -507,7 +497,7 @@ static int max9611_init(struct max9611_dev *max9611) MAX9611_REG_CTRL2, 0); return ret; } - usleep_range(1000, 2000); + usleep_range(MAX9611_CONV_TIME_US_RANGE); return 0; } diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 38bf10085696..465c7625a55a 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -164,7 +164,7 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, case mcp3550_60: case mcp3551: case mcp3553: { - u32 raw = be32_to_cpup((u32 *)adc->rx_buf); + u32 raw = be32_to_cpup((__be32 *)adc->rx_buf); if (!(adc->spi->mode & SPI_CPOL)) raw <<= 1; /* strip Data Ready bit in SPI mode 0,0 */ diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c index 3b2fbb7ce431..196c8226381e 100644 --- a/drivers/iio/adc/men_z188_adc.c +++ b/drivers/iio/adc/men_z188_adc.c @@ -167,3 +167,4 @@ MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IIO ADC driver for MEN 16z188 ADC Core"); MODULE_ALIAS("mcb:16z188"); +MODULE_IMPORT_NS(MCB); diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 7b28d045d271..22a470db9ef8 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -1187,7 +1187,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev) const struct meson_sar_adc_data *match_data; struct meson_sar_adc_priv *priv; struct iio_dev *indio_dev; - struct resource *res; void __iomem *base; int irq, ret; @@ -1214,11 +1213,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &meson_sar_adc_iio_info; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); + priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, + priv->param->regmap_config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + irq = irq_of_parse_and_map(pdev->dev.of_node, 0); if (!irq) return -EINVAL; @@ -1228,11 +1231,6 @@ static int meson_sar_adc_probe(struct platform_device *pdev) if (ret) return ret; - priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, - priv->param->regmap_config); - if (IS_ERR(priv->regmap)) - return PTR_ERR(priv->regmap); - priv->clkin = devm_clk_get(&pdev->dev, "clkin"); if (IS_ERR(priv->clkin)) { dev_err(&pdev->dev, "failed to get clkin\n"); diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index 7bbb64ca3b32..a4776d924f3a 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -237,7 +237,6 @@ static int mt6577_auxadc_probe(struct platform_device *pdev) { struct mt6577_auxadc_device *adc_dev; unsigned long adc_clk_rate; - struct resource *res; struct iio_dev *indio_dev; int ret; @@ -253,8 +252,7 @@ static int mt6577_auxadc_probe(struct platform_device *pdev) indio_dev->channels = mt6577_auxadc_iio_channels; indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res); + adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(adc_dev->reg_base)) { dev_err(&pdev->dev, "failed to get auxadc base address\n"); return PTR_ERR(adc_dev->reg_base); diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c index 193b3b81de4d..a6170a37ebe8 100644 --- a/drivers/iio/adc/npcm_adc.c +++ b/drivers/iio/adc/npcm_adc.c @@ -183,7 +183,6 @@ static int npcm_adc_probe(struct platform_device *pdev) int irq; u32 div; u32 reg_con; - struct resource *res; struct npcm_adc *info; struct iio_dev *indio_dev; struct device *dev = &pdev->dev; @@ -196,8 +195,7 @@ static int npcm_adc_probe(struct platform_device *pdev) info->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - info->regs = devm_ioremap_resource(&pdev->dev, res); + info->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(info->regs)) return PTR_ERR(info->regs); @@ -225,7 +223,6 @@ static int npcm_adc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; goto err_disable_clk; } diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c index dcd7fb5b9fb2..2bb78d1c4daa 100644 --- a/drivers/iio/adc/qcom-vadc-common.c +++ b/drivers/iio/adc/qcom-vadc-common.c @@ -6,6 +6,7 @@ #include <linux/log2.h> #include <linux/err.h> #include <linux/module.h> +#include <linux/units.h> #include "qcom-vadc-common.h" @@ -236,8 +237,7 @@ static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph, voltage = 0; } - voltage -= KELVINMIL_CELSIUSMIL; - *result_mdec = voltage; + *result_mdec = milli_kelvin_to_millicelsius(voltage); return 0; } @@ -325,7 +325,7 @@ static int qcom_vadc_scale_hw_calib_die_temp( { *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code, prescale, data, 2); - *result_mdec -= KELVINMIL_CELSIUSMIL; + *result_mdec = milli_kelvin_to_millicelsius(*result_mdec); return 0; } diff --git a/drivers/iio/adc/qcom-vadc-common.h b/drivers/iio/adc/qcom-vadc-common.h index bbb1fa02b382..e074902a24cc 100644 --- a/drivers/iio/adc/qcom-vadc-common.h +++ b/drivers/iio/adc/qcom-vadc-common.h @@ -38,7 +38,6 @@ #define VADC_AVG_SAMPLES_MAX 512 #define ADC5_AVG_SAMPLES_MAX 16 -#define KELVINMIL_CELSIUSMIL 273150 #define PMIC5_CHG_TEMP_SCALE_FACTOR 377500 #define PMIC5_SMB_TEMP_CONSTANT 419400 #define PMIC5_SMB_TEMP_SCALE_FACTOR 356 diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index c37f201294b2..63ce743ee7af 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -481,7 +481,6 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rcar_gyroadc *priv; struct iio_dev *indio_dev; - struct resource *mem; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); @@ -491,8 +490,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) priv = iio_priv(indio_dev); priv->dev = dev; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->regs = devm_ioremap_resource(dev, mem); + priv->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs)) return PTR_ERR(priv->regs); diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index dd8299831e09..582ba047c4a6 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -244,10 +244,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev) init_completion(&info->completion); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, 0, dev_name(&pdev->dev), info); diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index f7f7a18904b4..66b387f9b36d 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -3,7 +3,6 @@ #include <linux/hwspinlock.h> #include <linux/iio/iio.h> -#include <linux/interrupt.h> #include <linux/module.h> #include <linux/nvmem-consumer.h> #include <linux/of.h> @@ -46,14 +45,18 @@ /* Bits definitions for SC27XX_ADC_INT_CLR registers */ #define SC27XX_ADC_IRQ_CLR BIT(0) +/* Bits definitions for SC27XX_ADC_INT_RAW registers */ +#define SC27XX_ADC_IRQ_RAW BIT(0) + /* Mask definition for SC27XX_ADC_DATA register */ #define SC27XX_ADC_DATA_MASK GENMASK(11, 0) /* Timeout (ms) for the trylock of hardware spinlocks */ #define SC27XX_ADC_HWLOCK_TIMEOUT 5000 -/* Timeout (ms) for ADC data conversion according to ADC datasheet */ -#define SC27XX_ADC_RDY_TIMEOUT 100 +/* Timeout (us) for ADC data conversion according to ADC datasheet */ +#define SC27XX_ADC_RDY_TIMEOUT 1000000 +#define SC27XX_ADC_POLL_RAW_STATUS 500 /* Maximum ADC channel number */ #define SC27XX_ADC_CHANNEL_MAX 32 @@ -72,10 +75,8 @@ struct sc27xx_adc_data { * subsystems which will access the unique ADC controller. */ struct hwspinlock *hwlock; - struct completion completion; int channel_scale[SC27XX_ADC_CHANNEL_MAX]; u32 base; - int value; int irq; }; @@ -188,9 +189,7 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, int scale, int *val) { int ret; - u32 tmp; - - reinit_completion(&data->completion); + u32 tmp, value, status; ret = hwspin_lock_timeout_raw(data->hwlock, SC27XX_ADC_HWLOCK_TIMEOUT); if (ret) { @@ -203,6 +202,11 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, if (ret) goto unlock_adc; + ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, + SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); + if (ret) + goto disable_adc; + /* Configure the channel id and scale */ tmp = (scale << SC27XX_ADC_SCALE_SHIFT) & SC27XX_ADC_SCALE_MASK; tmp |= channel & SC27XX_ADC_CHN_ID_MASK; @@ -226,15 +230,22 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, if (ret) goto disable_adc; - ret = wait_for_completion_timeout(&data->completion, - msecs_to_jiffies(SC27XX_ADC_RDY_TIMEOUT)); - if (!ret) { - dev_err(data->dev, "read ADC data timeout\n"); - ret = -ETIMEDOUT; - } else { - ret = 0; + ret = regmap_read_poll_timeout(data->regmap, + data->base + SC27XX_ADC_INT_RAW, + status, (status & SC27XX_ADC_IRQ_RAW), + SC27XX_ADC_POLL_RAW_STATUS, + SC27XX_ADC_RDY_TIMEOUT); + if (ret) { + dev_err(data->dev, "read adc timeout, status = 0x%x\n", status); + goto disable_adc; } + ret = regmap_read(data->regmap, data->base + SC27XX_ADC_DATA, &value); + if (ret) + goto disable_adc; + + value &= SC27XX_ADC_DATA_MASK; + disable_adc: regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, SC27XX_ADC_EN, 0); @@ -242,32 +253,11 @@ unlock_adc: hwspin_unlock_raw(data->hwlock); if (!ret) - *val = data->value; + *val = value; return ret; } -static irqreturn_t sc27xx_adc_isr(int irq, void *dev_id) -{ - struct sc27xx_adc_data *data = dev_id; - int ret; - - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, - SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); - if (ret) - return IRQ_RETVAL(ret); - - ret = regmap_read(data->regmap, data->base + SC27XX_ADC_DATA, - &data->value); - if (ret) - return IRQ_RETVAL(ret); - - data->value &= SC27XX_ADC_DATA_MASK; - complete(&data->completion); - - return IRQ_HANDLED; -} - static void sc27xx_adc_volt_ratio(struct sc27xx_adc_data *data, int channel, int scale, u32 *div_numerator, u32 *div_denominator) @@ -454,11 +444,6 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data) if (ret) goto disable_adc; - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_EN, - SC27XX_ADC_IRQ_EN, SC27XX_ADC_IRQ_EN); - if (ret) - goto disable_clk; - /* ADC channel scales' calibration from nvmem device */ ret = sc27xx_adc_scale_calibration(data, true); if (ret) @@ -484,9 +469,6 @@ static void sc27xx_adc_disable(void *_data) { struct sc27xx_adc_data *data = _data; - regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_EN, - SC27XX_ADC_IRQ_EN, 0); - /* Disable ADC work clock and controller clock */ regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN, SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0); @@ -495,97 +477,71 @@ static void sc27xx_adc_disable(void *_data) SC27XX_MODULE_ADC_EN, 0); } -static void sc27xx_adc_free_hwlock(void *_data) -{ - struct hwspinlock *hwlock = _data; - - hwspin_lock_free(hwlock); -} - static int sc27xx_adc_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct sc27xx_adc_data *sc27xx_data; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*sc27xx_data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*sc27xx_data)); if (!indio_dev) return -ENOMEM; sc27xx_data = iio_priv(indio_dev); - sc27xx_data->regmap = dev_get_regmap(pdev->dev.parent, NULL); + sc27xx_data->regmap = dev_get_regmap(dev->parent, NULL); if (!sc27xx_data->regmap) { - dev_err(&pdev->dev, "failed to get ADC regmap\n"); + dev_err(dev, "failed to get ADC regmap\n"); return -ENODEV; } ret = of_property_read_u32(np, "reg", &sc27xx_data->base); if (ret) { - dev_err(&pdev->dev, "failed to get ADC base address\n"); + dev_err(dev, "failed to get ADC base address\n"); return ret; } sc27xx_data->irq = platform_get_irq(pdev, 0); - if (sc27xx_data->irq < 0) { - dev_err(&pdev->dev, "failed to get ADC irq number\n"); + if (sc27xx_data->irq < 0) return sc27xx_data->irq; - } ret = of_hwspin_lock_get_id(np, 0); if (ret < 0) { - dev_err(&pdev->dev, "failed to get hwspinlock id\n"); + dev_err(dev, "failed to get hwspinlock id\n"); return ret; } - sc27xx_data->hwlock = hwspin_lock_request_specific(ret); + sc27xx_data->hwlock = devm_hwspin_lock_request_specific(dev, ret); if (!sc27xx_data->hwlock) { - dev_err(&pdev->dev, "failed to request hwspinlock\n"); + dev_err(dev, "failed to request hwspinlock\n"); return -ENXIO; } - ret = devm_add_action(&pdev->dev, sc27xx_adc_free_hwlock, - sc27xx_data->hwlock); - if (ret) { - sc27xx_adc_free_hwlock(sc27xx_data->hwlock); - dev_err(&pdev->dev, "failed to add hwspinlock action\n"); - return ret; - } - - init_completion(&sc27xx_data->completion); - sc27xx_data->dev = &pdev->dev; + sc27xx_data->dev = dev; ret = sc27xx_adc_enable(sc27xx_data); if (ret) { - dev_err(&pdev->dev, "failed to enable ADC module\n"); - return ret; - } - - ret = devm_add_action(&pdev->dev, sc27xx_adc_disable, sc27xx_data); - if (ret) { - sc27xx_adc_disable(sc27xx_data); - dev_err(&pdev->dev, "failed to add ADC disable action\n"); + dev_err(dev, "failed to enable ADC module\n"); return ret; } - ret = devm_request_threaded_irq(&pdev->dev, sc27xx_data->irq, NULL, - sc27xx_adc_isr, IRQF_ONESHOT, - pdev->name, sc27xx_data); + ret = devm_add_action_or_reset(dev, sc27xx_adc_disable, sc27xx_data); if (ret) { - dev_err(&pdev->dev, "failed to request ADC irq\n"); + dev_err(dev, "failed to add ADC disable action\n"); return ret; } - indio_dev->dev.parent = &pdev->dev; - indio_dev->name = dev_name(&pdev->dev); + indio_dev->dev.parent = dev; + indio_dev->name = dev_name(dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &sc27xx_info; indio_dev->channels = sc27xx_channels; indio_dev->num_channels = ARRAY_SIZE(sc27xx_channels); - ret = devm_iio_device_register(&pdev->dev, indio_dev); + ret = devm_iio_device_register(dev, indio_dev); if (ret) - dev_err(&pdev->dev, "could not register iio (ADC)"); + dev_err(dev, "could not register iio (ADC)"); return ret; } diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c index a33d0a4cc088..0ad536494e8f 100644 --- a/drivers/iio/adc/spear_adc.c +++ b/drivers/iio/adc/spear_adc.c @@ -260,7 +260,6 @@ static int spear_adc_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; struct spear_adc_state *st; - struct resource *res; struct iio_dev *indio_dev = NULL; int ret = -ENODEV; int irq; @@ -279,8 +278,7 @@ static int spear_adc_probe(struct platform_device *pdev) * (e.g. SPEAr3xx). Let's provide two register base addresses * to support multi-arch kernels. */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - st->adc_base_spear6xx = devm_ioremap_resource(&pdev->dev, res); + st->adc_base_spear6xx = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(st->adc_base_spear6xx)) return PTR_ERR(st->adc_base_spear6xx); @@ -301,7 +299,6 @@ static int spear_adc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; goto errout2; } diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 1f7ce5186dfc..2df88d2b880a 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -14,50 +14,38 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqdesc.h> #include <linux/irqdomain.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/pm_runtime.h> +#include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include "stm32-adc-core.h" -/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */ -#define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00) -#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04) - -/* STM32F4_ADC_CSR - bit fields */ -#define STM32F4_EOC3 BIT(17) -#define STM32F4_EOC2 BIT(9) -#define STM32F4_EOC1 BIT(1) - -/* STM32F4_ADC_CCR - bit fields */ -#define STM32F4_ADC_ADCPRE_SHIFT 16 -#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16) - -/* 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) +#define STM32_ADC_CORE_SLEEP_DELAY_MS 2000 -/* STM32H7_ADC_CSR - bit fields */ -#define STM32H7_EOC_SLV BIT(18) -#define STM32H7_EOC_MST BIT(2) +/* SYSCFG registers */ +#define STM32MP1_SYSCFG_PMCSETR 0x04 +#define STM32MP1_SYSCFG_PMCCLRR 0x44 -/* 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) +/* SYSCFG bit fields */ +#define STM32MP1_SYSCFG_ANASWVDD_MASK BIT(9) -#define STM32_ADC_CORE_SLEEP_DELAY_MS 2000 +/* SYSCFG capability flags */ +#define HAS_VBOOSTER BIT(0) +#define HAS_ANASWVDD BIT(1) /** - * stm32_adc_common_regs - stm32 common registers, compatible dependent data + * struct stm32_adc_common_regs - stm32 common registers * @csr: common status register offset * @ccr: common control 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 + * @eoc1_msk: adc1 end of conversion flag in @csr + * @eoc2_msk: adc2 end of conversion flag in @csr + * @eoc3_msk: adc3 end of conversion flag in @csr + * @ier: interrupt enable register offset for each adc + * @eocie_msk: end of conversion interrupt enable mask in @ier */ struct stm32_adc_common_regs { u32 csr; @@ -65,20 +53,24 @@ struct stm32_adc_common_regs { u32 eoc1_msk; u32 eoc2_msk; u32 eoc3_msk; + u32 ier; + u32 eocie_msk; }; struct stm32_adc_priv; /** - * stm32_adc_priv_cfg - stm32 core compatible configuration data + * struct stm32_adc_priv_cfg - stm32 core compatible configuration data * @regs: common registers for all instances * @clk_sel: clock selection routine * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) + * @has_syscfg: SYSCFG capability flags */ struct stm32_adc_priv_cfg { const struct stm32_adc_common_regs *regs; int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); u32 max_clk_rate_hz; + unsigned int has_syscfg; }; /** @@ -87,22 +79,34 @@ struct stm32_adc_priv_cfg { * @domain: irq domain reference * @aclk: clock reference for the analog circuitry * @bclk: bus clock common for all ADCs, depends on part used + * @max_clk_rate: desired maximum clock rate + * @booster: booster supply reference + * @vdd: vdd supply reference * @vdda: vdda analog supply reference * @vref: regulator reference + * @vdd_uv: vdd supply voltage (microvolts) + * @vdda_uv: vdda supply voltage (microvolts) * @cfg: compatible configuration data * @common: common data for all ADC instances * @ccr_bak: backup CCR in low power mode + * @syscfg: reference to syscon, system control registers */ struct stm32_adc_priv { int irq[STM32_ADC_MAX_ADCS]; struct irq_domain *domain; struct clk *aclk; struct clk *bclk; + u32 max_clk_rate; + struct regulator *booster; + struct regulator *vdd; struct regulator *vdda; struct regulator *vref; + int vdd_uv; + int vdda_uv; const struct stm32_adc_priv_cfg *cfg; struct stm32_adc_common common; u32 ccr_bak; + struct regmap *syscfg; }; static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com) @@ -115,6 +119,7 @@ static int stm32f4_pclk_div[] = {2, 4, 6, 8}; /** * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler + * @pdev: platform device * @priv: stm32 ADC core private data * Select clock prescaler used for analog conversions, before using ADC. */ @@ -138,7 +143,7 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev, } for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) { - if ((rate / stm32f4_pclk_div[i]) <= priv->cfg->max_clk_rate_hz) + if ((rate / stm32f4_pclk_div[i]) <= priv->max_clk_rate) break; } if (i >= ARRAY_SIZE(stm32f4_pclk_div)) { @@ -227,7 +232,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, if (ckmode) continue; - if ((rate / div) <= priv->cfg->max_clk_rate_hz) + if ((rate / div) <= priv->max_clk_rate) goto out; } } @@ -247,7 +252,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, if (!ckmode) continue; - if ((rate / div) <= priv->cfg->max_clk_rate_hz) + if ((rate / div) <= priv->max_clk_rate) goto out; } @@ -275,19 +280,37 @@ out: static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { .csr = STM32F4_ADC_CSR, .ccr = STM32F4_ADC_CCR, - .eoc1_msk = STM32F4_EOC1, - .eoc2_msk = STM32F4_EOC2, - .eoc3_msk = STM32F4_EOC3, + .eoc1_msk = STM32F4_EOC1 | STM32F4_OVR1, + .eoc2_msk = STM32F4_EOC2 | STM32F4_OVR2, + .eoc3_msk = STM32F4_EOC3 | STM32F4_OVR3, + .ier = STM32F4_ADC_CR1, + .eocie_msk = STM32F4_EOCIE | STM32F4_OVRIE, }; /* STM32H7 common registers definitions */ static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { .csr = STM32H7_ADC_CSR, .ccr = STM32H7_ADC_CCR, - .eoc1_msk = STM32H7_EOC_MST, - .eoc2_msk = STM32H7_EOC_SLV, + .eoc1_msk = STM32H7_EOC_MST | STM32H7_OVR_MST, + .eoc2_msk = STM32H7_EOC_SLV | STM32H7_OVR_SLV, + .ier = STM32H7_ADC_IER, + .eocie_msk = STM32H7_EOCIE | STM32H7_OVRIE, }; +static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = { + 0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2, +}; + +static unsigned int stm32_adc_eoc_enabled(struct stm32_adc_priv *priv, + unsigned int adc) +{ + u32 ier, offset = stm32_adc_offset[adc]; + + ier = readl_relaxed(priv->common.base + offset + priv->cfg->regs->ier); + + return ier & priv->cfg->regs->eocie_msk; +} + /* ADC common interrupt for all instances */ static void stm32_adc_irq_handler(struct irq_desc *desc) { @@ -298,13 +321,28 @@ static void stm32_adc_irq_handler(struct irq_desc *desc) chained_irq_enter(chip, desc); status = readl_relaxed(priv->common.base + priv->cfg->regs->csr); - if (status & priv->cfg->regs->eoc1_msk) + /* + * End of conversion may be handled by using IRQ or DMA. There may be a + * race here when two conversions complete at the same time on several + * ADCs. EOC may be read 'set' for several ADCs, with: + * - an ADC configured to use DMA (EOC triggers the DMA request, and + * is then automatically cleared by DR read in hardware) + * - an ADC configured to use IRQs (EOCIE bit is set. The handler must + * be called in this case) + * So both EOC status bit in CSR and EOCIE control bit must be checked + * before invoking the interrupt handler (e.g. call ISR only for + * IRQ-enabled ADCs). + */ + if (status & priv->cfg->regs->eoc1_msk && + stm32_adc_eoc_enabled(priv, 0)) generic_handle_irq(irq_find_mapping(priv->domain, 0)); - if (status & priv->cfg->regs->eoc2_msk) + if (status & priv->cfg->regs->eoc2_msk && + stm32_adc_eoc_enabled(priv, 1)) generic_handle_irq(irq_find_mapping(priv->domain, 1)); - if (status & priv->cfg->regs->eoc3_msk) + if (status & priv->cfg->regs->eoc3_msk && + stm32_adc_eoc_enabled(priv, 2)) generic_handle_irq(irq_find_mapping(priv->domain, 2)); chained_irq_exit(chip, desc); @@ -349,7 +387,6 @@ static int stm32_adc_irq_probe(struct platform_device *pdev, */ if (i && priv->irq[i] == -ENXIO) continue; - dev_err(&pdev->dev, "failed to get irq\n"); return priv->irq[i]; } @@ -390,6 +427,82 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, } } +static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv, + struct device *dev) +{ + int ret; + + /* + * On STM32H7 and STM32MP1, the ADC inputs are multiplexed with analog + * switches (via PCSEL) which have reduced performances when their + * supply is below 2.7V (vdda by default): + * - Voltage booster can be used, to get full ADC performances + * (increases power consumption). + * - Vdd can be used to supply them, if above 2.7V (STM32MP1 only). + * + * Recommended settings for ANASWVDD and EN_BOOSTER: + * - vdda < 2.7V but vdd > 2.7V: ANASWVDD = 1, EN_BOOSTER = 0 (stm32mp1) + * - vdda < 2.7V and vdd < 2.7V: ANASWVDD = 0, EN_BOOSTER = 1 + * - vdda >= 2.7V: ANASWVDD = 0, EN_BOOSTER = 0 (default) + */ + if (priv->vdda_uv < 2700000) { + if (priv->syscfg && priv->vdd_uv > 2700000) { + ret = regulator_enable(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd enable failed %d\n", ret); + return ret; + } + + ret = regmap_write(priv->syscfg, + STM32MP1_SYSCFG_PMCSETR, + STM32MP1_SYSCFG_ANASWVDD_MASK); + if (ret < 0) { + regulator_disable(priv->vdd); + dev_err(dev, "vdd select failed, %d\n", ret); + return ret; + } + dev_dbg(dev, "analog switches supplied by vdd\n"); + + return 0; + } + + if (priv->booster) { + /* + * This is optional, as this is a trade-off between + * analog performance and power consumption. + */ + ret = regulator_enable(priv->booster); + if (ret < 0) { + dev_err(dev, "booster enable failed %d\n", ret); + return ret; + } + dev_dbg(dev, "analog switches supplied by booster\n"); + + return 0; + } + } + + /* Fallback using vdda (default), nothing to do */ + dev_dbg(dev, "analog switches supplied by vdda (%d uV)\n", + priv->vdda_uv); + + return 0; +} + +static void stm32_adc_core_switches_supply_dis(struct stm32_adc_priv *priv) +{ + if (priv->vdda_uv < 2700000) { + if (priv->syscfg && priv->vdd_uv > 2700000) { + regmap_write(priv->syscfg, STM32MP1_SYSCFG_PMCCLRR, + STM32MP1_SYSCFG_ANASWVDD_MASK); + regulator_disable(priv->vdd); + return; + } + if (priv->booster) + regulator_disable(priv->booster); + } +} + static int stm32_adc_core_hw_start(struct device *dev) { struct stm32_adc_common *common = dev_get_drvdata(dev); @@ -402,10 +515,21 @@ static int stm32_adc_core_hw_start(struct device *dev) return ret; } + ret = regulator_get_voltage(priv->vdda); + if (ret < 0) { + dev_err(dev, "vdda get voltage failed, %d\n", ret); + goto err_vdda_disable; + } + priv->vdda_uv = ret; + + ret = stm32_adc_core_switches_supply_en(priv, dev); + if (ret < 0) + goto err_vdda_disable; + ret = regulator_enable(priv->vref); if (ret < 0) { dev_err(dev, "vref enable failed\n"); - goto err_vdda_disable; + goto err_switches_dis; } if (priv->bclk) { @@ -433,6 +557,8 @@ err_bclk_disable: clk_disable_unprepare(priv->bclk); err_regulator_disable: regulator_disable(priv->vref); +err_switches_dis: + stm32_adc_core_switches_supply_dis(priv); err_vdda_disable: regulator_disable(priv->vdda); @@ -451,15 +577,87 @@ static void stm32_adc_core_hw_stop(struct device *dev) if (priv->bclk) clk_disable_unprepare(priv->bclk); regulator_disable(priv->vref); + stm32_adc_core_switches_supply_dis(priv); regulator_disable(priv->vdda); } +static int stm32_adc_core_switches_probe(struct device *dev, + struct stm32_adc_priv *priv) +{ + struct device_node *np = dev->of_node; + int ret; + + /* Analog switches supply can be controlled by syscfg (optional) */ + priv->syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(priv->syscfg)) { + ret = PTR_ERR(priv->syscfg); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Can't probe syscfg: %d\n", ret); + return ret; + } + priv->syscfg = NULL; + } + + /* Booster can be used to supply analog switches (optional) */ + if (priv->cfg->has_syscfg & HAS_VBOOSTER && + of_property_read_bool(np, "booster-supply")) { + priv->booster = devm_regulator_get_optional(dev, "booster"); + if (IS_ERR(priv->booster)) { + ret = PTR_ERR(priv->booster); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "can't get booster %d\n", + ret); + return ret; + } + priv->booster = NULL; + } + } + + /* Vdd can be used to supply analog switches (optional) */ + if (priv->cfg->has_syscfg & HAS_ANASWVDD && + of_property_read_bool(np, "vdd-supply")) { + priv->vdd = devm_regulator_get_optional(dev, "vdd"); + if (IS_ERR(priv->vdd)) { + ret = PTR_ERR(priv->vdd); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "can't get vdd %d\n", ret); + return ret; + } + priv->vdd = NULL; + } + } + + if (priv->vdd) { + ret = regulator_enable(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd enable failed %d\n", ret); + return ret; + } + + ret = regulator_get_voltage(priv->vdd); + if (ret < 0) { + dev_err(dev, "vdd get voltage failed %d\n", ret); + regulator_disable(priv->vdd); + return ret; + } + priv->vdd_uv = ret; + + regulator_disable(priv->vdd); + } + + return 0; +} + 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; + u32 max_rate; int ret; if (!pdev->dev.of_node) @@ -490,7 +688,8 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->vref = devm_regulator_get(&pdev->dev, "vref"); if (IS_ERR(priv->vref)) { ret = PTR_ERR(priv->vref); - dev_err(&pdev->dev, "vref get failed, %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "vref get failed, %d\n", ret); return ret; } @@ -498,7 +697,8 @@ static int stm32_adc_probe(struct platform_device *pdev) if (IS_ERR(priv->aclk)) { ret = PTR_ERR(priv->aclk); if (ret != -ENOENT) { - dev_err(&pdev->dev, "Can't get 'adc' clock\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get 'adc' clock\n"); return ret; } priv->aclk = NULL; @@ -508,12 +708,17 @@ static int stm32_adc_probe(struct platform_device *pdev) if (IS_ERR(priv->bclk)) { ret = PTR_ERR(priv->bclk); if (ret != -ENOENT) { - dev_err(&pdev->dev, "Can't get 'bus' clock\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get 'bus' clock\n"); return ret; } priv->bclk = NULL; } + ret = stm32_adc_core_switches_probe(dev, priv); + if (ret) + return ret; + pm_runtime_get_noresume(dev); pm_runtime_set_active(dev); pm_runtime_set_autosuspend_delay(dev, STM32_ADC_CORE_SLEEP_DELAY_MS); @@ -532,6 +737,13 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->common.vref_mv = ret / 1000; dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv); + ret = of_property_read_u32(pdev->dev.of_node, "st,max-clk-rate-hz", + &max_rate); + if (!ret) + priv->max_clk_rate = min(max_rate, priv->cfg->max_clk_rate_hz); + else + priv->max_clk_rate = priv->cfg->max_clk_rate_hz; + ret = priv->cfg->clk_sel(pdev, priv); if (ret < 0) goto err_hw_stop; @@ -611,12 +823,14 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = { .regs = &stm32h7_adc_common_regs, .clk_sel = stm32h7_adc_clk_sel, .max_clk_rate_hz = 36000000, + .has_syscfg = HAS_VBOOSTER, }; static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { .regs = &stm32h7_adc_common_regs, .clk_sel = stm32h7_adc_clk_sel, .max_clk_rate_hz = 40000000, + .has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD, }; static const struct of_device_id stm32_adc_of_match[] = { diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h index 8af507b3f32d..2322809bfd2f 100644 --- a/drivers/iio/adc/stm32-adc-core.h +++ b/drivers/iio/adc/stm32-adc-core.h @@ -25,8 +25,154 @@ * -------------------------------------------------------- */ #define STM32_ADC_MAX_ADCS 3 +#define STM32_ADC_OFFSET 0x100 #define STM32_ADCX_COMN_OFFSET 0x300 +/* STM32F4 - Registers for each ADC instance */ +#define STM32F4_ADC_SR 0x00 +#define STM32F4_ADC_CR1 0x04 +#define STM32F4_ADC_CR2 0x08 +#define STM32F4_ADC_SMPR1 0x0C +#define STM32F4_ADC_SMPR2 0x10 +#define STM32F4_ADC_HTR 0x24 +#define STM32F4_ADC_LTR 0x28 +#define STM32F4_ADC_SQR1 0x2C +#define STM32F4_ADC_SQR2 0x30 +#define STM32F4_ADC_SQR3 0x34 +#define STM32F4_ADC_JSQR 0x38 +#define STM32F4_ADC_JDR1 0x3C +#define STM32F4_ADC_JDR2 0x40 +#define STM32F4_ADC_JDR3 0x44 +#define STM32F4_ADC_JDR4 0x48 +#define STM32F4_ADC_DR 0x4C + +/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */ +#define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00) +#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04) + +/* STM32F4_ADC_SR - bit fields */ +#define STM32F4_OVR BIT(5) +#define STM32F4_STRT BIT(4) +#define STM32F4_EOC BIT(1) + +/* STM32F4_ADC_CR1 - bit fields */ +#define STM32F4_OVRIE BIT(26) +#define STM32F4_RES_SHIFT 24 +#define STM32F4_RES_MASK GENMASK(25, 24) +#define STM32F4_SCAN BIT(8) +#define STM32F4_EOCIE BIT(5) + +/* STM32F4_ADC_CR2 - bit fields */ +#define STM32F4_SWSTART BIT(30) +#define STM32F4_EXTEN_SHIFT 28 +#define STM32F4_EXTEN_MASK GENMASK(29, 28) +#define STM32F4_EXTSEL_SHIFT 24 +#define STM32F4_EXTSEL_MASK GENMASK(27, 24) +#define STM32F4_EOCS BIT(10) +#define STM32F4_DDS BIT(9) +#define STM32F4_DMA BIT(8) +#define STM32F4_ADON BIT(0) + +/* STM32F4_ADC_CSR - bit fields */ +#define STM32F4_OVR3 BIT(21) +#define STM32F4_EOC3 BIT(17) +#define STM32F4_OVR2 BIT(13) +#define STM32F4_EOC2 BIT(9) +#define STM32F4_OVR1 BIT(5) +#define STM32F4_EOC1 BIT(1) + +/* STM32F4_ADC_CCR - bit fields */ +#define STM32F4_ADC_ADCPRE_SHIFT 16 +#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16) + +/* 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_DIFSEL 0xC0 +#define STM32H7_ADC_CALFACT 0xC4 +#define STM32H7_ADC_CALFACT2 0xC8 + +/* 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_ISR - bit fields */ +#define STM32MP1_VREGREADY BIT(12) +#define STM32H7_OVR BIT(4) +#define STM32H7_EOC BIT(2) +#define STM32H7_ADRDY BIT(0) + +/* STM32H7_ADC_IER - bit fields */ +#define STM32H7_OVRIE STM32H7_OVR +#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) + +/* STM32H7_ADC_CSR - bit fields */ +#define STM32H7_OVR_SLV BIT(20) +#define STM32H7_EOC_SLV BIT(18) +#define STM32H7_OVR_MST BIT(4) +#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) + /** * struct stm32_adc_common - stm32 ADC driver common data (for all instances) * @base: control registers base cpu addr diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 205e1699f954..80c3f963527b 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -28,115 +28,6 @@ #include "stm32-adc-core.h" -/* STM32F4 - Registers for each ADC instance */ -#define STM32F4_ADC_SR 0x00 -#define STM32F4_ADC_CR1 0x04 -#define STM32F4_ADC_CR2 0x08 -#define STM32F4_ADC_SMPR1 0x0C -#define STM32F4_ADC_SMPR2 0x10 -#define STM32F4_ADC_HTR 0x24 -#define STM32F4_ADC_LTR 0x28 -#define STM32F4_ADC_SQR1 0x2C -#define STM32F4_ADC_SQR2 0x30 -#define STM32F4_ADC_SQR3 0x34 -#define STM32F4_ADC_JSQR 0x38 -#define STM32F4_ADC_JDR1 0x3C -#define STM32F4_ADC_JDR2 0x40 -#define STM32F4_ADC_JDR3 0x44 -#define STM32F4_ADC_JDR4 0x48 -#define STM32F4_ADC_DR 0x4C - -/* STM32F4_ADC_SR - bit fields */ -#define STM32F4_STRT BIT(4) -#define STM32F4_EOC BIT(1) - -/* STM32F4_ADC_CR1 - bit fields */ -#define STM32F4_RES_SHIFT 24 -#define STM32F4_RES_MASK GENMASK(25, 24) -#define STM32F4_SCAN BIT(8) -#define STM32F4_EOCIE BIT(5) - -/* STM32F4_ADC_CR2 - bit fields */ -#define STM32F4_SWSTART BIT(30) -#define STM32F4_EXTEN_SHIFT 28 -#define STM32F4_EXTEN_MASK GENMASK(29, 28) -#define STM32F4_EXTSEL_SHIFT 24 -#define STM32F4_EXTSEL_MASK GENMASK(27, 24) -#define STM32F4_EOCS BIT(10) -#define STM32F4_DDS BIT(9) -#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_DIFSEL 0xC0 -#define STM32H7_ADC_CALFACT 0xC4 -#define STM32H7_ADC_CALFACT2 0xC8 - -/* STM32H7_ADC_ISR - bit fields */ -#define STM32MP1_VREGREADY BIT(12) -#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 @@ -211,7 +102,7 @@ struct stm32_adc_calib { }; /** - * stm32_adc_regs - stm32 ADC misc registers & bitfield desc + * struct stm32_adc_regs - stm32 ADC misc registers & bitfield desc * @reg: register offset * @mask: bitfield mask * @shift: left shift @@ -223,10 +114,12 @@ struct stm32_adc_regs { }; /** - * stm32_adc_regspec - stm32 registers definition, compatible dependent data + * struct stm32_adc_regspec - stm32 registers definition * @dr: data register offset * @ier_eoc: interrupt enable register & eocie bitfield + * @ier_ovr: interrupt enable register & overrun bitfield * @isr_eoc: interrupt status register & eoc bitfield + * @isr_ovr: interrupt status register & overrun bitfield * @sqr: reference to sequence registers array * @exten: trigger control register & bitfield * @extsel: trigger selection register & bitfield @@ -237,7 +130,9 @@ struct stm32_adc_regs { struct stm32_adc_regspec { const u32 dr; const struct stm32_adc_regs ier_eoc; + const struct stm32_adc_regs ier_ovr; const struct stm32_adc_regs isr_eoc; + const struct stm32_adc_regs isr_ovr; const struct stm32_adc_regs *sqr; const struct stm32_adc_regs exten; const struct stm32_adc_regs extsel; @@ -249,7 +144,7 @@ struct stm32_adc_regspec { struct stm32_adc; /** - * stm32_adc_cfg - stm32 compatible configuration data + * struct stm32_adc_cfg - stm32 compatible configuration data * @regs: registers descriptions * @adc_info: per instance input channels definitions * @trigs: external trigger sources @@ -292,8 +187,8 @@ struct stm32_adc_cfg { * @rx_buf: dma rx buffer cpu address * @rx_dma_buf: dma rx buffer bus address * @rx_buf_sz: dma rx buffer size - * @difsel bitmask to set single-ended/differential channel - * @pcsel bitmask to preselect channels on some devices + * @difsel: bitmask to set single-ended/differential channel + * @pcsel: bitmask to preselect channels on some devices * @smpr_val: sampling time settings (e.g. smpr1 / smpr2) * @cal: optional calibration data on some devices * @chan_name: channel name array @@ -363,7 +258,7 @@ static const struct stm32_adc_info stm32h7_adc_info = { .num_res = ARRAY_SIZE(stm32h7_adc_resolutions), }; -/** +/* * stm32f4_sq - describe regular sequence registers * - L: sequence len (register & bit field) * - SQ1..SQ16: sequence entries (register & bit field) @@ -410,7 +305,7 @@ static struct stm32_adc_trig_info stm32f4_adc_trigs[] = { {}, /* sentinel */ }; -/** +/* * stm32f4_smp_bits[] - describe sampling time register index & bit fields * Sorted so it can be indexed by channel number. */ @@ -446,7 +341,9 @@ static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { static const struct stm32_adc_regspec stm32f4_adc_regspec = { .dr = STM32F4_ADC_DR, .ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE }, + .ier_ovr = { STM32F4_ADC_CR1, STM32F4_OVRIE }, .isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC }, + .isr_ovr = { STM32F4_ADC_SR, STM32F4_OVR }, .sqr = stm32f4_sq, .exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT }, .extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK, @@ -501,7 +398,7 @@ static struct stm32_adc_trig_info stm32h7_adc_trigs[] = { {}, }; -/** +/* * stm32h7_smp_bits - describe sampling time register index & bit fields * Sorted so it can be indexed by channel number. */ @@ -538,7 +435,9 @@ static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { static const struct stm32_adc_regspec stm32h7_adc_regspec = { .dr = STM32H7_ADC_DR, .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE }, + .ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE }, .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC }, + .isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR }, .sqr = stm32h7_sq, .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT }, .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, @@ -615,6 +514,18 @@ static void stm32_adc_conv_irq_disable(struct stm32_adc *adc) adc->cfg->regs->ier_eoc.mask); } +static void stm32_adc_ovr_irq_enable(struct stm32_adc *adc) +{ + stm32_adc_set_bits(adc, adc->cfg->regs->ier_ovr.reg, + adc->cfg->regs->ier_ovr.mask); +} + +static void stm32_adc_ovr_irq_disable(struct stm32_adc *adc) +{ + stm32_adc_clr_bits(adc, adc->cfg->regs->ier_ovr.reg, + adc->cfg->regs->ier_ovr.mask); +} + static void stm32_adc_set_res(struct stm32_adc *adc) { const struct stm32_adc_regs *res = &adc->cfg->regs->res; @@ -1103,6 +1014,7 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev, /** * stm32_adc_get_trig_extsel() - Get external trigger selection + * @indio_dev: IIO device structure * @trig: trigger * * Returns trigger extsel value, if trig matches, -EINVAL otherwise. @@ -1313,6 +1225,19 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, } } +static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) +{ + struct stm32_adc *adc = data; + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + const struct stm32_adc_regspec *regs = adc->cfg->regs; + u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); + + if (status & regs->isr_ovr.mask) + dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n"); + + return IRQ_HANDLED; +} + static irqreturn_t stm32_adc_isr(int irq, void *data) { struct stm32_adc *adc = data; @@ -1320,6 +1245,19 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) const struct stm32_adc_regspec *regs = adc->cfg->regs; u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); + if (status & regs->isr_ovr.mask) { + /* + * Overrun occurred on regular conversions: data for wrong + * channel may be read. Unconditionally disable interrupts + * to stop processing data and print error message. + * Restarting the capture can be done by disabling, then + * re-enabling it (e.g. write 0, then 1 to buffer/enable). + */ + stm32_adc_ovr_irq_disable(adc); + stm32_adc_conv_irq_disable(adc); + return IRQ_WAKE_THREAD; + } + if (status & regs->isr_eoc.mask) { /* Reading DR also clears EOC status flag */ adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr); @@ -1406,6 +1344,10 @@ static int stm32_adc_of_xlate(struct iio_dev *indio_dev, /** * stm32_adc_debugfs_reg_access - read or write register value + * @indio_dev: IIO device structure + * @reg: register offset + * @writeval: value to write + * @readval: value to read * * To read a value from an ADC register: * echo [ADC reg offset] > direct_reg_access @@ -1508,7 +1450,7 @@ static int stm32_adc_dma_start(struct iio_dev *indio_dev) cookie = dmaengine_submit(desc); ret = dma_submit_error(cookie); if (ret) { - dmaengine_terminate_all(adc->dma_chan); + dmaengine_terminate_sync(adc->dma_chan); return ret; } @@ -1545,6 +1487,8 @@ static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev) /* Reset adc buffer index */ adc->bufi = 0; + stm32_adc_ovr_irq_enable(adc); + if (!adc->dma_chan) stm32_adc_conv_irq_enable(adc); @@ -1585,8 +1529,10 @@ static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev) if (!adc->dma_chan) stm32_adc_conv_irq_disable(adc); + stm32_adc_ovr_irq_disable(adc); + if (adc->dma_chan) - dmaengine_terminate_all(adc->dma_chan); + dmaengine_terminate_sync(adc->dma_chan); if (stm32_adc_set_trig(indio_dev, NULL)) dev_err(&indio_dev->dev, "Can't clear trigger\n"); @@ -1850,9 +1796,21 @@ static int stm32_adc_dma_request(struct iio_dev *indio_dev) struct dma_slave_config config; int ret; - adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx"); - if (!adc->dma_chan) + adc->dma_chan = dma_request_chan(&indio_dev->dev, "rx"); + if (IS_ERR(adc->dma_chan)) { + ret = PTR_ERR(adc->dma_chan); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(&indio_dev->dev, + "DMA channel request failed with %d\n", + ret); + return ret; + } + + /* DMA is optional: fall back to IRQ mode */ + adc->dma_chan = NULL; return 0; + } adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev, STM32_DMA_BUFFER_SIZE, @@ -1919,13 +1877,12 @@ static int stm32_adc_probe(struct platform_device *pdev) } adc->irq = platform_get_irq(pdev, 0); - if (adc->irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (adc->irq < 0) return adc->irq; - } - ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, - 0, pdev->name, adc); + ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr, + stm32_adc_threaded_isr, + 0, pdev->name, adc); if (ret) { dev_err(&pdev->dev, "failed to request IRQ\n"); return ret; diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index ee1e0569d0e1..2aad2cda6943 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1204,6 +1204,8 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, stm32_dfsdm_stop_conv(adc); + stm32_dfsdm_process_data(adc, res); + stop_dfsdm: stm32_dfsdm_stop_dfsdm(adc->dfsdm); @@ -1219,14 +1221,32 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, unsigned int spi_freq; int ret = -EINVAL; + switch (ch->src) { + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: + spi_freq = adc->dfsdm->spi_master_freq; + break; + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: + spi_freq = adc->dfsdm->spi_master_freq / 2; + break; + default: + spi_freq = adc->spi_freq; + } + switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; + ret = stm32_dfsdm_compute_all_osrs(indio_dev, val); - if (!ret) + if (!ret) { + dev_dbg(&indio_dev->dev, + "Sampling rate changed from (%u) to (%u)\n", + adc->sample_freq, spi_freq / val); adc->oversamp = val; + adc->sample_freq = spi_freq / val; + } iio_device_release_direct_mode(indio_dev); return ret; @@ -1238,18 +1258,6 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, if (ret) return ret; - switch (ch->src) { - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: - spi_freq = adc->dfsdm->spi_master_freq; - break; - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: - spi_freq = adc->dfsdm->spi_master_freq / 2; - break; - default: - spi_freq = adc->spi_freq; - } - ret = dfsdm_adc_set_samp_freq(indio_dev, val, spi_freq); iio_device_release_direct_mode(indio_dev); return ret; @@ -1383,9 +1391,13 @@ static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx"); - if (!adc->dma_chan) - return -EINVAL; + adc->dma_chan = dma_request_chan(&indio_dev->dev, "rx"); + if (IS_ERR(adc->dma_chan)) { + int ret = PTR_ERR(adc->dma_chan); + + adc->dma_chan = NULL; + return ret; + } adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE, @@ -1509,7 +1521,16 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev) init_completion(&adc->completion); /* Optionally request DMA */ - if (stm32_dfsdm_dma_request(indio_dev)) { + ret = stm32_dfsdm_dma_request(indio_dev); + if (ret) { + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(&indio_dev->dev, + "DMA channel request failed with %d\n", + ret); + return ret; + } + dev_dbg(&indio_dev->dev, "No DMA support\n"); return 0; } @@ -1601,11 +1622,8 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) * So IRQ associated to filter instance 0 is dedicated to the Filter 0. */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(dev, "Failed to get IRQ: %d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, 0, pdev->name, adc); diff --git a/drivers/iio/adc/stmpe-adc.c b/drivers/iio/adc/stmpe-adc.c index bd72727fc417..0f88048ea48f 100644 --- a/drivers/iio/adc/stmpe-adc.c +++ b/drivers/iio/adc/stmpe-adc.c @@ -175,7 +175,7 @@ static int stmpe_read_raw(struct iio_dev *indio_dev, static irqreturn_t stmpe_adc_isr(int irq, void *dev_id) { struct stmpe_adc *info = (struct stmpe_adc *)dev_id; - u16 data; + __be16 data; if (info->channel <= STMPE_ADC_LAST_NR) { int int_sta; diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index f13c6248a662..176e1cb4abb1 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -460,10 +460,8 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, atomic_set(atomic, 1); ret = platform_get_irq_byname(pdev, name); - if (ret < 0) { - dev_err(&pdev->dev, "no %s interrupt registered\n", name); + if (ret < 0) return ret; - } ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); if (ret < 0) { diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index a550b132cfb7..5ea4f45d6bad 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -12,17 +12,15 @@ */ #include <linux/module.h> -#include <linux/of_device.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/i2c.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/pm_runtime.h> #include <linux/mutex.h> #include <linux/delay.h> -#include <linux/platform_data/ads1015.h> - #include <linux/iio/iio.h> #include <linux/iio/types.h> #include <linux/iio/sysfs.h> @@ -33,6 +31,8 @@ #define ADS1015_DRV_NAME "ads1015" +#define ADS1015_CHANNELS 8 + #define ADS1015_CONV_REG 0x00 #define ADS1015_CFG_REG 0x01 #define ADS1015_LO_THRESH_REG 0x02 @@ -77,6 +77,7 @@ #define ADS1015_DEFAULT_CHAN 0 enum chip_ids { + ADSXXXX = 0, ADS1015, ADS1115, }; @@ -219,6 +220,12 @@ static const struct iio_event_spec ads1015_events[] = { .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ } +struct ads1015_channel_data { + bool enabled; + unsigned int pga; + unsigned int data_rate; +}; + struct ads1015_thresh_data { unsigned int comp_queue; int high_thresh; @@ -837,65 +844,58 @@ static const struct iio_info ads1115_info = { .attrs = &ads1115_attribute_group, }; -#ifdef CONFIG_OF -static int ads1015_get_channels_config_of(struct i2c_client *client) +static int ads1015_client_get_channels_config(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ads1015_data *data = iio_priv(indio_dev); - struct device_node *node; + struct device *dev = &client->dev; + struct fwnode_handle *node; + int i = -1; - if (!client->dev.of_node || - !of_get_next_child(client->dev.of_node, NULL)) - return -EINVAL; - - for_each_child_of_node(client->dev.of_node, node) { + device_for_each_child_node(dev, node) { u32 pval; unsigned int channel; unsigned int pga = ADS1015_DEFAULT_PGA; unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; - if (of_property_read_u32(node, "reg", &pval)) { - dev_err(&client->dev, "invalid reg on %pOF\n", - node); + if (fwnode_property_read_u32(node, "reg", &pval)) { + dev_err(dev, "invalid reg on %pfw\n", node); continue; } channel = pval; if (channel >= ADS1015_CHANNELS) { - dev_err(&client->dev, - "invalid channel index %d on %pOF\n", + dev_err(dev, "invalid channel index %d on %pfw\n", channel, node); continue; } - if (!of_property_read_u32(node, "ti,gain", &pval)) { + if (!fwnode_property_read_u32(node, "ti,gain", &pval)) { pga = pval; if (pga > 6) { - dev_err(&client->dev, "invalid gain on %pOF\n", - node); - of_node_put(node); + dev_err(dev, "invalid gain on %pfw\n", node); + fwnode_handle_put(node); return -EINVAL; } } - if (!of_property_read_u32(node, "ti,datarate", &pval)) { + if (!fwnode_property_read_u32(node, "ti,datarate", &pval)) { data_rate = pval; if (data_rate > 7) { - dev_err(&client->dev, - "invalid data_rate on %pOF\n", - node); - of_node_put(node); + dev_err(dev, "invalid data_rate on %pfw\n", node); + fwnode_handle_put(node); return -EINVAL; } } data->channel_data[channel].pga = pga; data->channel_data[channel].data_rate = data_rate; + + i++; } - return 0; + return i < 0 ? -EINVAL : 0; } -#endif static void ads1015_get_channels_config(struct i2c_client *client) { @@ -903,19 +903,10 @@ static void ads1015_get_channels_config(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ads1015_data *data = iio_priv(indio_dev); - struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev); - /* prefer platform data */ - if (pdata) { - memcpy(data->channel_data, pdata->channel_data, - sizeof(data->channel_data)); + if (!ads1015_client_get_channels_config(client)) return; - } -#ifdef CONFIG_OF - if (!ads1015_get_channels_config_of(client)) - return; -#endif /* fallback on default configuration */ for (k = 0; k < ADS1015_CHANNELS; ++k) { data->channel_data[k].pga = ADS1015_DEFAULT_PGA; @@ -953,9 +944,8 @@ static int ads1015_probe(struct i2c_client *client, indio_dev->name = ADS1015_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; - if (client->dev.of_node) - chip = (enum chip_ids)of_device_get_match_data(&client->dev); - else + chip = (enum chip_ids)device_get_match_data(&client->dev); + if (chip == ADSXXXX) chip = id->driver_data; switch (chip) { case ADS1015: @@ -970,6 +960,9 @@ static int ads1015_probe(struct i2c_client *client, indio_dev->info = &ads1115_info; data->data_rate = (unsigned int *) &ads1115_data_rate; break; + default: + dev_err(&client->dev, "Unknown chip %d\n", chip); + return -EINVAL; } data->event_channel = ADS1015_CHANNELS; diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index 2e66e4d586ff..f9edc1207f75 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -602,7 +602,7 @@ static int ti_ads7950_probe(struct spi_device *spi) st->reg = devm_regulator_get(&spi->dev, "vref"); if (IS_ERR(st->reg)) { - dev_err(&spi->dev, "Failed get get regulator \"vref\"\n"); + dev_err(&spi->dev, "Failed to get regulator \"vref\"\n"); ret = PTR_ERR(st->reg); goto error_destroy_mutex; } diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index 55c5119fe575..472b08f37fea 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -495,7 +495,7 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) ret = twl4030_madc_disable_irq(madc, i); if (ret < 0) dev_dbg(madc->dev, "Disable interrupt failed %d\n", i); - madc->requests[i].result_pending = 1; + madc->requests[i].result_pending = true; } for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) { r = &madc->requests[i]; @@ -507,8 +507,8 @@ static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) len = twl4030_madc_read_channels(madc, method->rbase, r->channels, r->rbuf, r->raw); /* Free request */ - r->result_pending = 0; - r->active = 0; + r->result_pending = false; + r->active = false; } mutex_unlock(&madc->lock); @@ -521,15 +521,15 @@ err_i2c: */ for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) { r = &madc->requests[i]; - if (r->active == 0) + if (!r->active) continue; method = &twl4030_conversion_methods[r->method]; /* Read results */ len = twl4030_madc_read_channels(madc, method->rbase, r->channels, r->rbuf, r->raw); /* Free request */ - r->result_pending = 0; - r->active = 0; + r->result_pending = false; + r->active = false; } mutex_unlock(&madc->lock); @@ -652,16 +652,16 @@ static int twl4030_madc_conversion(struct twl4030_madc_request *req) ret = twl4030_madc_start_conversion(twl4030_madc, req->method); if (ret < 0) goto out; - twl4030_madc->requests[req->method].active = 1; + twl4030_madc->requests[req->method].active = true; /* Wait until conversion is ready (ctrl register returns EOC) */ ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl); if (ret) { - twl4030_madc->requests[req->method].active = 0; + twl4030_madc->requests[req->method].active = false; goto out; } ret = twl4030_madc_read_channels(twl4030_madc, method->rbase, req->channels, req->rbuf, req->raw); - twl4030_madc->requests[req->method].active = 0; + twl4030_madc->requests[req->method].active = false; out: mutex_unlock(&twl4030_madc->lock); diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index 2fa6ec83bb13..f24148bd15de 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -905,10 +905,8 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(dev, irq, NULL, twl6030_gpadc_irq_handler, diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 41d3621c4787..cb7380bf07ca 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -802,7 +802,6 @@ static int vf610_adc_probe(struct platform_device *pdev) { struct vf610_adc *info; struct iio_dev *indio_dev; - struct resource *mem; int irq; int ret; @@ -815,16 +814,13 @@ static int vf610_adc_probe(struct platform_device *pdev) info = iio_priv(indio_dev); info->dev = &pdev->dev; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - info->regs = devm_ioremap_resource(&pdev->dev, mem); + info->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(info->regs)) return PTR_ERR(info->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(info->dev, irq, vf610_adc_isr, 0, diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index 4fd389678dba..ec227b358cd6 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -1150,7 +1150,6 @@ static int xadc_probe(struct platform_device *pdev) const struct of_device_id *id; struct iio_dev *indio_dev; unsigned int bipolar_mask; - struct resource *mem; unsigned int conf0; struct xadc *xadc; int ret; @@ -1180,8 +1179,7 @@ static int xadc_probe(struct platform_device *pdev) spin_lock_init(&xadc->lock); INIT_DELAYED_WORK(&xadc->zynq_unmask_work, xadc_zynq_unmask_worker); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xadc->base = devm_ioremap_resource(&pdev->dev, mem); + xadc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xadc->base)) return PTR_ERR(xadc->base); |