1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Helpers for parsing common ADC information from a firmware node. 4 * 5 * Copyright (c) 2025 Matti Vaittinen <mazziesaccount@gmail.com> 6 */ 7 8 #include <linux/device.h> 9 #include <linux/errno.h> 10 #include <linux/export.h> 11 #include <linux/module.h> 12 #include <linux/property.h> 13 #include <linux/types.h> 14 15 #include <linux/iio/adc-helpers.h> 16 #include <linux/iio/iio.h> 17 18 /** 19 * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC 20 * 21 * Scan the device node for single-ended ADC channel information. Channel ID is 22 * expected to be found from the "reg" property. Allocate and populate the 23 * iio_chan_spec structure corresponding to channels that are found. The memory 24 * for iio_chan_spec structure will be freed upon device detach. 25 * 26 * @dev: Pointer to the ADC device. 27 * @template: Template iio_chan_spec from which the fields of all 28 * found and allocated channels are initialized. 29 * @max_chan_id: Maximum value of a channel ID. Use negative value if no 30 * checking is required. 31 * @cs: Location where pointer to allocated iio_chan_spec 32 * should be stored. 33 * 34 * Return: Number of found channels on success. Negative value to indicate 35 * failure. Specifically, -ENOENT if no channel nodes were found. 36 */ 37 int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev, 38 const struct iio_chan_spec *template, 39 int max_chan_id, 40 struct iio_chan_spec **cs) 41 { 42 struct iio_chan_spec *chan_array, *chan; 43 int num_chan, ret; 44 45 num_chan = iio_adc_device_num_channels(dev); 46 if (num_chan < 0) 47 return num_chan; 48 49 if (!num_chan) 50 return -ENOENT; 51 52 chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array), 53 GFP_KERNEL); 54 if (!chan_array) 55 return -ENOMEM; 56 57 chan = &chan_array[0]; 58 59 device_for_each_named_child_node_scoped(dev, child, "channel") { 60 u32 ch; 61 62 ret = fwnode_property_read_u32(child, "reg", &ch); 63 if (ret) 64 return ret; 65 66 if (max_chan_id >= 0 && ch > max_chan_id) 67 return -ERANGE; 68 69 *chan = *template; 70 chan->channel = ch; 71 chan++; 72 } 73 74 *cs = chan_array; 75 76 return num_chan; 77 } 78 EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER"); 79 80 MODULE_LICENSE("GPL"); 81 MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>"); 82 MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers"); 83