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 {
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 {
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;
......@@ -271,7 +281,6 @@ struct ad3552r_desc {
struct iio_chan_spec channels[AD3552R_NUM_CH + 1];
unsigned long enabled_ch;
unsigned int num_ch;
enum ad3542r_id chip_id;
};
static const u16 addr_mask_map[][2] = {
......@@ -745,13 +754,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 +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);
}
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 +936,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 +950,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 +963,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 +986,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 +1030,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 +1040,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 +1050,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 +1061,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 +1079,40 @@ static int ad3552r_probe(struct spi_device *spi)
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[] = {
{ "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);
static const struct of_device_id ad3552r_of_match[] = {
{ .compatible = "adi,ad3542r"},
{ .compatible = "adi,ad3552r"},
{ .compatible = "adi,ad3542r", .data = &ad3542r_model_data },
{ .compatible = "adi,ad3552r", .data = &ad3552r_model_data },
{ }
};
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