in adc/xilinx-xadc-core.c [1185:1295]
static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
unsigned int *conf, int irq)
{
struct device *dev = indio_dev->dev.parent;
struct xadc *xadc = iio_priv(indio_dev);
const struct iio_chan_spec *channel_templates;
struct iio_chan_spec *channels, *chan;
struct device_node *chan_node, *child;
unsigned int max_channels;
unsigned int num_channels;
const char *external_mux;
u32 ext_mux_chan;
u32 reg;
int ret;
int i;
*conf = 0;
ret = of_property_read_string(np, "xlnx,external-mux", &external_mux);
if (ret < 0 || strcasecmp(external_mux, "none") == 0)
xadc->external_mux_mode = XADC_EXTERNAL_MUX_NONE;
else if (strcasecmp(external_mux, "single") == 0)
xadc->external_mux_mode = XADC_EXTERNAL_MUX_SINGLE;
else if (strcasecmp(external_mux, "dual") == 0)
xadc->external_mux_mode = XADC_EXTERNAL_MUX_DUAL;
else
return -EINVAL;
if (xadc->external_mux_mode != XADC_EXTERNAL_MUX_NONE) {
ret = of_property_read_u32(np, "xlnx,external-mux-channel",
&ext_mux_chan);
if (ret < 0)
return ret;
if (xadc->external_mux_mode == XADC_EXTERNAL_MUX_SINGLE) {
if (ext_mux_chan == 0)
ext_mux_chan = XADC_REG_VPVN;
else if (ext_mux_chan <= 16)
ext_mux_chan = XADC_REG_VAUX(ext_mux_chan - 1);
else
return -EINVAL;
} else {
if (ext_mux_chan > 0 && ext_mux_chan <= 8)
ext_mux_chan = XADC_REG_VAUX(ext_mux_chan - 1);
else
return -EINVAL;
}
*conf |= XADC_CONF0_MUX | XADC_CONF0_CHAN(ext_mux_chan);
}
if (xadc->ops->type == XADC_TYPE_S7) {
channel_templates = xadc_7s_channels;
max_channels = ARRAY_SIZE(xadc_7s_channels);
} else {
channel_templates = xadc_us_channels;
max_channels = ARRAY_SIZE(xadc_us_channels);
}
channels = devm_kmemdup(dev, channel_templates,
sizeof(channels[0]) * max_channels, GFP_KERNEL);
if (!channels)
return -ENOMEM;
num_channels = 9;
chan = &channels[9];
chan_node = of_get_child_by_name(np, "xlnx,channels");
if (chan_node) {
for_each_child_of_node(chan_node, child) {
if (num_channels >= max_channels) {
of_node_put(child);
break;
}
ret = of_property_read_u32(child, "reg", ®);
if (ret || reg > 16)
continue;
if (of_property_read_bool(child, "xlnx,bipolar"))
chan->scan_type.sign = 's';
if (reg == 0) {
chan->scan_index = 11;
chan->address = XADC_REG_VPVN;
} else {
chan->scan_index = 15 + reg;
chan->address = XADC_REG_VAUX(reg - 1);
}
num_channels++;
chan++;
}
}
of_node_put(chan_node);
/* No IRQ => no events */
if (irq <= 0) {
for (i = 0; i < num_channels; i++) {
channels[i].event_spec = NULL;
channels[i].num_event_specs = 0;
}
}
indio_dev->num_channels = num_channels;
indio_dev->channels = devm_krealloc(dev, channels,
sizeof(*channels) * num_channels,
GFP_KERNEL);
/* If we can't resize the channels array, just use the original */
if (!indio_dev->channels)
indio_dev->channels = channels;
return 0;
}