Commit 2334d5e0 authored by Angelo Dureghello's avatar Angelo Dureghello Committed by Jonathan Cameron

iio: dac: ad3552r: add model data structure

Add a "model data" structure to keep useful hardware-related
information as from datasheet, avoiding id-based conditional
choices later on.

Removed id-based checks and filled model-specific structures
with device specific features, In particular, num_hw_channels
is introduced to keep the number of hardware implemented
channels, since 1-channel versions of the DACs are added
in this same patchset.
Signed-off-by: default avatarAngelo Dureghello <adureghello@baylibre.com>
Reviewed-by: default avatarNuno Sa <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20240522150141.1776196-4-adureghello@baylibre.orgSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 80ea2007
...@@ -261,7 +261,17 @@ struct ad3552r_ch_data { ...@@ -261,7 +261,17 @@ struct ad3552r_ch_data {
bool range_override; bool range_override;
}; };
struct ad3552r_model_data {
const char *model_name;
enum ad3542r_id chip_id;
unsigned int num_hw_channels;
const s32 (*ranges_table)[2];
int num_ranges;
bool requires_output_range;
};
struct ad3552r_desc { struct ad3552r_desc {
const struct ad3552r_model_data *model_data;
/* Used to look the spi bus for atomic operations where needed */ /* Used to look the spi bus for atomic operations where needed */
struct mutex lock; struct mutex lock;
struct gpio_desc *gpio_reset; struct gpio_desc *gpio_reset;
...@@ -271,7 +281,6 @@ struct ad3552r_desc { ...@@ -271,7 +281,6 @@ struct ad3552r_desc {
struct iio_chan_spec channels[AD3552R_NUM_CH + 1]; struct iio_chan_spec channels[AD3552R_NUM_CH + 1];
unsigned long enabled_ch; unsigned long enabled_ch;
unsigned int num_ch; unsigned int num_ch;
enum ad3542r_id chip_id;
}; };
static const u16 addr_mask_map[][2] = { static const u16 addr_mask_map[][2] = {
...@@ -745,13 +754,8 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch) ...@@ -745,13 +754,8 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
} else { } else {
/* Normal range */ /* Normal range */
idx = dac->ch_data[ch].range; idx = dac->ch_data[ch].range;
if (dac->chip_id == AD3542R_ID) { v_min = dac->model_data->ranges_table[idx][0];
v_min = ad3542r_ch_ranges[idx][0]; v_max = dac->model_data->ranges_table[idx][1];
v_max = ad3542r_ch_ranges[idx][1];
} else {
v_min = ad3552r_ch_ranges[idx][0];
v_max = ad3552r_ch_ranges[idx][1];
}
} }
/* /*
...@@ -775,22 +779,14 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch) ...@@ -775,22 +779,14 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
dac->ch_data[ch].offset_dec = div_s64(tmp, span); 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; int i;
const s32 (*ranges)[2];
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++) for (i = 0; i < model_data->num_ranges; i++)
if (vals[0] == ranges[i][0] * 1000 && if (vals[0] == model_data->ranges_table[i][0] * 1000 &&
vals[1] == ranges[i][1] * 1000) vals[1] == model_data->ranges_table[i][1] * 1000)
return i; return i;
return -EINVAL; return -EINVAL;
...@@ -940,10 +936,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) ...@@ -940,10 +936,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
if (err) if (err)
return dev_err_probe(dev, err, return dev_err_probe(dev, err,
"mandatory reg property missing\n"); "mandatory reg property missing\n");
if (ch >= AD3552R_NUM_CH) if (ch >= dac->model_data->num_hw_channels)
return dev_err_probe(dev, -EINVAL, return dev_err_probe(dev, -EINVAL,
"reg must be less than %d\n", "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")) { if (fwnode_property_present(child, "adi,output-range-microvolt")) {
err = fwnode_property_read_u32_array(child, err = fwnode_property_read_u32_array(child,
...@@ -954,7 +950,7 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) ...@@ -954,7 +950,7 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
return dev_err_probe(dev, err, return dev_err_probe(dev, err,
"adi,output-range-microvolt property could not be parsed\n"); "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) if (err < 0)
return dev_err_probe(dev, err, return dev_err_probe(dev, err,
"Invalid adi,output-range-microvolt value\n"); "Invalid adi,output-range-microvolt value\n");
...@@ -967,9 +963,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) ...@@ -967,9 +963,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
return err; return err;
dac->ch_data[ch].range = val; 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, 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 { } else {
err = ad3552r_configure_custom_gain(dac, child, ch); err = ad3552r_configure_custom_gain(dac, child, ch);
if (err) if (err)
...@@ -989,7 +986,8 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) ...@@ -989,7 +986,8 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
} }
/* Disable unused channels */ /* 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, err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN,
ch, 1); ch, 1);
if (err) if (err)
...@@ -1032,7 +1030,7 @@ static int ad3552r_init(struct ad3552r_desc *dac) ...@@ -1032,7 +1030,7 @@ static int ad3552r_init(struct ad3552r_desc *dac)
} }
id |= val << 8; 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"); dev_err(&dac->spi->dev, "Product id not matching\n");
return -ENODEV; return -ENODEV;
} }
...@@ -1042,7 +1040,6 @@ static int ad3552r_init(struct ad3552r_desc *dac) ...@@ -1042,7 +1040,6 @@ static int ad3552r_init(struct ad3552r_desc *dac)
static int ad3552r_probe(struct spi_device *spi) static int ad3552r_probe(struct spi_device *spi)
{ {
const struct spi_device_id *id = spi_get_device_id(spi);
struct ad3552r_desc *dac; struct ad3552r_desc *dac;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
int err; int err;
...@@ -1053,7 +1050,9 @@ static int ad3552r_probe(struct spi_device *spi) ...@@ -1053,7 +1050,9 @@ static int ad3552r_probe(struct spi_device *spi)
dac = iio_priv(indio_dev); dac = iio_priv(indio_dev);
dac->spi = spi; 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); mutex_init(&dac->lock);
...@@ -1062,10 +1061,7 @@ static int ad3552r_probe(struct spi_device *spi) ...@@ -1062,10 +1061,7 @@ static int ad3552r_probe(struct spi_device *spi)
return err; return err;
/* Config triggered buffer device */ /* Config triggered buffer device */
if (dac->chip_id == AD3552R_ID) indio_dev->name = dac->model_data->model_name;
indio_dev->name = "ad3552r";
else
indio_dev->name = "ad3542r";
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->info = &ad3552r_iio_info; indio_dev->info = &ad3552r_iio_info;
indio_dev->num_channels = dac->num_ch; indio_dev->num_channels = dac->num_ch;
...@@ -1083,16 +1079,40 @@ static int ad3552r_probe(struct spi_device *spi) ...@@ -1083,16 +1079,40 @@ static int ad3552r_probe(struct spi_device *spi)
return devm_iio_device_register(&spi->dev, indio_dev); return devm_iio_device_register(&spi->dev, indio_dev);
} }
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 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[] = { static const struct spi_device_id ad3552r_id[] = {
{ "ad3542r", AD3542R_ID }, {
{ "ad3552r", AD3552R_ID }, .name = "ad3542r",
.driver_data = (kernel_ulong_t)&ad3542r_model_data
},
{
.name = "ad3552r",
.driver_data = (kernel_ulong_t)&ad3552r_model_data
},
{ } { }
}; };
MODULE_DEVICE_TABLE(spi, ad3552r_id); MODULE_DEVICE_TABLE(spi, ad3552r_id);
static const struct of_device_id ad3552r_of_match[] = { static const struct of_device_id ad3552r_of_match[] = {
{ .compatible = "adi,ad3542r"}, { .compatible = "adi,ad3542r", .data = &ad3542r_model_data },
{ .compatible = "adi,ad3552r"}, { .compatible = "adi,ad3552r", .data = &ad3552r_model_data },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, ad3552r_of_match); MODULE_DEVICE_TABLE(of, ad3552r_of_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment