@@ -15,6 +15,7 @@
#include <linux/property.h>
#include <linux/reset.h>
+#include <linux/iio/adc-helpers.h>
#include <linux/iio/iio.h>
#define SUN20I_GPADC_DRIVER_NAME "sun20i-gpadc"
@@ -149,37 +150,32 @@ static void sun20i_gpadc_reset_assert(void *data)
reset_control_assert(rst);
}
+static const struct iio_chan_spec sun20i_gpadc_chan_template = {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+};
+
+static const struct iio_adc_props sun20i_gpadc_chan_props = {
+ .required = IIO_ADC_CHAN_PROP_TYPE_REG,
+};
+
static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
struct device *dev)
{
- unsigned int channel;
- int num_channels, i, ret;
+ int num_channels;
struct iio_chan_spec *channels;
- num_channels = device_get_child_node_count(dev);
+ num_channels = devm_iio_adc_device_alloc_chaninfo(dev,
+ &sun20i_gpadc_chan_template, &channels,
+ &sun20i_gpadc_chan_props);
+ if (num_channels < 0)
+ return num_channels;
+
if (num_channels == 0)
return dev_err_probe(dev, -ENODEV, "no channel children\n");
- channels = devm_kcalloc(dev, num_channels, sizeof(*channels),
- GFP_KERNEL);
- if (!channels)
- return -ENOMEM;
-
- i = 0;
- device_for_each_child_node_scoped(dev, node) {
- ret = fwnode_property_read_u32(node, "reg", &channel);
- if (ret)
- return dev_err_probe(dev, ret, "invalid channel number\n");
-
- channels[i].type = IIO_VOLTAGE;
- channels[i].indexed = 1;
- channels[i].channel = channel;
- channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
- channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
-
- i++;
- }
-
indio_dev->channels = channels;
indio_dev->num_channels = num_channels;
The new devm_iio_adc_device_alloc_chaninfo() -helper is intended to help drivers avoid open-coding the for_each_node -loop for getting the channel IDs. The helper provides standard way to detect the ADC channel nodes (by the node name), and a standard way to convert the "reg", "diff-channels", "single-channel" and the "common-mode-channel" to channel identification numbers used in the struct iio_chan_spec. Furthermore, the helper checks the ID is in range of 0 ... num-channels. The original driver treated all found child nodes as channel nodes. The new helper requires channel nodes to be named channel[@N]. This should help avoid problems with devices which may contain also other but ADC child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible string didn't reveal any in-tree .dts with channel nodes named othervice. Also, same grep shows all the in-tree .dts seem to have channel IDs between 0..num of channels. Use the new helper. Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com> --- Revision history: v2 => v3: - New patch I picked the sun20i-gpadc in this series because it has a straightforward approach for populating the struct iio_chan_spec. Everything else except the .channel can use 'template'-data. This makes the sun20i-gpadc well suited to be an example user of this new helper. I hope this patch helps to evaluate whether these helpers are worth the hassle. The change is compile tested only!! Testing before applying is highly appreciated (as always!). Also, even though I tried to audit the dts files for the reg-properties in the channel nodes, use of references didn't make it easy. I can't guarantee I didn't miss anything. --- drivers/iio/adc/sun20i-gpadc-iio.c | 42 ++++++++++++++---------------- 1 file changed, 19 insertions(+), 23 deletions(-)