iio: dac: ad3552r: add model data structure
authorAngelo Dureghello <adureghello@baylibre.com>
Wed, 22 May 2024 15:01:38 +0000 (17:01 +0200)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Tue, 4 Jun 2024 18:53:06 +0000 (19:53 +0100)
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@baylibre.com>
Reviewed-by: Nuno Sa <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20240522150141.1776196-4-adureghello@baylibre.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/dac/ad3552r.c

index 8aa942896b5bc1f95b527ebbfceaa81d86411040..d637a8722f171f35e65390d49ead7bf011ff59c3 100644 (file)
@@ -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);