static int meson_sar_adc_probe()

in adc/meson_saradc.c [1185:1314]


static int meson_sar_adc_probe(struct platform_device *pdev)
{
	const struct meson_sar_adc_data *match_data;
	struct meson_sar_adc_priv *priv;
	struct iio_dev *indio_dev;
	void __iomem *base;
	int irq, ret;

	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
	if (!indio_dev) {
		dev_err(&pdev->dev, "failed allocating iio device\n");
		return -ENOMEM;
	}

	priv = iio_priv(indio_dev);
	init_completion(&priv->done);

	match_data = of_device_get_match_data(&pdev->dev);
	if (!match_data) {
		dev_err(&pdev->dev, "failed to get match data\n");
		return -ENODEV;
	}

	priv->param = match_data->param;

	indio_dev->name = match_data->name;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->info = &meson_sar_adc_iio_info;

	base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(base))
		return PTR_ERR(base);

	priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
					     priv->param->regmap_config);
	if (IS_ERR(priv->regmap))
		return PTR_ERR(priv->regmap);

	irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
	if (!irq)
		return -EINVAL;

	ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
			       dev_name(&pdev->dev), indio_dev);
	if (ret)
		return ret;

	priv->clkin = devm_clk_get(&pdev->dev, "clkin");
	if (IS_ERR(priv->clkin))
		return dev_err_probe(&pdev->dev, PTR_ERR(priv->clkin),
				     "failed to get clkin\n");

	priv->core_clk = devm_clk_get(&pdev->dev, "core");
	if (IS_ERR(priv->core_clk))
		return dev_err_probe(&pdev->dev, PTR_ERR(priv->core_clk),
				     "failed to get core clk\n");

	priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk");
	if (IS_ERR(priv->adc_clk)) {
		if (PTR_ERR(priv->adc_clk) == -ENOENT)
			priv->adc_clk = NULL;
		else
			return dev_err_probe(&pdev->dev, PTR_ERR(priv->adc_clk),
					     "failed to get adc clk\n");
	}

	priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel");
	if (IS_ERR(priv->adc_sel_clk)) {
		if (PTR_ERR(priv->adc_sel_clk) == -ENOENT)
			priv->adc_sel_clk = NULL;
		else
			return dev_err_probe(&pdev->dev, PTR_ERR(priv->adc_sel_clk),
					     "failed to get adc_sel clk\n");
	}

	/* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */
	if (!priv->adc_clk) {
		ret = meson_sar_adc_clk_init(indio_dev, base);
		if (ret)
			return ret;
	}

	priv->vref = devm_regulator_get(&pdev->dev, "vref");
	if (IS_ERR(priv->vref))
		return dev_err_probe(&pdev->dev, PTR_ERR(priv->vref),
				     "failed to get vref regulator\n");

	priv->calibscale = MILLION;

	if (priv->param->temperature_trimming_bits) {
		ret = meson_sar_adc_temp_sensor_init(indio_dev);
		if (ret)
			return ret;
	}

	if (priv->temperature_sensor_calibrated) {
		indio_dev->channels = meson_sar_adc_and_temp_iio_channels;
		indio_dev->num_channels =
			ARRAY_SIZE(meson_sar_adc_and_temp_iio_channels);
	} else {
		indio_dev->channels = meson_sar_adc_iio_channels;
		indio_dev->num_channels =
			ARRAY_SIZE(meson_sar_adc_iio_channels);
	}

	ret = meson_sar_adc_init(indio_dev);
	if (ret)
		goto err;

	ret = meson_sar_adc_hw_enable(indio_dev);
	if (ret)
		goto err;

	ret = meson_sar_adc_calib(indio_dev);
	if (ret)
		dev_warn(&pdev->dev, "calibration failed\n");

	platform_set_drvdata(pdev, indio_dev);

	ret = iio_device_register(indio_dev);
	if (ret)
		goto err_hw;

	return 0;

err_hw:
	meson_sar_adc_hw_disable(indio_dev);
err:
	return ret;
}