From: Angelo Dureghello <adureghello@xxxxxxxxxxxx> 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: Angelo Dureghello <adureghello@xxxxxxxxxxxx> --- Changes for v2: - patch added in v2 --- drivers/iio/dac/ad3552r.c | 98 +++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 39 deletions(-) diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c index a492e8f2fc0f..6a40c7eece1f 100644 --- a/drivers/iio/dac/ad3552r.c +++ b/drivers/iio/dac/ad3552r.c @@ -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; @@ -955,9 +951,9 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) dev_err(dev, "mandatory reg property missing\n"); goto put_child; } - if (ch >= AD3552R_NUM_CH) { + if (ch >= dac->model_data->num_hw_channels) { dev_err(dev, "reg must be less than %d\n", - AD3552R_NUM_CH); + dac->model_data->num_hw_channels); err = -EINVAL; goto put_child; } @@ -973,7 +969,7 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) goto put_child; } - err = ad3552r_find_range(dac->chip_id, vals); + err = ad3552r_find_range(dac->model_data, vals); if (err < 0) { dev_err(dev, "Invalid adi,output-range-microvolt value\n"); @@ -987,9 +983,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) goto put_child; dac->ch_data[ch].range = val; - } else if (dac->chip_id == AD3542R_ID) { + } else if (dac->model_data->requires_output_range) { dev_err(dev, - "adi,output-range-microvolt is required for ad3542r\n"); + "adi,output-range-microvolt is required for %s\n", + dac->model_data->model_name); err = -EINVAL; goto put_child; } else { @@ -1011,7 +1008,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) @@ -1058,7 +1056,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; } @@ -1068,7 +1066,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; @@ -1079,7 +1076,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); @@ -1088,10 +1087,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; @@ -1109,16 +1105,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); -- 2.45.0.rc1