summaryrefslogtreecommitdiff
path: root/drivers/iio/dac/ad3552r.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-06-16 12:03:31 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-06-16 12:03:31 +0200
commit2db573c5dc1f896d8c6c73d4bdb6429f8b1dcf34 (patch)
tree3dfcd57209398aafe1b96c3bf776d21781eb4f39 /drivers/iio/dac/ad3552r.c
parenta774c5d1f9c4ad43411ee4010d8eb8e60b8e60a0 (diff)
parent07d4d0bb4a8ddcc463ed599b22f510d5926c2495 (diff)
Merge tag 'iio-for-6.11a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-testing
Jonathan writes: IIO: 1st set of new device support, cleanups etc for 6.11 Lots of new device support and 3 entirely new drivers. Early pull request this cycle to allow for clean picking up of fixes that are dependencies for some queued patch sets. Device support ============== adi,ad3552r - Add AD3541R and AD3551R - single output variants of already supported DACs. adi,ad7192 - Add support for ad7194 24-bit ADC with integrated PGA. adi,ad7380 - New ADC driver built up in a number of steps. Supports - 2 channel differential ADCs: AD7380, AD7381 - 4 channel differential ADCs: AD7380-4, AD7381-4 - 2 channel pseudo-differential ADCs: AD7383, AD7384 - 4 channel pseudo-differential ADCs: AD7383-4, AD7384-4 adi,adis16475 - Support ADS16501 variant - ID and some different scale factors from parts already supported. - Driver refactoring then enables support for 6 more IMUs: - ADIS16575-[2,3] - ADIS16576-[2,3] - ADIS16577-[2,3] adi,adsi16480 - Driver refactoring and feature additions leading to support for 6 more IMUs - with new delta angle and delta velocity feature: - ADIS16545-[1,2,3] - ADIS16547-[1,2,3] bosch,bmi160 - Support for the bmi120 IMU: ID only. Also relax ID checking to warn only on mismatch allowing use of fallback compatibles for new devices. sciosense,ens160 - New driver for this metal oxide multi-gas sensor for indoor air quality monitoring. sensortek,stk3110 - Support for stk3311a and stk3311s34 light sensor variants. Relax ID checking to warn only on a mismatch allowing use of fallback compatibles for new devices. vishay,veml6040 - New driver for this RGBW light sensor. Note that whilst the register interface is very different, the dt-binding similar enough that it is shared with the existing vishay,veml6075 binding x-powers,axp20x - Add support for axp192, very similar to another supported PMIC ADC variant but with a few more GPIO channels. Dt-binding only =============== ti,ads1015 - Add binding (no driver support yet) for ti,tla2021 New features ============ core - Variable scan type support. We have papered over this for a long time so good to finally resolve it. Some devices will change their data output format (typically resolution) dependent on settings such as oversampling. A new callback is added to enable this. First used in the ad7380 driver. - Harden the core against missing callback functions. dt-binding: - Add a single-channel property that can be used in per channel nodes instead of reg to indicate which device channel. This is important in devices with a mixture of differential and single ended channels as reg already just acted as an index for the differential channels making things inconsistent if it had more meaning for single ended channels. adi,ad7380 - Use spi_optimize_message() to reduce reading message setup overhead. - Add oversampling support using the new core functionality to allow a device support multiple scan types. invense,icm42600 - Support for low-power accelerometer modes. When a given sampling frequency is only supported at one power mode, use that. Otherwise default to low power at the cost of some noise unless overridden via a new sysfs attribute. silicon-labs,si70720 - Add control of the heater. Cleanups and minor fixes ======================== core - Cleanup use of sizeof(struct xxxx) in favor of sizeof(*variable) Makefile - Resort the iio/adc/Makefile which has drifted away from alphabetical order. gts library - Fix sorting of lists with a zero in the middle. Doesn't happen with upstream drivers, but good to harden this code. Add a related unit test. multiple drivers - Add missing MODULE_DESCRIPTION() - Drop some unused structure fields. - Drop some entirely unused structure definitions. - Stop pointless initialization of i2c_device_id::driver_data to 0 in drivers where it isn't used. - Use spi_get_device_match_data() to replace open-coded equivalent. adi,ad3552r - Fix dt gain parameter names to reflect what the driver does. Note discussion in patch to justify fixing it in the binding not the driver. - Tidy up some naming. adi,ad7192 - Use read_avail() callback to handle the low pass filter. - Add an aincom supply for pseudo differential operation. adi,ad7606 - Use iio_device_claim_direct_scoped() to simplify error paths. adi,ad7944 - Drop an unused function parameter. adi,adrf6780 - Drop unused header. adi,ad9467 - Use a DMA safe buffer for SPI transfers. - Stop using tabs to pad structure field names. It was creating a lot of noise. adi,axi-adc - Prevent races between enable and disable calls. - Ensure the DRP (dynamic reconfiguration port) is locked. Not used in most real designs, but better safe than sorry. - Limit build to COMPILE_TEST or platforms for which the IP exists. adi,axi-dac - Limit build to COMPILE_TEST or platforms for which the IP exists. ams,iaq - Use __packed instead of ___attribute__((__packed__)) bosch,bmp280 - White space cleanup. - Use BME280 prefix for registers that do not exist on the BMP280. - Add parameter names to callback function definitions. - Rename measure function to better reflect what it does which is wait for a measurement to happen. - Drop a redundant error check. - Improve error messages - Make error checks consistent as if (ret) - Use unsigned types for inherently unsigned data. - Refactor reading functions to not rely on a hidden t_fine variable. - Make use of cleanup.h freescale,mma7660 - Add mount matrix support. invense,icm42600 - Enable the regmap cache to reduce bus accesses. amlogic,meson-saradc - Add dt-binding support for power-domains. ti,adc161s626 - Use iio_device_claim_direct_scoped() to simplify error handling. * tag 'iio-for-6.11a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (107 commits) iio: imu: inv_icm42600: add support of accel low-power mode iio: document inv_icm42600 driver private sysfs attributes MAINTAINERS: Add ScioSense ENS160 iio: chemical: ens160: add power management support iio: chemical: ens160: add triggered buffer support iio: chemical: add driver for ENS160 sensor dt-bindings: iio: chemical: add ENS160 sensor dt-bindings: vendor-prefixes: add ScioSense iio: temperature: mcp9600: add threshold events support dt-bindings: iio: light: add VEML6040 RGBW-LS iio: light: driver for Vishay VEML6040 dt-bindings: iio: adc: amlogic,meson-saradc: add optional power-domains iio: dac: adi-axi-dac: add platform dependencies iio: adc: adi-axi-adc: add platform dependencies iio: imu: inv_icm42600: add register caching in the regmap iio: adc: mcp3564: drop redundant open-coded spi_get_device_match_data() iio: dac: max5522: simplify with spi_get_device_match_data() iio: addac: ad74413r: simplify with spi_get_device_match_data() iio: adc: ti-tsc2046: simplify with spi_get_device_match_data() iio: adc: ti-ads131e08: simplify with spi_get_device_match_data() ...
Diffstat (limited to 'drivers/iio/dac/ad3552r.c')
-rw-r--r--drivers/iio/dac/ad3552r.c140
1 files changed, 95 insertions, 45 deletions
diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c
index 8aa942896b5b..ddc6c262f801 100644
--- a/drivers/iio/dac/ad3552r.c
+++ b/drivers/iio/dac/ad3552r.c
@@ -117,7 +117,7 @@
#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3)
/* Useful defines */
-#define AD3552R_NUM_CH 2
+#define AD3552R_MAX_CH 2
#define AD3552R_MASK_CH(ch) BIT(ch)
#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
#define AD3552R_MAX_REG_SIZE 3
@@ -139,8 +139,10 @@ enum ad3552r_ch_vref_select {
AD3552R_EXTERNAL_VREF_PIN_INPUT
};
-enum ad3542r_id {
+enum ad3552r_id {
+ AD3541R_ID = 0x400b,
AD3542R_ID = 0x4009,
+ AD3551R_ID = 0x400a,
AD3552R_ID = 0x4008,
};
@@ -261,17 +263,26 @@ struct ad3552r_ch_data {
bool range_override;
};
+struct ad3552r_model_data {
+ const char *model_name;
+ enum ad3552r_id chip_id;
+ unsigned int num_hw_channels;
+ const s32 (*ranges_table)[2];
+ int num_ranges;
+ bool requires_output_range;
+};
+
struct ad3552r_desc {
+ const struct ad3552r_model_data *model_data;
/* Used to look the spi bus for atomic operations where needed */
struct mutex lock;
struct gpio_desc *gpio_reset;
struct gpio_desc *gpio_ldac;
struct spi_device *spi;
- struct ad3552r_ch_data ch_data[AD3552R_NUM_CH];
- struct iio_chan_spec channels[AD3552R_NUM_CH + 1];
+ struct ad3552r_ch_data ch_data[AD3552R_MAX_CH];
+ struct iio_chan_spec channels[AD3552R_MAX_CH + 1];
unsigned long enabled_ch;
unsigned int num_ch;
- enum ad3542r_id chip_id;
};
static const u16 addr_mask_map[][2] = {
@@ -528,7 +539,7 @@ static int32_t ad3552r_trigger_hw_ldac(struct gpio_desc *ldac)
static int ad3552r_write_all_channels(struct ad3552r_desc *dac, u8 *data)
{
int err, len;
- u8 addr, buff[AD3552R_NUM_CH * AD3552R_MAX_REG_SIZE + 1];
+ u8 addr, buff[AD3552R_MAX_CH * AD3552R_MAX_REG_SIZE + 1];
addr = AD3552R_REG_ADDR_CH_INPUT_24B(1);
/* CH1 */
@@ -586,7 +597,7 @@ static irqreturn_t ad3552r_trigger_handler(int irq, void *p)
struct iio_buffer *buf = indio_dev->buffer;
struct ad3552r_desc *dac = iio_priv(indio_dev);
/* Maximum size of a scan */
- u8 buff[AD3552R_NUM_CH * AD3552R_MAX_REG_SIZE];
+ u8 buff[AD3552R_MAX_CH * AD3552R_MAX_REG_SIZE];
int err;
memset(buff, 0, sizeof(buff));
@@ -745,13 +756,8 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
} else {
/* Normal range */
idx = dac->ch_data[ch].range;
- if (dac->chip_id == AD3542R_ID) {
- v_min = ad3542r_ch_ranges[idx][0];
- v_max = ad3542r_ch_ranges[idx][1];
- } else {
- v_min = ad3552r_ch_ranges[idx][0];
- v_max = ad3552r_ch_ranges[idx][1];
- }
+ v_min = dac->model_data->ranges_table[idx][0];
+ v_max = dac->model_data->ranges_table[idx][1];
}
/*
@@ -775,22 +781,14 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
dac->ch_data[ch].offset_dec = div_s64(tmp, span);
}
-static int ad3552r_find_range(u16 id, s32 *vals)
+static int ad3552r_find_range(const struct ad3552r_model_data *model_data,
+ s32 *vals)
{
- int i, len;
- const s32 (*ranges)[2];
+ int i;
- if (id == AD3542R_ID) {
- len = ARRAY_SIZE(ad3542r_ch_ranges);
- ranges = ad3542r_ch_ranges;
- } else {
- len = ARRAY_SIZE(ad3552r_ch_ranges);
- ranges = ad3552r_ch_ranges;
- }
-
- for (i = 0; i < len; i++)
- if (vals[0] == ranges[i][0] * 1000 &&
- vals[1] == ranges[i][1] * 1000)
+ for (i = 0; i < model_data->num_ranges; i++)
+ if (vals[0] == model_data->ranges_table[i][0] * 1000 &&
+ vals[1] == model_data->ranges_table[i][1] * 1000)
return i;
return -EINVAL;
@@ -940,10 +938,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
if (err)
return dev_err_probe(dev, err,
"mandatory reg property missing\n");
- if (ch >= AD3552R_NUM_CH)
+ if (ch >= dac->model_data->num_hw_channels)
return dev_err_probe(dev, -EINVAL,
"reg must be less than %d\n",
- AD3552R_NUM_CH);
+ dac->model_data->num_hw_channels);
if (fwnode_property_present(child, "adi,output-range-microvolt")) {
err = fwnode_property_read_u32_array(child,
@@ -954,7 +952,7 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
return dev_err_probe(dev, err,
"adi,output-range-microvolt property could not be parsed\n");
- err = ad3552r_find_range(dac->chip_id, vals);
+ err = ad3552r_find_range(dac->model_data, vals);
if (err < 0)
return dev_err_probe(dev, err,
"Invalid adi,output-range-microvolt value\n");
@@ -967,9 +965,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
return err;
dac->ch_data[ch].range = val;
- } else if (dac->chip_id == AD3542R_ID) {
+ } else if (dac->model_data->requires_output_range) {
return dev_err_probe(dev, -EINVAL,
- "adi,output-range-microvolt is required for ad3542r\n");
+ "adi,output-range-microvolt is required for %s\n",
+ dac->model_data->model_name);
} else {
err = ad3552r_configure_custom_gain(dac, child, ch);
if (err)
@@ -989,7 +988,8 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
}
/* Disable unused channels */
- for_each_clear_bit(ch, &dac->enabled_ch, AD3552R_NUM_CH) {
+ for_each_clear_bit(ch, &dac->enabled_ch,
+ dac->model_data->num_hw_channels) {
err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN,
ch, 1);
if (err)
@@ -1032,7 +1032,7 @@ static int ad3552r_init(struct ad3552r_desc *dac)
}
id |= val << 8;
- if (id != dac->chip_id) {
+ if (id != dac->model_data->chip_id) {
dev_err(&dac->spi->dev, "Product id not matching\n");
return -ENODEV;
}
@@ -1042,7 +1042,6 @@ static int ad3552r_init(struct ad3552r_desc *dac)
static int ad3552r_probe(struct spi_device *spi)
{
- const struct spi_device_id *id = spi_get_device_id(spi);
struct ad3552r_desc *dac;
struct iio_dev *indio_dev;
int err;
@@ -1053,7 +1052,9 @@ static int ad3552r_probe(struct spi_device *spi)
dac = iio_priv(indio_dev);
dac->spi = spi;
- dac->chip_id = id->driver_data;
+ dac->model_data = spi_get_device_match_data(spi);
+ if (!dac->model_data)
+ return -EINVAL;
mutex_init(&dac->lock);
@@ -1062,10 +1063,7 @@ static int ad3552r_probe(struct spi_device *spi)
return err;
/* Config triggered buffer device */
- if (dac->chip_id == AD3552R_ID)
- indio_dev->name = "ad3552r";
- else
- indio_dev->name = "ad3542r";
+ indio_dev->name = dac->model_data->model_name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &ad3552r_iio_info;
indio_dev->num_channels = dac->num_ch;
@@ -1083,16 +1081,68 @@ static int ad3552r_probe(struct spi_device *spi)
return devm_iio_device_register(&spi->dev, indio_dev);
}
+static const struct ad3552r_model_data ad3541r_model_data = {
+ .model_name = "ad3541r",
+ .chip_id = AD3541R_ID,
+ .num_hw_channels = 1,
+ .ranges_table = ad3542r_ch_ranges,
+ .num_ranges = ARRAY_SIZE(ad3542r_ch_ranges),
+ .requires_output_range = true,
+};
+
+static const struct ad3552r_model_data ad3542r_model_data = {
+ .model_name = "ad3542r",
+ .chip_id = AD3542R_ID,
+ .num_hw_channels = 2,
+ .ranges_table = ad3542r_ch_ranges,
+ .num_ranges = ARRAY_SIZE(ad3542r_ch_ranges),
+ .requires_output_range = true,
+};
+
+static const struct ad3552r_model_data ad3551r_model_data = {
+ .model_name = "ad3551r",
+ .chip_id = AD3551R_ID,
+ .num_hw_channels = 1,
+ .ranges_table = ad3552r_ch_ranges,
+ .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges),
+ .requires_output_range = false,
+};
+
+static const struct ad3552r_model_data ad3552r_model_data = {
+ .model_name = "ad3552r",
+ .chip_id = AD3552R_ID,
+ .num_hw_channels = 2,
+ .ranges_table = ad3552r_ch_ranges,
+ .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges),
+ .requires_output_range = false,
+};
+
static const struct spi_device_id ad3552r_id[] = {
- { "ad3542r", AD3542R_ID },
- { "ad3552r", AD3552R_ID },
+ {
+ .name = "ad3541r",
+ .driver_data = (kernel_ulong_t)&ad3541r_model_data
+ },
+ {
+ .name = "ad3542r",
+ .driver_data = (kernel_ulong_t)&ad3542r_model_data
+ },
+ {
+ .name = "ad3551r",
+ .driver_data = (kernel_ulong_t)&ad3551r_model_data
+ },
+ {
+ .name = "ad3552r",
+ .driver_data = (kernel_ulong_t)&ad3552r_model_data
+ },
{ }
};
MODULE_DEVICE_TABLE(spi, ad3552r_id);
static const struct of_device_id ad3552r_of_match[] = {
- { .compatible = "adi,ad3542r"},
- { .compatible = "adi,ad3552r"},
+ { .compatible = "adi,ad3541r", .data = &ad3541r_model_data },
+ { .compatible = "adi,ad3542r", .data = &ad3542r_model_data },
+ { .compatible = "adi,ad3551r", .data = &ad3551r_model_data },
+ { .compatible = "adi,ad3552r", .data = &ad3552r_model_data },
{ }
};
MODULE_DEVICE_TABLE(of, ad3552r_of_match);