summaryrefslogtreecommitdiff
path: root/drivers/iio/adc
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-05-19 16:53:08 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-05-19 16:53:08 +0200
commitbcfa9546500a41fa448816a3c6df2fb798ba9130 (patch)
tree36de73d51aa7adf6ccb0624519600e9833e231a6 /drivers/iio/adc
parent33a1c6618677fe33f8e84cb7bedc45abbce89a50 (diff)
parenteda75f8238b079a41aa11383bd47dc3297e74cb1 (diff)
Merge tag 'iio-for-5.19a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-next
Jonathan writes: First set of IIO new device support, features and cleanup for 5.19 Usual mixed bag. Stand out this time is Andy Shevchenko's continuing effort to move drivers over the generic firmware interfaces. Device support * sprd,sc2720 - upm9620 binding addition. - Refactor and support for sc2720, sc2721 and sc2730. * ti,ads1015 - Refactor driver and add support for TLA2024. Device support (IDs only) * invensense,mpu6050 - Add ID for ICM-20608-D. * st,accel: - Add ID for lis302dl. * st,lsm6dsx - Add support for ASM330LHHX (can fallback to LSM6DSR.) Features * convert drivers to device properties - IIO core - adi,ad7266 - adi,adis16480 - adi,adxl355 - bosch,bmi160 - domintech,dmard06 - fsl,fxas21002c - invensense,mpu3050 - linear,ltc2983 - linear,ltc2632 - maxbotix,mb1232 - maxim,max31856 - maxim,max31865 - multiplexer - ping - rescale - taos,tsl2772 * core - Add runtime check on whether realbits fit in storagebits for each channel. * adi,ad_sigma_delta - Add sequencer support and relevant update_scan_mode callbacks for adi,ad7192 and adi,ad7124. Cleanup and minor fixes * MAINTAINERS - Update Lorenzo Bianconi's email address for IIO drivers. - Add entry for ad3552r and update maintainer in dt-binding doc. * tree-wide - Replace strtobool() with kstrtobool(). - Drop false OF dependencies. * core - Tidy up and document IIO modes. - Take iio_buffer_enabled() out of header allowing current_mode to be moved to the opaque structure. - As all kfifo buffers use the same mode value, drop that parameter and set it unconditionally. - White space fixes and similar. - Drop use of list iterator variable for list_for_each_entry_continue_reverse and use list_prepare_entry to restart. * sysfs-trigger - Replace use of 'found' variable with dedicate list iterator variable. * adi,ad7124 - Drop misleading shift. * adi,ad2s1210 - Remove redundant local variable assignment. * adi,adis16480 - Use local device pointer to reduce repetition. - Improve handling of clocks. * domintech,dmard09 - White space. * dummy driver - Improve error handling. * fsl,mma8452 - Add missing documentation of name element. * invensense,mpu3050 - Stop remove() returning non 0. * kionix,kxsd9 - White space. * linear,ltc2688 - Use local variable for struct device. - Combine of_node_put() error handling paths. * linear,ltc2983 - Avoid use of constants in messages where a define is available. * microchip,mcp4131 - Fix compatible in dt example. * pni,rm3100 - Stop directly accessing iio_dev->current_mode just to find out if the buffer is enabled. * renesas,rzg2l - Relax kconfig constraint to include newer devices. * sprd,sc27xx - Fix wrong scaling mask. - Improve the calibration values. * samsung,ssp - Replace a 'found' variable in favor of an explicit value that was found. * sensortek,stk3xx - Add proximity-near-level binding and driver support. * st,st_sensors: - Drop unused accel_type enum. - Return early in *_write_raw() - Drop unnecessary locking in _avail functions. - Add local lock to protect odr against concurrent updates allowing mlock to no longer be used outside of the core. - Use iio_device_claim_direct_mode() rather than racy checking of the current mode. * st,stmpe-adc - Fix checks on wait_for_completion_timeout(). - Allow use of of_device_id for matching. * st,stm32-dfsdm - Stop accessing iio_dev->current_mode to find out if the buffer is enabled (so we can hide that variable in the opaque structure) * st,vl53l0x - Fix checks on wait_for_completion_timeout. * ti,ads1015 - Add missing ID for ti,ads1115 in binding doc. - Convert from repeated chip ID look up to selecting static const data. - Switch to read_avail() callback. * ti,ads8688 - Use of_device_id for driver matching. * ti,palmas-adc - Drop a warning on minor calibration mismatch leading to slightly negative values after applying the calibration. * tag 'iio-for-5.19a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (95 commits) iio: ti-ads8688: use of_device_id for OF matching iio: stmpe-adc: use of_device_id for OF matching dt-bindings: iio: Fix incorrect compatible strings in examples iio: gyro: mpu3050: Make mpu3050_common_remove() return void iio: dac: ltc2632: Make use of device properties iio: temperature: max31865: Make use of device properties iio: proximity: mb1232: Switch to use fwnode_irq_get() iio: imu: adis16480: Improve getting the optional clocks iio: imu: adis16480: Use temporary variable for struct device iio: imu: adis16480: Make use of device properties staging: iio: ad2s1210: remove redundant assignment to variable negative iio: adc: sc27xx: add support for PMIC sc2730 iio: adc: sc27xx: add support for PMIC sc2720 and sc2721 iio: adc: sc27xx: refactor some functions for support more PMiCs iio: adc: sc27xx: structure adjustment and optimization iio: adc: sc27xx: Fine tune the scale calibration values iio: adc: sc27xx: fix read big scale voltage not right dt-bindings:iio:adc: add sprd,ump9620-adc dt-binding iio: proximity: stk3310: Export near level property for proximity sensor dt-bindings: iio: light: stk33xx: Add proximity-near-level ...
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r--drivers/iio/adc/Kconfig2
-rw-r--r--drivers/iio/adc/ad7124.c86
-rw-r--r--drivers/iio/adc/ad7192.c68
-rw-r--r--drivers/iio/adc/ad7266.c44
-rw-r--r--drivers/iio/adc/ad7280a.c2
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c143
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c4
-rw-r--r--drivers/iio/adc/ina2xx-adc.c3
-rw-r--r--drivers/iio/adc/palmas_gpadc.c3
-rw-r--r--drivers/iio/adc/sc27xx_adc.c470
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c5
-rw-r--r--drivers/iio/adc/stmpe-adc.c21
-rw-r--r--drivers/iio/adc/ti-ads1015.c398
-rw-r--r--drivers/iio/adc/ti-ads8688.c1
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c4
15 files changed, 982 insertions, 272 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 71ab0a06aa82..48ace7412874 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -910,7 +910,7 @@ config ROCKCHIP_SARADC
config RZG2L_ADC
tristate "Renesas RZ/G2L ADC driver"
- depends on ARCH_R9A07G044 || COMPILE_TEST
+ depends on ARCH_RZG2L || COMPILE_TEST
help
Say yes here to build support for the ADC found in Renesas
RZ/G2L family.
diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c
index c47ead15f6e5..c5b785d8b241 100644
--- a/drivers/iio/adc/ad7124.c
+++ b/drivers/iio/adc/ad7124.c
@@ -43,6 +43,8 @@
#define AD7124_STATUS_POR_FLAG_MSK BIT(4)
/* AD7124_ADC_CONTROL */
+#define AD7124_ADC_STATUS_EN_MSK BIT(10)
+#define AD7124_ADC_STATUS_EN(x) FIELD_PREP(AD7124_ADC_STATUS_EN_MSK, x)
#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)
@@ -188,7 +190,6 @@ static const struct iio_chan_spec ad7124_channel_template = {
.sign = 'u',
.realbits = 24,
.storagebits = 32,
- .shift = 8,
.endianness = IIO_BE,
},
};
@@ -501,26 +502,70 @@ static int ad7124_prepare_read(struct ad7124_state *st, int address)
return ad7124_enable_channel(st, &st->channels[address]);
}
+static int __ad7124_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
+{
+ struct ad7124_state *st = container_of(sd, struct ad7124_state, sd);
+
+ return ad7124_prepare_read(st, channel);
+}
+
static int ad7124_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
{
struct ad7124_state *st = container_of(sd, struct ad7124_state, sd);
int ret;
mutex_lock(&st->cfgs_lock);
- ret = ad7124_prepare_read(st, channel);
+ ret = __ad7124_set_channel(sd, channel);
mutex_unlock(&st->cfgs_lock);
return ret;
}
+static int ad7124_append_status(struct ad_sigma_delta *sd, bool append)
+{
+ struct ad7124_state *st = container_of(sd, struct ad7124_state, sd);
+ unsigned int adc_control = st->adc_control;
+ int ret;
+
+ adc_control &= ~AD7124_ADC_STATUS_EN_MSK;
+ adc_control |= AD7124_ADC_STATUS_EN(append);
+
+ ret = ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, adc_control);
+ if (ret < 0)
+ return ret;
+
+ st->adc_control = adc_control;
+
+ return 0;
+}
+
+static int ad7124_disable_all(struct ad_sigma_delta *sd)
+{
+ struct ad7124_state *st = container_of(sd, struct ad7124_state, sd);
+ int ret;
+ int i;
+
+ for (i = 0; i < st->num_channels; i++) {
+ ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_EN_MSK, 0, 2);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct ad_sigma_delta_info ad7124_sigma_delta_info = {
.set_channel = ad7124_set_channel,
+ .append_status = ad7124_append_status,
+ .disable_all = ad7124_disable_all,
.set_mode = ad7124_set_mode,
.has_registers = true,
.addr_shift = 0,
.read_mask = BIT(6),
+ .status_ch_mask = GENMASK(3, 0),
.data_reg = AD7124_DATA,
- .irq_flags = IRQF_TRIGGER_FALLING
+ .num_slots = 8,
+ .irq_flags = IRQF_TRIGGER_FALLING,
};
static int ad7124_read_raw(struct iio_dev *indio_dev,
@@ -670,11 +715,40 @@ static const struct attribute_group ad7124_attrs_group = {
.attrs = ad7124_attributes,
};
+static int ad7124_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct ad7124_state *st = iio_priv(indio_dev);
+ bool bit_set;
+ int ret;
+ int i;
+
+ mutex_lock(&st->cfgs_lock);
+ for (i = 0; i < st->num_channels; i++) {
+ bit_set = test_bit(i, scan_mask);
+ if (bit_set)
+ ret = __ad7124_set_channel(&st->sd, i);
+ else
+ ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_EN_MSK,
+ 0, 2);
+ if (ret < 0) {
+ mutex_unlock(&st->cfgs_lock);
+
+ return ret;
+ }
+ }
+
+ mutex_unlock(&st->cfgs_lock);
+
+ return 0;
+}
+
static const struct iio_info ad7124_info = {
.read_raw = ad7124_read_raw,
.write_raw = ad7124_write_raw,
.debugfs_reg_access = &ad7124_reg_access,
.validate_trigger = ad_sd_validate_trigger,
+ .update_scan_mode = ad7124_update_scan_mode,
.attrs = &ad7124_attrs_group,
};
@@ -886,12 +960,14 @@ static int ad7124_probe(struct spi_device *spi)
st->chip_info = info;
- ad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info);
-
indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &ad7124_info;
+ ret = ad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info);
+ if (ret < 0)
+ return ret;
+
ret = ad7124_of_parse_channel_config(indio_dev, spi->dev.of_node);
if (ret < 0)
return ret;
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 770b4e59238f..d71977be7d22 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -58,7 +58,8 @@
/* Mode Register Bit Designations (AD7192_REG_MODE) */
#define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */
#define AD7192_MODE_SEL_MASK (0x7 << 21) /* Operation Mode Select Mask */
-#define AD7192_MODE_DAT_STA BIT(20) /* Status Register transmission */
+#define AD7192_MODE_STA(x) (((x) & 0x1) << 20) /* Status Register transmission */
+#define AD7192_MODE_STA_MASK BIT(20) /* Status Register transmission Mask */
#define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */
#define AD7192_MODE_SINC3 BIT(15) /* SINC3 Filter Select */
#define AD7192_MODE_ACX BIT(14) /* AC excitation enable(AD7195 only)*/
@@ -225,7 +226,7 @@ static ssize_t ad7192_write_syscalib(struct iio_dev *indio_dev,
bool sys_calib;
int ret, temp;
- ret = strtobool(buf, &sys_calib);
+ ret = kstrtobool(buf, &sys_calib);
if (ret)
return ret;
@@ -288,12 +289,51 @@ static int ad7192_set_mode(struct ad_sigma_delta *sd,
return ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
}
+static int ad7192_append_status(struct ad_sigma_delta *sd, bool append)
+{
+ struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
+ unsigned int mode = st->mode;
+ int ret;
+
+ mode &= ~AD7192_MODE_STA_MASK;
+ mode |= AD7192_MODE_STA(append);
+
+ ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, mode);
+ if (ret < 0)
+ return ret;
+
+ st->mode = mode;
+
+ return 0;
+}
+
+static int ad7192_disable_all(struct ad_sigma_delta *sd)
+{
+ struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
+ u32 conf = st->conf;
+ int ret;
+
+ conf &= ~AD7192_CONF_CHAN_MASK;
+
+ ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, conf);
+ if (ret < 0)
+ return ret;
+
+ st->conf = conf;
+
+ return 0;
+}
+
static const struct ad_sigma_delta_info ad7192_sigma_delta_info = {
.set_channel = ad7192_set_channel,
+ .append_status = ad7192_append_status,
+ .disable_all = ad7192_disable_all,
.set_mode = ad7192_set_mode,
.has_registers = true,
.addr_shift = 3,
.read_mask = BIT(6),
+ .status_ch_mask = GENMASK(3, 0),
+ .num_slots = 4,
.irq_flags = IRQF_TRIGGER_FALLING,
};
@@ -457,7 +497,7 @@ static ssize_t ad7192_set(struct device *dev,
int ret;
bool val;
- ret = strtobool(buf, &val);
+ ret = kstrtobool(buf, &val);
if (ret < 0)
return ret;
@@ -783,6 +823,26 @@ static int ad7192_read_avail(struct iio_dev *indio_dev,
return -EINVAL;
}
+static int ad7192_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask)
+{
+ struct ad7192_state *st = iio_priv(indio_dev);
+ u32 conf = st->conf;
+ int ret;
+ int i;
+
+ conf &= ~AD7192_CONF_CHAN_MASK;
+ for_each_set_bit(i, scan_mask, 8)
+ conf |= AD7192_CONF_CHAN(i);
+
+ ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, conf);
+ if (ret < 0)
+ return ret;
+
+ st->conf = conf;
+
+ return 0;
+}
+
static const struct iio_info ad7192_info = {
.read_raw = ad7192_read_raw,
.write_raw = ad7192_write_raw,
@@ -790,6 +850,7 @@ static const struct iio_info ad7192_info = {
.read_avail = ad7192_read_avail,
.attrs = &ad7192_attribute_group,
.validate_trigger = ad_sd_validate_trigger,
+ .update_scan_mode = ad7192_update_scan_mode,
};
static const struct iio_info ad7195_info = {
@@ -799,6 +860,7 @@ static const struct iio_info ad7195_info = {
.read_avail = ad7192_read_avail,
.attrs = &ad7195_attribute_group,
.validate_trigger = ad_sd_validate_trigger,
+ .update_scan_mode = ad7192_update_scan_mode,
};
#define __AD719x_CHANNEL(_si, _channel1, _channel2, _address, _extend_name, \
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index c17d9b5fbaf6..f20d39f0bc01 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -378,6 +378,11 @@ static const char * const ad7266_gpio_labels[] = {
"ad0", "ad1", "ad2",
};
+static void ad7266_reg_disable(void *reg)
+{
+ regulator_disable(reg);
+}
+
static int ad7266_probe(struct spi_device *spi)
{
struct ad7266_platform_data *pdata = spi->dev.platform_data;
@@ -398,9 +403,13 @@ static int ad7266_probe(struct spi_device *spi)
if (ret)
return ret;
+ ret = devm_add_action_or_reset(&spi->dev, ad7266_reg_disable, st->reg);
+ if (ret)
+ return ret;
+
ret = regulator_get_voltage(st->reg);
if (ret < 0)
- goto error_disable_reg;
+ return ret;
st->vref_mv = ret / 1000;
} else {
@@ -423,7 +432,7 @@ static int ad7266_probe(struct spi_device *spi)
GPIOD_OUT_LOW);
if (IS_ERR(st->gpios[i])) {
ret = PTR_ERR(st->gpios[i]);
- goto error_disable_reg;
+ return ret;
}
}
}
@@ -433,7 +442,6 @@ static int ad7266_probe(struct spi_device *spi)
st->mode = AD7266_MODE_DIFF;
}
- spi_set_drvdata(spi, indio_dev);
st->spi = spi;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -459,35 +467,12 @@ static int ad7266_probe(struct spi_device *spi)
spi_message_add_tail(&st->single_xfer[1], &st->single_msg);
spi_message_add_tail(&st->single_xfer[2], &st->single_msg);
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, &iio_pollfunc_store_time,
&ad7266_trigger_handler, &iio_triggered_buffer_setup_ops);
if (ret)
- goto error_disable_reg;
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_buffer_cleanup;
-
- return 0;
-
-error_buffer_cleanup:
- iio_triggered_buffer_cleanup(indio_dev);
-error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
-
- return ret;
-}
-
-static void ad7266_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad7266_state *st = iio_priv(indio_dev);
+ return ret;
- iio_device_unregister(indio_dev);
- iio_triggered_buffer_cleanup(indio_dev);
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad7266_id[] = {
@@ -502,7 +487,6 @@ static struct spi_driver ad7266_driver = {
.name = "ad7266",
},
.probe = ad7266_probe,
- .remove = ad7266_remove,
.id_table = ad7266_id,
};
module_spi_driver(ad7266_driver);
diff --git a/drivers/iio/adc/ad7280a.c b/drivers/iio/adc/ad7280a.c
index ec9acbf12b9a..3bdf3d9422f2 100644
--- a/drivers/iio/adc/ad7280a.c
+++ b/drivers/iio/adc/ad7280a.c
@@ -488,7 +488,7 @@ static ssize_t ad7280_store_balance_sw(struct iio_dev *indio_dev,
bool readin;
int ret;
- ret = strtobool(buf, &readin);
+ ret = kstrtobool(buf, &readin);
if (ret)
return ret;
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index ebcd52526cac..261a9a6b45e1 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -6,6 +6,7 @@
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
+#include <linux/align.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -342,15 +343,49 @@ EXPORT_SYMBOL_NS_GPL(ad_sigma_delta_single_conversion, IIO_AD_SIGMA_DELTA);
static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+ unsigned int i, slot, samples_buf_size;
unsigned int channel;
+ uint8_t *samples_buf;
int ret;
- channel = find_first_bit(indio_dev->active_scan_mask,
- indio_dev->masklength);
- ret = ad_sigma_delta_set_channel(sigma_delta,
- indio_dev->channels[channel].address);
- if (ret)
- return ret;
+ if (sigma_delta->num_slots == 1) {
+ channel = find_first_bit(indio_dev->active_scan_mask,
+ indio_dev->masklength);
+ ret = ad_sigma_delta_set_channel(sigma_delta,
+ indio_dev->channels[channel].address);
+ if (ret)
+ return ret;
+ slot = 1;
+ } else {
+ /*
+ * At this point update_scan_mode already enabled the required channels.
+ * For sigma-delta sequencer drivers with multiple slots, an update_scan_mode
+ * implementation is mandatory.
+ */
+ slot = 0;
+ for_each_set_bit(i, indio_dev->active_scan_mask, indio_dev->masklength) {
+ sigma_delta->slots[slot] = indio_dev->channels[i].address;
+ slot++;
+ }
+ }
+
+ sigma_delta->active_slots = slot;
+ sigma_delta->current_slot = 0;
+
+ if (sigma_delta->active_slots > 1) {
+ ret = ad_sigma_delta_append_status(sigma_delta, true);
+ if (ret)
+ return ret;
+ }
+
+ samples_buf_size = ALIGN(slot * indio_dev->channels[0].scan_type.storagebits, 8);
+ samples_buf_size += sizeof(int64_t);
+ samples_buf = devm_krealloc(&sigma_delta->spi->dev, sigma_delta->samples_buf,
+ samples_buf_size, GFP_KERNEL);
+ if (!samples_buf)
+ return -ENOMEM;
+
+ sigma_delta->samples_buf = samples_buf;
spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
@@ -386,6 +421,10 @@ static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
+ if (sigma_delta->status_appended)
+ ad_sigma_delta_append_status(sigma_delta, false);
+
+ ad_sigma_delta_disable_all(sigma_delta);
sigma_delta->bus_locked = false;
return spi_bus_unlock(sigma_delta->spi->master);
}
@@ -396,6 +435,10 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
uint8_t *data = sigma_delta->rx_buf;
+ unsigned int transfer_size;
+ unsigned int sample_size;
+ unsigned int sample_pos;
+ unsigned int status_pos;
unsigned int reg_size;
unsigned int data_reg;
@@ -408,21 +451,69 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
else
data_reg = AD_SD_REG_DATA;
+ /* Status word will be appended to the sample during transfer */
+ if (sigma_delta->status_appended)
+ transfer_size = reg_size + 1;
+ else
+ transfer_size = reg_size;
+
switch (reg_size) {
case 4:
case 2:
case 1:
- ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[0]);
+ status_pos = reg_size;
+ ad_sd_read_reg_raw(sigma_delta, data_reg, transfer_size, &data[0]);
break;
case 3:
+ /*
+ * Data array after transfer will look like (if status is appended):
+ * data[] = { [0][sample][sample][sample][status] }
+ * Keeping the first byte 0 shifts the status postion by 1 byte to the right.
+ */
+ status_pos = reg_size + 1;
+
/* We store 24 bit samples in a 32 bit word. Keep the upper
* byte set to zero. */
- ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[1]);
+ ad_sd_read_reg_raw(sigma_delta, data_reg, transfer_size, &data[1]);
break;
}
- iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp);
+ /*
+ * For devices sampling only one channel at
+ * once, there is no need for sample number tracking.
+ */
+ if (sigma_delta->active_slots == 1) {
+ iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp);
+ goto irq_handled;
+ }
+
+ if (sigma_delta->status_appended) {
+ u8 converted_channel;
+
+ converted_channel = data[status_pos] & sigma_delta->info->status_ch_mask;
+ if (converted_channel != sigma_delta->slots[sigma_delta->current_slot]) {
+ /*
+ * Desync occurred during continuous sampling of multiple channels.
+ * Drop this incomplete sample and start from first channel again.
+ */
+
+ sigma_delta->current_slot = 0;
+ goto irq_handled;
+ }
+ }
+
+ sample_size = indio_dev->channels[0].scan_type.storagebits / 8;
+ sample_pos = sample_size * sigma_delta->current_slot;
+ memcpy(&sigma_delta->samples_buf[sample_pos], data, sample_size);
+ sigma_delta->current_slot++;
+ if (sigma_delta->current_slot == sigma_delta->active_slots) {
+ sigma_delta->current_slot = 0;
+ iio_push_to_buffers_with_timestamp(indio_dev, sigma_delta->samples_buf,
+ pf->timestamp);
+ }
+
+irq_handled:
iio_trigger_notify_done(indio_dev->trig);
sigma_delta->irq_dis = false;
enable_irq(sigma_delta->spi->irq);
@@ -430,10 +521,17 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
return IRQ_HANDLED;
}
+static bool ad_sd_validate_scan_mask(struct iio_dev *indio_dev, const unsigned long *mask)
+{
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+
+ return bitmap_weight(mask, indio_dev->masklength) <= sigma_delta->num_slots;
+}
+
static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
.postenable = &ad_sd_buffer_postenable,
.postdisable = &ad_sd_buffer_postdisable,
- .validate_scan_mask = &iio_validate_scan_mask_onehot,
+ .validate_scan_mask = &ad_sd_validate_scan_mask,
};
static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
@@ -513,8 +611,14 @@ static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_de
*/
int devm_ad_sd_setup_buffer_and_trigger(struct device *dev, struct iio_dev *indio_dev)
{
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
int ret;
+ sigma_delta->slots = devm_kcalloc(dev, sigma_delta->num_slots,
+ sizeof(*sigma_delta->slots), GFP_KERNEL);
+ if (!sigma_delta->slots)
+ return -ENOMEM;
+
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
&iio_pollfunc_store_time,
&ad_sd_trigger_handler,
@@ -541,6 +645,25 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
{
sigma_delta->spi = spi;
sigma_delta->info = info;
+
+ /* If the field is unset in ad_sigma_delta_info, asume there can only be 1 slot. */
+ if (!info->num_slots)
+ sigma_delta->num_slots = 1;
+ else
+ sigma_delta->num_slots = info->num_slots;
+
+ if (sigma_delta->num_slots > 1) {
+ if (!indio_dev->info->update_scan_mode) {
+ dev_err(&spi->dev, "iio_dev lacks update_scan_mode().\n");
+ return -EINVAL;
+ }
+
+ if (!info->disable_all) {
+ dev_err(&spi->dev, "ad_sigma_delta_info lacks disable_all().\n");
+ return -EINVAL;
+ }
+ }
+
iio_device_set_drvdata(indio_dev, sigma_delta);
return 0;
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 854b1f81d807..b764823ce57e 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1117,7 +1117,7 @@ static int at91_adc_buffer_prepare(struct iio_dev *indio_dev)
return at91_adc_configure_touch(st, true);
/* if we are not in triggered mode, we cannot enable the buffer. */
- if (!(indio_dev->currentmode & INDIO_ALL_TRIGGERED_MODES))
+ if (!(iio_device_get_current_mode(indio_dev) & INDIO_ALL_TRIGGERED_MODES))
return -EINVAL;
/* we continue with the triggered buffer */
@@ -1159,7 +1159,7 @@ static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
return at91_adc_configure_touch(st, false);
/* if we are not in triggered mode, nothing to do here */
- if (!(indio_dev->currentmode & INDIO_ALL_TRIGGERED_MODES))
+ if (!(iio_device_get_current_mode(indio_dev) & INDIO_ALL_TRIGGERED_MODES))
return -EINVAL;
/*
diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
index 8d902a32a0fd..abad16803849 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -550,7 +550,7 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev,
bool val;
int ret;
- ret = strtobool(buf, &val);
+ ret = kstrtobool(buf, &val);
if (ret)
return ret;
@@ -1027,7 +1027,6 @@ static int ina2xx_probe(struct i2c_client *client,
indio_dev->name = id->name;
ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev,
- INDIO_BUFFER_SOFTWARE,
&ina2xx_setup_ops);
if (ret)
return ret;
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 61e80bf3d05e..fd000345ec5c 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -376,7 +376,8 @@ static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc,
adc->adc_info[adc_chan].gain_error;
if (val < 0) {
- dev_err(adc->dev, "Mismatch with calibration\n");
+ if (val < -10)
+ dev_err(adc->dev, "Mismatch with calibration var = %d\n", val);
return 0;
}
diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c
index 00098caf6d9e..e9ff2d6a8a57 100644
--- a/drivers/iio/adc/sc27xx_adc.c
+++ b/drivers/iio/adc/sc27xx_adc.c
@@ -9,12 +9,16 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
/* PMIC global registers definition */
-#define SC27XX_MODULE_EN 0xc08
+#define SC2730_MODULE_EN 0x1808
+#define SC2731_MODULE_EN 0xc08
#define SC27XX_MODULE_ADC_EN BIT(5)
-#define SC27XX_ARM_CLK_EN 0xc10
+#define SC2721_ARM_CLK_EN 0xc0c
+#define SC2730_ARM_CLK_EN 0x180c
+#define SC2731_ARM_CLK_EN 0xc10
#define SC27XX_CLK_ADC_EN BIT(5)
#define SC27XX_CLK_ADC_CLK_EN BIT(6)
@@ -36,8 +40,10 @@
/* Bits and mask definition for SC27XX_ADC_CH_CFG register */
#define SC27XX_ADC_CHN_ID_MASK GENMASK(4, 0)
-#define SC27XX_ADC_SCALE_MASK GENMASK(10, 8)
-#define SC27XX_ADC_SCALE_SHIFT 8
+#define SC27XX_ADC_SCALE_MASK GENMASK(10, 9)
+#define SC2721_ADC_SCALE_MASK BIT(5)
+#define SC27XX_ADC_SCALE_SHIFT 9
+#define SC2721_ADC_SCALE_SHIFT 5
/* Bits definitions for SC27XX_ADC_INT_EN registers */
#define SC27XX_ADC_IRQ_EN BIT(0)
@@ -67,8 +73,15 @@
#define SC27XX_RATIO_NUMERATOR_OFFSET 16
#define SC27XX_RATIO_DENOMINATOR_MASK GENMASK(15, 0)
+/* ADC specific channel reference voltage 3.5V */
+#define SC27XX_ADC_REFVOL_VDD35 3500000
+
+/* ADC default channel reference voltage is 2.8V */
+#define SC27XX_ADC_REFVOL_VDD28 2800000
+
struct sc27xx_adc_data {
struct device *dev;
+ struct regulator *volref;
struct regmap *regmap;
/*
* One hardware spinlock to synchronize between the multiple
@@ -78,6 +91,24 @@ struct sc27xx_adc_data {
int channel_scale[SC27XX_ADC_CHANNEL_MAX];
u32 base;
int irq;
+ const struct sc27xx_adc_variant_data *var_data;
+};
+
+/*
+ * Since different PMICs of SC27xx series can have different
+ * address and ratio, we should save ratio config and base
+ * in the device data structure.
+ */
+struct sc27xx_adc_variant_data {
+ u32 module_en;
+ u32 clk_en;
+ u32 scale_shift;
+ u32 scale_mask;
+ const struct sc27xx_adc_linear_graph *bscale_cal;
+ const struct sc27xx_adc_linear_graph *sscale_cal;
+ void (*init_scale)(struct sc27xx_adc_data *data);
+ int (*get_ratio)(int channel, int scale);
+ bool set_volref;
};
struct sc27xx_adc_linear_graph {
@@ -103,6 +134,16 @@ static struct sc27xx_adc_linear_graph small_scale_graph = {
100, 341,
};
+static const struct sc27xx_adc_linear_graph sc2731_big_scale_graph_calib = {
+ 4200, 850,
+ 3600, 728,
+};
+
+static const struct sc27xx_adc_linear_graph sc2731_small_scale_graph_calib = {
+ 1000, 838,
+ 100, 84,
+};
+
static const struct sc27xx_adc_linear_graph big_scale_graph_calib = {
4200, 856,
3600, 733,
@@ -118,49 +159,225 @@ static int sc27xx_adc_get_calib_data(u32 calib_data, int calib_adc)
return ((calib_data & 0xff) + calib_adc - 128) * 4;
}
+/* get the adc nvmem cell calibration data */
+static int adc_nvmem_cell_calib_data(struct sc27xx_adc_data *data, const char *cell_name)
+{
+ struct nvmem_cell *cell;
+ void *buf;
+ u32 origin_calib_data = 0;
+ size_t len;
+
+ if (!data)
+ return -EINVAL;
+
+ cell = nvmem_cell_get(data->dev, cell_name);
+ if (IS_ERR(cell))
+ return PTR_ERR(cell);
+
+ buf = nvmem_cell_read(cell, &len);
+ if (IS_ERR(buf)) {
+ nvmem_cell_put(cell);
+ return PTR_ERR(buf);
+ }
+
+ memcpy(&origin_calib_data, buf, min(len, sizeof(u32)));
+
+ kfree(buf);
+ nvmem_cell_put(cell);
+ return origin_calib_data;
+}
+
static int sc27xx_adc_scale_calibration(struct sc27xx_adc_data *data,
bool big_scale)
{
const struct sc27xx_adc_linear_graph *calib_graph;
struct sc27xx_adc_linear_graph *graph;
- struct nvmem_cell *cell;
const char *cell_name;
u32 calib_data = 0;
- void *buf;
- size_t len;
if (big_scale) {
- calib_graph = &big_scale_graph_calib;
+ calib_graph = data->var_data->bscale_cal;
graph = &big_scale_graph;
cell_name = "big_scale_calib";
} else {
- calib_graph = &small_scale_graph_calib;
+ calib_graph = data->var_data->sscale_cal;
graph = &small_scale_graph;
cell_name = "small_scale_calib";
}
- cell = nvmem_cell_get(data->dev, cell_name);
- if (IS_ERR(cell))
- return PTR_ERR(cell);
-
- buf = nvmem_cell_read(cell, &len);
- nvmem_cell_put(cell);
-
- if (IS_ERR(buf))
- return PTR_ERR(buf);
-
- memcpy(&calib_data, buf, min(len, sizeof(u32)));
+ calib_data = adc_nvmem_cell_calib_data(data, cell_name);
/* Only need to calibrate the adc values in the linear graph. */
graph->adc0 = sc27xx_adc_get_calib_data(calib_data, calib_graph->adc0);
graph->adc1 = sc27xx_adc_get_calib_data(calib_data >> 8,
calib_graph->adc1);
- kfree(buf);
return 0;
}
-static int sc27xx_adc_get_ratio(int channel, int scale)
+static int sc2720_adc_get_ratio(int channel, int scale)
+{
+ switch (channel) {
+ case 14:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(68, 900);
+ case 1:
+ return SC27XX_VOLT_RATIO(68, 1760);
+ case 2:
+ return SC27XX_VOLT_RATIO(68, 2327);
+ case 3:
+ return SC27XX_VOLT_RATIO(68, 3654);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 16:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(48, 100);
+ case 1:
+ return SC27XX_VOLT_RATIO(480, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(480, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(48, 406);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 21:
+ case 22:
+ case 23:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(3, 8);
+ case 1:
+ return SC27XX_VOLT_RATIO(375, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(375, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(300, 3248);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ default:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(1, 1);
+ case 1:
+ return SC27XX_VOLT_RATIO(1000, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(1000, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(100, 406);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ }
+ return SC27XX_VOLT_RATIO(1, 1);
+}
+
+static int sc2721_adc_get_ratio(int channel, int scale)
+{
+ switch (channel) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ return scale ? SC27XX_VOLT_RATIO(400, 1025) :
+ SC27XX_VOLT_RATIO(1, 1);
+ case 5:
+ return SC27XX_VOLT_RATIO(7, 29);
+ case 7:
+ case 9:
+ return scale ? SC27XX_VOLT_RATIO(100, 125) :
+ SC27XX_VOLT_RATIO(1, 1);
+ case 14:
+ return SC27XX_VOLT_RATIO(68, 900);
+ case 16:
+ return SC27XX_VOLT_RATIO(48, 100);
+ case 19:
+ return SC27XX_VOLT_RATIO(1, 3);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ return SC27XX_VOLT_RATIO(1, 1);
+}
+
+static int sc2730_adc_get_ratio(int channel, int scale)
+{
+ switch (channel) {
+ case 14:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(68, 900);
+ case 1:
+ return SC27XX_VOLT_RATIO(68, 1760);
+ case 2:
+ return SC27XX_VOLT_RATIO(68, 2327);
+ case 3:
+ return SC27XX_VOLT_RATIO(68, 3654);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 15:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(1, 3);
+ case 1:
+ return SC27XX_VOLT_RATIO(1000, 5865);
+ case 2:
+ return SC27XX_VOLT_RATIO(500, 3879);
+ case 3:
+ return SC27XX_VOLT_RATIO(500, 6090);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 16:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(48, 100);
+ case 1:
+ return SC27XX_VOLT_RATIO(480, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(480, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(48, 406);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 21:
+ case 22:
+ case 23:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(3, 8);
+ case 1:
+ return SC27XX_VOLT_RATIO(375, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(375, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(300, 3248);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ default:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(1, 1);
+ case 1:
+ return SC27XX_VOLT_RATIO(1000, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(1000, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(1000, 4060);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ }
+ return SC27XX_VOLT_RATIO(1, 1);
+}
+
+static int sc2731_adc_get_ratio(int channel, int scale)
{
switch (channel) {
case 1:
@@ -185,10 +402,87 @@ static int sc27xx_adc_get_ratio(int channel, int scale)
return SC27XX_VOLT_RATIO(1, 1);
}
+/*
+ * According to the datasheet set specific value on some channel.
+ */
+static void sc2720_adc_scale_init(struct sc27xx_adc_data *data)
+{
+ int i;
+
+ for (i = 0; i < SC27XX_ADC_CHANNEL_MAX; i++) {
+ switch (i) {
+ case 5:
+ data->channel_scale[i] = 3;
+ break;
+ case 7:
+ case 9:
+ data->channel_scale[i] = 2;
+ break;
+ case 13:
+ data->channel_scale[i] = 1;
+ break;
+ case 19:
+ case 30:
+ case 31:
+ data->channel_scale[i] = 3;
+ break;
+ default:
+ data->channel_scale[i] = 0;
+ break;
+ }
+ }
+}
+
+static void sc2730_adc_scale_init(struct sc27xx_adc_data *data)
+{
+ int i;
+
+ for (i = 0; i < SC27XX_ADC_CHANNEL_MAX; i++) {
+ switch (i) {
+ case 5:
+ case 10:
+ case 19:
+ case 30:
+ case 31:
+ data->channel_scale[i] = 3;
+ break;
+ case 7:
+ case 9:
+ data->channel_scale[i] = 2;
+ break;
+ case 13:
+ data->channel_scale[i] = 1;
+ break;
+ default:
+ data->channel_scale[i] = 0;
+ break;
+ }
+ }
+}
+
+static void sc2731_adc_scale_init(struct sc27xx_adc_data *data)
+{
+ int i;
+ /*
+ * In the current software design, SC2731 support 2 scales,
+ * channels 5 uses big scale, others use smale.
+ */
+ for (i = 0; i < SC27XX_ADC_CHANNEL_MAX; i++) {
+ switch (i) {
+ case 5:
+ data->channel_scale[i] = 1;
+ break;
+ default:
+ data->channel_scale[i] = 0;
+ break;
+ }
+ }
+}
+
static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel,
int scale, int *val)
{
- int ret;
+ int ret, ret_volref;
u32 tmp, value, status;
ret = hwspin_lock_timeout_raw(data->hwlock, SC27XX_ADC_HWLOCK_TIMEOUT);
@@ -197,10 +491,25 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel,
return ret;
}
+ /*
+ * According to the sc2721 chip data sheet, the reference voltage of
+ * specific channel 30 and channel 31 in ADC module needs to be set from
+ * the default 2.8v to 3.5v.
+ */
+ if ((data->var_data->set_volref) && (channel == 30 || channel == 31)) {
+ ret = regulator_set_voltage(data->volref,
+ SC27XX_ADC_REFVOL_VDD35,
+ SC27XX_ADC_REFVOL_VDD35);
+ if (ret) {
+ dev_err(data->dev, "failed to set the volref 3.5v\n");
+ goto unlock_adc;
+ }
+ }
+
ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL,
SC27XX_ADC_EN, SC27XX_ADC_EN);
if (ret)
- goto unlock_adc;
+ goto regulator_restore;
ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR,
SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR);
@@ -208,10 +517,11 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel,
goto disable_adc;
/* Configure the channel id and scale */
- tmp = (scale << SC27XX_ADC_SCALE_SHIFT) & SC27XX_ADC_SCALE_MASK;
+ tmp = (scale << data->var_data->scale_shift) & data->var_data->scale_mask;
tmp |= channel & SC27XX_ADC_CHN_ID_MASK;
ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CH_CFG,
- SC27XX_ADC_CHN_ID_MASK | SC27XX_ADC_SCALE_MASK,
+ SC27XX_ADC_CHN_ID_MASK |
+ data->var_data->scale_mask,
tmp);
if (ret)
goto disable_adc;
@@ -249,6 +559,17 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel,
disable_adc:
regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL,
SC27XX_ADC_EN, 0);
+regulator_restore:
+ if ((data->var_data->set_volref) && (channel == 30 || channel == 31)) {
+ ret_volref = regulator_set_voltage(data->volref,
+ SC27XX_ADC_REFVOL_VDD28,
+ SC27XX_ADC_REFVOL_VDD28);
+ if (ret_volref) {
+ dev_err(data->dev, "failed to set the volref 2.8v,ret_volref = 0x%x\n",
+ ret_volref);
+ ret = ret || ret_volref;
+ }
+ }
unlock_adc:
hwspin_unlock_raw(data->hwlock);
@@ -262,13 +583,14 @@ static void sc27xx_adc_volt_ratio(struct sc27xx_adc_data *data,
int channel, int scale,
u32 *div_numerator, u32 *div_denominator)
{
- u32 ratio = sc27xx_adc_get_ratio(channel, scale);
+ u32 ratio;
+ ratio = data->var_data->get_ratio(channel, scale);
*div_numerator = ratio >> SC27XX_RATIO_NUMERATOR_OFFSET;
*div_denominator = ratio & SC27XX_RATIO_DENOMINATOR_MASK;
}
-static int sc27xx_adc_to_volt(struct sc27xx_adc_linear_graph *graph,
+static int adc_to_volt(struct sc27xx_adc_linear_graph *graph,
int raw_adc)
{
int tmp;
@@ -277,6 +599,16 @@ static int sc27xx_adc_to_volt(struct sc27xx_adc_linear_graph *graph,
tmp /= (graph->adc0 - graph->adc1);
tmp += graph->volt1;
+ return tmp;
+}
+
+static int sc27xx_adc_to_volt(struct sc27xx_adc_linear_graph *graph,
+ int raw_adc)
+{
+ int tmp;
+
+ tmp = adc_to_volt(graph, raw_adc);
+
return tmp < 0 ? 0 : tmp;
}
@@ -432,13 +764,13 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data)
{
int ret;
- ret = regmap_update_bits(data->regmap, SC27XX_MODULE_EN,
+ ret = regmap_update_bits(data->regmap, data->var_data->module_en,
SC27XX_MODULE_ADC_EN, SC27XX_MODULE_ADC_EN);
if (ret)
return ret;
/* Enable ADC work clock and controller clock */
- ret = regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN,
+ ret = regmap_update_bits(data->regmap, data->var_data->clk_en,
SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN,
SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN);
if (ret)
@@ -456,10 +788,10 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data)
return 0;
disable_clk:
- regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN,
+ regmap_update_bits(data->regmap, data->var_data->clk_en,
SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0);
disable_adc:
- regmap_update_bits(data->regmap, SC27XX_MODULE_EN,
+ regmap_update_bits(data->regmap, data->var_data->module_en,
SC27XX_MODULE_ADC_EN, 0);
return ret;
@@ -470,21 +802,76 @@ static void sc27xx_adc_disable(void *_data)
struct sc27xx_adc_data *data = _data;
/* Disable ADC work clock and controller clock */
- regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN,
+ regmap_update_bits(data->regmap, data->var_data->clk_en,
SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0);
- regmap_update_bits(data->regmap, SC27XX_MODULE_EN,
+ regmap_update_bits(data->regmap, data->var_data->module_en,
SC27XX_MODULE_ADC_EN, 0);
}
+static const struct sc27xx_adc_variant_data sc2731_data = {
+ .module_en = SC2731_MODULE_EN,
+ .clk_en = SC2731_ARM_CLK_EN,
+ .scale_shift = SC27XX_ADC_SCALE_SHIFT,
+ .scale_mask = SC27XX_ADC_SCALE_MASK,
+ .bscale_cal = &sc2731_big_scale_graph_calib,
+ .sscale_cal = &sc2731_small_scale_graph_calib,
+ .init_scale = sc2731_adc_scale_init,
+ .get_ratio = sc2731_adc_get_ratio,
+ .set_volref = false,
+};
+
+static const struct sc27xx_adc_variant_data sc2730_data = {
+ .module_en = SC2730_MODULE_EN,
+ .clk_en = SC2730_ARM_CLK_EN,
+ .scale_shift = SC27XX_ADC_SCALE_SHIFT,
+ .scale_mask = SC27XX_ADC_SCALE_MASK,
+ .bscale_cal = &big_scale_graph_calib,
+ .sscale_cal = &small_scale_graph_calib,
+ .init_scale = sc2730_adc_scale_init,
+ .get_ratio = sc2730_adc_get_ratio,
+ .set_volref = false,
+};
+
+static const struct sc27xx_adc_variant_data sc2721_data = {
+ .module_en = SC2731_MODULE_EN,
+ .clk_en = SC2721_ARM_CLK_EN,
+ .scale_shift = SC2721_ADC_SCALE_SHIFT,
+ .scale_mask = SC2721_ADC_SCALE_MASK,
+ .bscale_cal = &sc2731_big_scale_graph_calib,
+ .sscale_cal = &sc2731_small_scale_graph_calib,
+ .init_scale = sc2731_adc_scale_init,
+ .get_ratio = sc2721_adc_get_ratio,
+ .set_volref = true,
+};
+
+static const struct sc27xx_adc_variant_data sc2720_data = {
+ .module_en = SC2731_MODULE_EN,
+ .clk_en = SC2721_ARM_CLK_EN,
+ .scale_shift = SC27XX_ADC_SCALE_SHIFT,
+ .scale_mask = SC27XX_ADC_SCALE_MASK,
+ .bscale_cal = &big_scale_graph_calib,
+ .sscale_cal = &small_scale_graph_calib,
+ .init_scale = sc2720_adc_scale_init,
+ .get_ratio = sc2720_adc_get_ratio,
+ .set_volref = false,
+};
+
static int sc27xx_adc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct sc27xx_adc_data *sc27xx_data;
+ const struct sc27xx_adc_variant_data *pdata;
struct iio_dev *indio_dev;
int ret;
+ pdata = of_device_get_match_data(dev);
+ if (!pdata) {
+ dev_err(dev, "No matching driver data found\n");
+ return -EINVAL;
+ }
+
indio_dev = devm_iio_device_alloc(dev, sizeof(*sc27xx_data));
if (!indio_dev)
return -ENOMEM;
@@ -520,6 +907,16 @@ static int sc27xx_adc_probe(struct platform_device *pdev)
}
sc27xx_data->dev = dev;
+ if (pdata->set_volref) {
+ sc27xx_data->volref = devm_regulator_get(dev, "vref");
+ if (IS_ERR(sc27xx_data->volref)) {
+ ret = PTR_ERR(sc27xx_data->volref);
+ return dev_err_probe(dev, ret, "failed to get ADC volref\n");
+ }
+ }
+
+ sc27xx_data->var_data = pdata;
+ sc27xx_data->var_data->init_scale(sc27xx_data);
ret = sc27xx_adc_enable(sc27xx_data);
if (ret) {
@@ -546,7 +943,10 @@ static int sc27xx_adc_probe(struct platform_device *pdev)
}
static const struct of_device_id sc27xx_adc_of_match[] = {
- { .compatible = "sprd,sc2731-adc", },
+ { .compatible = "sprd,sc2731-adc", .data = &sc2731_data},
+ { .compatible = "sprd,sc2730-adc", .data = &sc2730_data},
+ { .compatible = "sprd,sc2721-adc", .data = &sc2721_data},
+ { .compatible = "sprd,sc2720-adc", .data = &sc2720_data},
{ }
};
MODULE_DEVICE_TABLE(of, sc27xx_adc_of_match);
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 9704cf0b9753..6d21ea84fa82 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -466,8 +466,7 @@ static int stm32_dfsdm_channels_configure(struct iio_dev *indio_dev,
* In continuous mode, use fast mode configuration,
* if it provides a better resolution.
*/
- if (adc->nconv == 1 && !trig &&
- (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE)) {
+ if (adc->nconv == 1 && !trig && iio_buffer_enabled(indio_dev)) {
if (fl->flo[1].res >= fl->flo[0].res) {
fl->fast = 1;
flo = &fl->flo[1];
@@ -562,7 +561,7 @@ static int stm32_dfsdm_filter_configure(struct iio_dev *indio_dev,
cr1 = DFSDM_CR1_RCH(chan->channel);
/* Continuous conversions triggered by SPI clk in buffer mode */
- if (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE)
+ if (iio_buffer_enabled(indio_dev))
cr1 |= DFSDM_CR1_RCONT(1);
cr1 |= DFSDM_CR1_RSYNC(fl->sync_mode);
diff --git a/drivers/iio/adc/stmpe-adc.c b/drivers/iio/adc/stmpe-adc.c
index d2d405388499..000e5cfecb43 100644
--- a/drivers/iio/adc/stmpe-adc.c
+++ b/drivers/iio/adc/stmpe-adc.c
@@ -61,7 +61,7 @@ struct stmpe_adc {
static int stmpe_read_voltage(struct stmpe_adc *info,
struct iio_chan_spec const *chan, int *val)
{
- long ret;
+ unsigned long ret;
mutex_lock(&info->lock);
@@ -79,7 +79,7 @@ static int stmpe_read_voltage(struct stmpe_adc *info,
ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT);
- if (ret <= 0) {
+ if (ret == 0) {
stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA,
STMPE_ADC_CH(info->channel));
mutex_unlock(&info->lock);
@@ -96,7 +96,7 @@ static int stmpe_read_voltage(struct stmpe_adc *info,
static int stmpe_read_temp(struct stmpe_adc *info,
struct iio_chan_spec const *chan, int *val)
{
- long ret;
+ unsigned long ret;
mutex_lock(&info->lock);
@@ -114,7 +114,7 @@ static int stmpe_read_temp(struct stmpe_adc *info,
ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT);
- if (ret <= 0) {
+ if (ret == 0) {
mutex_unlock(&info->lock);
return -ETIMEDOUT;
}
@@ -345,21 +345,22 @@ static int __maybe_unused stmpe_adc_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(stmpe_adc_pm_ops, NULL, stmpe_adc_resume);
+static const struct of_device_id stmpe_adc_ids[] = {
+ { .compatible = "st,stmpe-adc", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, stmpe_adc_ids);
+
static struct platform_driver stmpe_adc_driver = {
.probe = stmpe_adc_probe,
.driver = {
.name = "stmpe-adc",
.pm = &stmpe_adc_pm_ops,
+ .of_match_table = stmpe_adc_ids,
},
};
module_platform_driver(stmpe_adc_driver);
-static const struct of_device_id stmpe_adc_ids[] = {
- { .compatible = "st,stmpe-adc", },
- { },
-};
-MODULE_DEVICE_TABLE(of, stmpe_adc_ids);
-
MODULE_AUTHOR("Stefan Agner <stefan.agner@toradex.com>");
MODULE_DESCRIPTION("STMPEXXX ADC driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 068efbce1710..5544da80b636 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -76,10 +76,15 @@
#define ADS1015_DEFAULT_DATA_RATE 4
#define ADS1015_DEFAULT_CHAN 0
-enum chip_ids {
- ADSXXXX = 0,
- ADS1015,
- ADS1115,
+struct ads1015_chip_data {
+ struct iio_chan_spec const *channels;
+ int num_channels;
+ const struct iio_info *info;
+ const int *data_rate;
+ const int data_rate_len;
+ const int *scale;
+ const int scale_len;
+ bool has_comparator;
};
enum ads1015_channels {
@@ -94,11 +99,11 @@ enum ads1015_channels {
ADS1015_TIMESTAMP,
};
-static const unsigned int ads1015_data_rate[] = {
+static const int ads1015_data_rate[] = {
128, 250, 490, 920, 1600, 2400, 3300, 3300
};
-static const unsigned int ads1115_data_rate[] = {
+static const int ads1115_data_rate[] = {
8, 16, 32, 64, 128, 250, 475, 860
};
@@ -106,10 +111,28 @@ static const unsigned int ads1115_data_rate[] = {
* Translation from PGA bits to full-scale positive and negative input voltage
* range in mV
*/
-static int ads1015_fullscale_range[] = {
+static const int ads1015_fullscale_range[] = {
6144, 4096, 2048, 1024, 512, 256, 256, 256
};
+static const int ads1015_scale[] = { /* 12bit ADC */
+ 256, 11,
+ 512, 11,
+ 1024, 11,
+ 2048, 11,
+ 4096, 11,
+ 6144, 11
+};
+
+static const int ads1115_scale[] = { /* 16bit ADC */
+ 256, 15,
+ 512, 15,
+ 1024, 15,
+ 2048, 15,
+ 4096, 15,
+ 6144, 15
+};
+
/*
* Translation from COMP_QUE field value to the number of successive readings
* exceed the threshold values before an interrupt is generated
@@ -134,71 +157,53 @@ static const struct iio_event_spec ads1015_events[] = {
},
};
-#define ADS1015_V_CHAN(_chan, _addr) { \
- .type = IIO_VOLTAGE, \
- .indexed = 1, \
- .address = _addr, \
- .channel = _chan, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- .scan_index = _addr, \
- .scan_type = { \
- .sign = 's', \
- .realbits = 12, \
- .storagebits = 16, \
- .shift = 4, \
- .endianness = IIO_CPU, \
- }, \
- .event_spec = ads1015_events, \
- .num_event_specs = ARRAY_SIZE(ads1015_events), \
- .datasheet_name = "AIN"#_chan, \
-}
-
-#define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \
+/*
+ * Compile-time check whether _fitbits can accommodate up to _testbits
+ * bits. Returns _fitbits on success, fails to compile otherwise.
+ *
+ * The test works such that it multiplies constant _fitbits by constant
+ * double-negation of size of a non-empty structure, i.e. it multiplies
+ * constant _fitbits by constant 1 in each successful compilation case.
+ * The non-empty structure may contain C11 _Static_assert(), make use of
+ * this and place the kernel variant of static assert in there, so that
+ * it performs the compile-time check for _testbits <= _fitbits. Note
+ * that it is not possible to directly use static_assert in compound
+ * statements, hence this convoluted construct.
+ */
+#define FIT_CHECK(_testbits, _fitbits) \
+ ( \
+ (_fitbits) * \
+ !!sizeof(struct { \
+ static_assert((_testbits) <= (_fitbits)); \
+ int pad; \
+ }) \
+ )
+
+#define ADS1015_V_CHAN(_chan, _addr, _realbits, _shift, _event_spec, _num_event_specs) { \
.type = IIO_VOLTAGE, \
- .differential = 1, \
.indexed = 1, \
.address = _addr, \
.channel = _chan, \
- .channel2 = _chan2, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- .scan_index = _addr, \
- .scan_type = { \
- .sign = 's', \
- .realbits = 12, \
- .storagebits = 16, \
- .shift = 4, \
- .endianness = IIO_CPU, \
- }, \
- .event_spec = ads1015_events, \
- .num_event_specs = ARRAY_SIZE(ads1015_events), \
- .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
-}
-
-#define ADS1115_V_CHAN(_chan, _addr) { \
- .type = IIO_VOLTAGE, \
- .indexed = 1, \
- .address = _addr, \
- .channel = _chan, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ .info_mask_shared_by_all_available = \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = _addr, \
.scan_type = { \
.sign = 's', \
- .realbits = 16, \
- .storagebits = 16, \
+ .realbits = (_realbits), \
+ .storagebits = FIT_CHECK((_realbits) + (_shift), 16), \
+ .shift = (_shift), \
.endianness = IIO_CPU, \
}, \
- .event_spec = ads1015_events, \
- .num_event_specs = ARRAY_SIZE(ads1015_events), \
+ .event_spec = (_event_spec), \
+ .num_event_specs = (_num_event_specs), \
.datasheet_name = "AIN"#_chan, \
}
-#define ADS1115_V_DIFF_CHAN(_chan, _chan2, _addr) { \
+#define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr, _realbits, _shift, _event_spec, _num_event_specs) { \
.type = IIO_VOLTAGE, \
.differential = 1, \
.indexed = 1, \
@@ -208,15 +213,19 @@ static const struct iio_event_spec ads1015_events[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_all_available = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = _addr, \
.scan_type = { \
.sign = 's', \
- .realbits = 16, \
- .storagebits = 16, \
+ .realbits = (_realbits), \
+ .storagebits = FIT_CHECK((_realbits) + (_shift), 16), \
+ .shift = (_shift), \
.endianness = IIO_CPU, \
}, \
- .event_spec = ads1015_events, \
- .num_event_specs = ARRAY_SIZE(ads1015_events), \
+ .event_spec = (_event_spec), \
+ .num_event_specs = (_num_event_specs), \
.datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
}
@@ -245,7 +254,7 @@ struct ads1015_data {
unsigned int comp_mode;
struct ads1015_thresh_data thresh_data[ADS1015_CHANNELS];
- unsigned int *data_rate;
+ const struct ads1015_chip_data *chip;
/*
* Set to true when the ADC is switched to the continuous-conversion
* mode and exits from a power-down state. This flag is used to avoid
@@ -273,49 +282,91 @@ static void ads1015_event_channel_disable(struct ads1015_data *data, int chan)
data->event_channel = ADS1015_CHANNELS;
}
-static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case ADS1015_CFG_REG:
- case ADS1015_LO_THRESH_REG:
- case ADS1015_HI_THRESH_REG:
- return true;
- default:
- return false;
- }
-}
+static const struct regmap_range ads1015_writeable_ranges[] = {
+ regmap_reg_range(ADS1015_CFG_REG, ADS1015_HI_THRESH_REG),
+};
+
+static const struct regmap_access_table ads1015_writeable_table = {
+ .yes_ranges = ads1015_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ads1015_writeable_ranges),
+};
static const struct regmap_config ads1015_regmap_config = {
.reg_bits = 8,
.val_bits = 16,
.max_register = ADS1015_HI_THRESH_REG,
- .writeable_reg = ads1015_is_writeable_reg,
+ .wr_table = &ads1015_writeable_table,
+};
+
+static const struct regmap_range tla2024_writeable_ranges[] = {
+ regmap_reg_range(ADS1015_CFG_REG, ADS1015_CFG_REG),
+};
+
+static const struct regmap_access_table tla2024_writeable_table = {
+ .yes_ranges = tla2024_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(tla2024_writeable_ranges),
+};
+
+static const struct regmap_config tla2024_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = ADS1015_CFG_REG,
+ .wr_table = &tla2024_writeable_table,
};
static const struct iio_chan_spec ads1015_channels[] = {
- ADS1015_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1),
- ADS1015_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3),
- ADS1015_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3),
- ADS1015_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3),
- ADS1015_V_CHAN(0, ADS1015_AIN0),
- ADS1015_V_CHAN(1, ADS1015_AIN1),
- ADS1015_V_CHAN(2, ADS1015_AIN2),
- ADS1015_V_CHAN(3, ADS1015_AIN3),
+ ADS1015_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1, 12, 4,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3, 12, 4,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3, 12, 4,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3, 12, 4,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_CHAN(0, ADS1015_AIN0, 12, 4,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_CHAN(1, ADS1015_AIN1, 12, 4,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_CHAN(2, ADS1015_AIN2, 12, 4,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_CHAN(3, ADS1015_AIN3, 12, 4,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
};
static const struct iio_chan_spec ads1115_channels[] = {
- ADS1115_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1),
- ADS1115_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3),
- ADS1115_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3),
- ADS1115_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3),
- ADS1115_V_CHAN(0, ADS1015_AIN0),
- ADS1115_V_CHAN(1, ADS1015_AIN1),
- ADS1115_V_CHAN(2, ADS1015_AIN2),
- ADS1115_V_CHAN(3, ADS1015_AIN3),
+ ADS1015_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1, 16, 0,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3, 16, 0,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3, 16, 0,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3, 16, 0,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_CHAN(0, ADS1015_AIN0, 16, 0,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_CHAN(1, ADS1015_AIN1, 16, 0,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_CHAN(2, ADS1015_AIN2, 16, 0,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
+ ADS1015_V_CHAN(3, ADS1015_AIN3, 16, 0,
+ ads1015_events, ARRAY_SIZE(ads1015_events)),
IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
};
+static const struct iio_chan_spec tla2024_channels[] = {
+ ADS1015_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1, 12, 4, NULL, 0),
+ ADS1015_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3, 12, 4, NULL, 0),
+ ADS1015_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3, 12, 4, NULL, 0),
+ ADS1015_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3, 12, 4, NULL, 0),
+ ADS1015_V_CHAN(0, ADS1015_AIN0, 12, 4, NULL, 0),
+ ADS1015_V_CHAN(1, ADS1015_AIN1, 12, 4, NULL, 0),
+ ADS1015_V_CHAN(2, ADS1015_AIN2, 12, 4, NULL, 0),
+ ADS1015_V_CHAN(3, ADS1015_AIN3, 12, 4, NULL, 0),
+ IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
+};
+
+
#ifdef CONFIG_PM
static int ads1015_set_power_state(struct ads1015_data *data, bool on)
{
@@ -344,6 +395,7 @@ static int ads1015_set_power_state(struct ads1015_data *data, bool on)
static
int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
{
+ const int *data_rate = data->chip->data_rate;
int ret, pga, dr, dr_old, conv_time;
unsigned int old, mask, cfg;
@@ -378,8 +430,8 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
}
if (data->conv_invalid) {
dr_old = (old & ADS1015_CFG_DR_MASK) >> ADS1015_CFG_DR_SHIFT;
- conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr_old]);
- conv_time += DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
+ conv_time = DIV_ROUND_UP(USEC_PER_SEC, data_rate[dr_old]);
+ conv_time += DIV_ROUND_UP(USEC_PER_SEC, data_rate[dr]);
conv_time += conv_time / 10; /* 10% internal clock inaccuracy */
usleep_range(conv_time, conv_time + 1);
data->conv_invalid = false;
@@ -445,8 +497,8 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate)
{
int i;
- for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) {
- if (data->data_rate[i] == rate) {
+ for (i = 0; i < data->chip->data_rate_len; i++) {
+ if (data->chip->data_rate[i] == rate) {
data->channel_data[chan].data_rate = i;
return 0;
}
@@ -455,6 +507,32 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate)
return -EINVAL;
}
+static int ads1015_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct ads1015_data *data = iio_priv(indio_dev);
+
+ if (chan->type != IIO_VOLTAGE)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ *type = IIO_VAL_FRACTIONAL_LOG2;
+ *vals = data->chip->scale;
+ *length = data->chip->scale_len;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *type = IIO_VAL_INT;
+ *vals = data->chip->data_rate;
+ *length = data->chip->data_rate_len;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
static int ads1015_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -504,7 +582,7 @@ release_direct:
break;
case IIO_CHAN_INFO_SAMP_FREQ:
idx = data->channel_data[chan->address].data_rate;
- *val = data->data_rate[idx];
+ *val = data->chip->data_rate[idx];
ret = IIO_VAL_INT;
break;
default:
@@ -564,7 +642,7 @@ static int ads1015_read_event(struct iio_dev *indio_dev,
dr = data->channel_data[chan->address].data_rate;
comp_queue = data->thresh_data[chan->address].comp_queue;
period = ads1015_comp_queue[comp_queue] *
- USEC_PER_SEC / data->data_rate[dr];
+ USEC_PER_SEC / data->chip->data_rate[dr];
*val = period / USEC_PER_SEC;
*val2 = period % USEC_PER_SEC;
@@ -586,6 +664,7 @@ static int ads1015_write_event(struct iio_dev *indio_dev,
int val2)
{
struct ads1015_data *data = iio_priv(indio_dev);
+ const int *data_rate = data->chip->data_rate;
int realbits = chan->scan_type.realbits;
int ret = 0;
long long period;
@@ -611,7 +690,7 @@ static int ads1015_write_event(struct iio_dev *indio_dev,
for (i = 0; i < ARRAY_SIZE(ads1015_comp_queue) - 1; i++) {
if (period <= ads1015_comp_queue[i] *
- USEC_PER_SEC / data->data_rate[dr])
+ USEC_PER_SEC / data_rate[dr])
break;
}
data->thresh_data[chan->address].comp_queue = i;
@@ -802,54 +881,20 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = {
.validate_scan_mask = &iio_validate_scan_mask_onehot,
};
-static IIO_CONST_ATTR_NAMED(ads1015_scale_available, scale_available,
- "3 2 1 0.5 0.25 0.125");
-static IIO_CONST_ATTR_NAMED(ads1115_scale_available, scale_available,
- "0.1875 0.125 0.0625 0.03125 0.015625 0.007813");
-
-static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available,
- sampling_frequency_available, "128 250 490 920 1600 2400 3300");
-static IIO_CONST_ATTR_NAMED(ads1115_sampling_frequency_available,
- sampling_frequency_available, "8 16 32 64 128 250 475 860");
-
-static struct attribute *ads1015_attributes[] = {
- &iio_const_attr_ads1015_scale_available.dev_attr.attr,
- &iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group ads1015_attribute_group = {
- .attrs = ads1015_attributes,
-};
-
-static struct attribute *ads1115_attributes[] = {
- &iio_const_attr_ads1115_scale_available.dev_attr.attr,
- &iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr,
- NULL,
-};
-
-static const struct attribute_group ads1115_attribute_group = {
- .attrs = ads1115_attributes,
-};
-
static const struct iio_info ads1015_info = {
+ .read_avail = ads1015_read_avail,
.read_raw = ads1015_read_raw,
.write_raw = ads1015_write_raw,
.read_event_value = ads1015_read_event,
.write_event_value = ads1015_write_event,
.read_event_config = ads1015_read_event_config,
.write_event_config = ads1015_write_event_config,
- .attrs = &ads1015_attribute_group,
};
-static const struct iio_info ads1115_info = {
+static const struct iio_info tla2024_info = {
+ .read_avail = ads1015_read_avail,
.read_raw = ads1015_read_raw,
.write_raw = ads1015_write_raw,
- .read_event_value = ads1015_read_event,
- .write_event_value = ads1015_write_event,
- .read_event_config = ads1015_read_event_config,
- .write_event_config = ads1015_write_event_config,
- .attrs = &ads1115_attribute_group,
};
static int ads1015_client_get_channels_config(struct i2c_client *client)
@@ -932,12 +977,18 @@ static int ads1015_set_conv_mode(struct ads1015_data *data, int mode)
static int ads1015_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ const struct ads1015_chip_data *chip;
struct iio_dev *indio_dev;
struct ads1015_data *data;
int ret;
- enum chip_ids chip;
int i;
+ chip = device_get_match_data(&client->dev);
+ if (!chip)
+ chip = (const struct ads1015_chip_data *)id->driver_data;
+ if (!chip)
+ return dev_err_probe(&client->dev, -EINVAL, "Unknown chip\n");
+
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
@@ -950,28 +1001,12 @@ static int ads1015_probe(struct i2c_client *client,
indio_dev->name = ADS1015_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
- chip = (uintptr_t)device_get_match_data(&client->dev);
- if (chip == ADSXXXX)
- chip = id->driver_data;
- switch (chip) {
- case ADS1015:
- indio_dev->channels = ads1015_channels;
- indio_dev->num_channels = ARRAY_SIZE(ads1015_channels);
- indio_dev->info = &ads1015_info;
- data->data_rate = (unsigned int *) &ads1015_data_rate;
- break;
- case ADS1115:
- indio_dev->channels = ads1115_channels;
- indio_dev->num_channels = ARRAY_SIZE(ads1115_channels);
- indio_dev->info = &ads1115_info;
- data->data_rate = (unsigned int *) &ads1115_data_rate;
- break;
- default:
- dev_err(&client->dev, "Unknown chip %d\n", chip);
- return -EINVAL;
- }
-
+ indio_dev->channels = chip->channels;
+ indio_dev->num_channels = chip->num_channels;
+ indio_dev->info = chip->info;
+ data->chip = chip;
data->event_channel = ADS1015_CHANNELS;
+
/*
* Set default lower and upper threshold to min and max value
* respectively.
@@ -986,7 +1021,9 @@ static int ads1015_probe(struct i2c_client *client,
/* we need to keep this ABI the same as used by hwmon ADS1015 driver */
ads1015_get_channels_config(client);
- data->regmap = devm_regmap_init_i2c(client, &ads1015_regmap_config);
+ data->regmap = devm_regmap_init_i2c(client, chip->has_comparator ?
+ &ads1015_regmap_config :
+ &tla2024_regmap_config);
if (IS_ERR(data->regmap)) {
dev_err(&client->dev, "Failed to allocate register map\n");
return PTR_ERR(data->regmap);
@@ -1000,7 +1037,7 @@ static int ads1015_probe(struct i2c_client *client,
return ret;
}
- if (client->irq) {
+ if (client->irq && chip->has_comparator) {
unsigned long irq_trig =
irqd_get_trigger_type(irq_get_irq_data(client->irq));
unsigned int cfg_comp_mask = ADS1015_CFG_COMP_QUE_MASK |
@@ -1099,22 +1136,51 @@ static const struct dev_pm_ops ads1015_pm_ops = {
ads1015_runtime_resume, NULL)
};
+static const struct ads1015_chip_data ads1015_data = {
+ .channels = ads1015_channels,
+ .num_channels = ARRAY_SIZE(ads1015_channels),
+ .info = &ads1015_info,
+ .data_rate = ads1015_data_rate,
+ .data_rate_len = ARRAY_SIZE(ads1015_data_rate),
+ .scale = ads1015_scale,
+ .scale_len = ARRAY_SIZE(ads1015_scale),
+ .has_comparator = true,
+};
+
+static const struct ads1015_chip_data ads1115_data = {
+ .channels = ads1115_channels,
+ .num_channels = ARRAY_SIZE(ads1115_channels),
+ .info = &ads1015_info,
+ .data_rate = ads1115_data_rate,
+ .data_rate_len = ARRAY_SIZE(ads1115_data_rate),
+ .scale = ads1115_scale,
+ .scale_len = ARRAY_SIZE(ads1115_scale),
+ .has_comparator = true,
+};
+
+static const struct ads1015_chip_data tla2024_data = {
+ .channels = tla2024_channels,
+ .num_channels = ARRAY_SIZE(tla2024_channels),
+ .info = &tla2024_info,
+ .data_rate = ads1015_data_rate,
+ .data_rate_len = ARRAY_SIZE(ads1015_data_rate),
+ .scale = ads1015_scale,
+ .scale_len = ARRAY_SIZE(ads1015_scale),
+ .has_comparator = false,
+};
+
static const struct i2c_device_id ads1015_id[] = {
- {"ads1015", ADS1015},
- {"ads1115", ADS1115},
+ { "ads1015", (kernel_ulong_t)&ads1015_data },
+ { "ads1115", (kernel_ulong_t)&ads1115_data },
+ { "tla2024", (kernel_ulong_t)&tla2024_data },
{}
};
MODULE_DEVICE_TABLE(i2c, ads1015_id);
static const struct of_device_id ads1015_of_match[] = {
- {
- .compatible = "ti,ads1015",
- .data = (void *)ADS1015
- },
- {
- .compatible = "ti,ads1115",
- .data = (void *)ADS1115
- },
+ { .compatible = "ti,ads1015", .data = &ads1015_data },
+ { .compatible = "ti,ads1115", .data = &ads1115_data },
+ { .compatible = "ti,tla2024", .data = &tla2024_data },
{}
};
MODULE_DEVICE_TABLE(of, ads1015_of_match);
diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c
index 22c2583eedd0..708cca0a63be 100644
--- a/drivers/iio/adc/ti-ads8688.c
+++ b/drivers/iio/adc/ti-ads8688.c
@@ -508,6 +508,7 @@ MODULE_DEVICE_TABLE(of, ads8688_of_match);
static struct spi_driver ads8688_driver = {
.driver = {
.name = "ads8688",
+ .of_match_table = ads8688_of_match,
},
.probe = ads8688_probe,
.remove = ads8688_remove,
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index dbdc1ef48566..567d43a30955 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -376,9 +376,7 @@ static int tiadc_iio_buffered_hardware_setup(struct device *dev,
{
int ret;
- ret = devm_iio_kfifo_buffer_setup(dev, indio_dev,
- INDIO_BUFFER_SOFTWARE,
- setup_ops);
+ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, setup_ops);
if (ret)
return ret;