static int xadc_parse_dt()

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", &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;
}