static int rcar_gyroadc_parse_subdevs()

in adc/rcar-gyroadc.c [314:442]


static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
{
	const struct of_device_id *of_id;
	const struct iio_chan_spec *channels;
	struct rcar_gyroadc *priv = iio_priv(indio_dev);
	struct device *dev = priv->dev;
	struct device_node *np = dev->of_node;
	struct device_node *child;
	struct regulator *vref;
	unsigned int reg;
	unsigned int adcmode = -1, childmode;
	unsigned int sample_width;
	unsigned int num_channels;
	int ret, first = 1;

	for_each_child_of_node(np, child) {
		of_id = of_match_node(rcar_gyroadc_child_match, child);
		if (!of_id) {
			dev_err(dev, "Ignoring unsupported ADC \"%pOFn\".",
				child);
			continue;
		}

		childmode = (uintptr_t)of_id->data;
		switch (childmode) {
		case RCAR_GYROADC_MODE_SELECT_1_MB88101A:
			sample_width = 12;
			channels = rcar_gyroadc_iio_channels_1;
			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_1);
			break;
		case RCAR_GYROADC_MODE_SELECT_2_ADCS7476:
			sample_width = 15;
			channels = rcar_gyroadc_iio_channels_2;
			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_2);
			break;
		case RCAR_GYROADC_MODE_SELECT_3_MAX1162:
			sample_width = 16;
			channels = rcar_gyroadc_iio_channels_3;
			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3);
			break;
		default:
			goto err_e_inval;
		}

		/*
		 * MB88101 is special in that it's only a single chip taking
		 * up all the CHS lines. Thus, the DT binding is also special
		 * and has no reg property. If we run into such ADC, handle
		 * it here.
		 */
		if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
			reg = 0;
		} else {
			ret = of_property_read_u32(child, "reg", &reg);
			if (ret) {
				dev_err(dev,
					"Failed to get child reg property of ADC \"%pOFn\".\n",
					child);
				goto err_of_node_put;
			}

			/* Channel number is too high. */
			if (reg >= num_channels) {
				dev_err(dev,
					"Only %i channels supported with %pOFn, but reg = <%i>.\n",
					num_channels, child, reg);
				goto err_e_inval;
			}
		}

		/* Child node selected different mode than the rest. */
		if (!first && (adcmode != childmode)) {
			dev_err(dev,
				"Channel %i uses different ADC mode than the rest.\n",
				reg);
			goto err_e_inval;
		}

		/* Channel is valid, grab the regulator. */
		dev->of_node = child;
		vref = devm_regulator_get(dev, "vref");
		dev->of_node = np;
		if (IS_ERR(vref)) {
			dev_dbg(dev, "Channel %i 'vref' supply not connected.\n",
				reg);
			ret = PTR_ERR(vref);
			goto err_of_node_put;
		}

		priv->vref[reg] = vref;

		if (!first)
			continue;

		/* First child node which passed sanity tests. */
		adcmode = childmode;
		first = 0;

		priv->num_channels = num_channels;
		priv->mode = childmode;
		priv->sample_width = sample_width;

		indio_dev->channels = channels;
		indio_dev->num_channels = num_channels;

		/*
		 * MB88101 is special and we only have one such device
		 * attached to the GyroADC at a time, so if we found it,
		 * we can stop parsing here.
		 */
		if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
			of_node_put(child);
			break;
		}
	}

	if (first) {
		dev_err(dev, "No valid ADC channels found, aborting.\n");
		return -EINVAL;
	}

	return 0;

err_e_inval:
	ret = -EINVAL;
err_of_node_put:
	of_node_put(child);
	return ret;
}