static int stm32_adc_probe()

in adc/stm32-adc.c [2203:2331]


static int stm32_adc_probe(struct platform_device *pdev)
{
	struct iio_dev *indio_dev;
	struct device *dev = &pdev->dev;
	irqreturn_t (*handler)(int irq, void *p) = NULL;
	struct stm32_adc *adc;
	bool timestamping = false;
	int ret;

	if (!pdev->dev.of_node)
		return -ENODEV;

	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
	if (!indio_dev)
		return -ENOMEM;

	adc = iio_priv(indio_dev);
	adc->common = dev_get_drvdata(pdev->dev.parent);
	spin_lock_init(&adc->lock);
	init_completion(&adc->completion);
	adc->cfg = (const struct stm32_adc_cfg *)
		of_match_device(dev->driver->of_match_table, dev)->data;

	indio_dev->name = dev_name(&pdev->dev);
	indio_dev->dev.of_node = pdev->dev.of_node;
	indio_dev->info = &stm32_adc_iio_info;
	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_HARDWARE_TRIGGERED;

	platform_set_drvdata(pdev, indio_dev);

	ret = of_property_read_u32(pdev->dev.of_node, "reg", &adc->offset);
	if (ret != 0) {
		dev_err(&pdev->dev, "missing reg property\n");
		return -EINVAL;
	}

	adc->irq = platform_get_irq(pdev, 0);
	if (adc->irq < 0)
		return adc->irq;

	ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr,
					stm32_adc_threaded_isr,
					0, pdev->name, indio_dev);
	if (ret) {
		dev_err(&pdev->dev, "failed to request IRQ\n");
		return ret;
	}

	adc->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(adc->clk)) {
		ret = PTR_ERR(adc->clk);
		if (ret == -ENOENT && !adc->cfg->clk_required) {
			adc->clk = NULL;
		} else {
			dev_err(&pdev->dev, "Can't get clock\n");
			return ret;
		}
	}

	ret = stm32_adc_of_get_resolution(indio_dev);
	if (ret < 0)
		return ret;

	ret = stm32_adc_dma_request(dev, indio_dev);
	if (ret < 0)
		return ret;

	if (!adc->dma_chan) {
		/* For PIO mode only, iio_pollfunc_store_time stores a timestamp
		 * in the primary trigger IRQ handler and stm32_adc_trigger_handler
		 * runs in the IRQ thread to push out buffer along with timestamp.
		 */
		handler = &stm32_adc_trigger_handler;
		timestamping = true;
	}

	ret = stm32_adc_chan_of_init(indio_dev, timestamping);
	if (ret < 0)
		goto err_dma_disable;

	ret = iio_triggered_buffer_setup(indio_dev,
					 &iio_pollfunc_store_time, handler,
					 &stm32_adc_buffer_setup_ops);
	if (ret) {
		dev_err(&pdev->dev, "buffer setup failed\n");
		goto err_dma_disable;
	}

	/* Get stm32-adc-core PM online */
	pm_runtime_get_noresume(dev);
	pm_runtime_set_active(dev);
	pm_runtime_set_autosuspend_delay(dev, STM32_ADC_HW_STOP_DELAY_MS);
	pm_runtime_use_autosuspend(dev);
	pm_runtime_enable(dev);

	ret = stm32_adc_hw_start(dev);
	if (ret)
		goto err_buffer_cleanup;

	ret = iio_device_register(indio_dev);
	if (ret) {
		dev_err(&pdev->dev, "iio dev register failed\n");
		goto err_hw_stop;
	}

	pm_runtime_mark_last_busy(dev);
	pm_runtime_put_autosuspend(dev);

	return 0;

err_hw_stop:
	stm32_adc_hw_stop(dev);

err_buffer_cleanup:
	pm_runtime_disable(dev);
	pm_runtime_set_suspended(dev);
	pm_runtime_put_noidle(dev);
	iio_triggered_buffer_cleanup(indio_dev);

err_dma_disable:
	if (adc->dma_chan) {
		dma_free_coherent(adc->dma_chan->device->dev,
				  STM32_DMA_BUFFER_SIZE,
				  adc->rx_buf, adc->rx_dma_buf);
		dma_release_channel(adc->dma_chan);
	}

	return ret;
}