in adc/rockchip_saradc.c [317:482]
static int rockchip_saradc_probe(struct platform_device *pdev)
{
struct rockchip_saradc *info = NULL;
struct device_node *np = pdev->dev.of_node;
struct iio_dev *indio_dev = NULL;
const struct of_device_id *match;
int ret;
int irq;
if (!np)
return -ENODEV;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
if (!indio_dev) {
dev_err(&pdev->dev, "failed allocating iio device\n");
return -ENOMEM;
}
info = iio_priv(indio_dev);
match = of_match_device(rockchip_saradc_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "failed to match device\n");
return -ENODEV;
}
info->data = match->data;
/* Sanity check for possible later IP variants with more channels */
if (info->data->num_channels > SARADC_MAX_CHANNELS) {
dev_err(&pdev->dev, "max channels exceeded");
return -EINVAL;
}
info->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(info->regs))
return PTR_ERR(info->regs);
/*
* The reset should be an optional property, as it should work
* with old devicetrees as well
*/
info->reset = devm_reset_control_get_exclusive(&pdev->dev,
"saradc-apb");
if (IS_ERR(info->reset)) {
ret = PTR_ERR(info->reset);
if (ret != -ENOENT)
return dev_err_probe(&pdev->dev, ret,
"failed to get saradc-apb\n");
dev_dbg(&pdev->dev, "no reset control found\n");
info->reset = NULL;
}
init_completion(&info->completion);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return dev_err_probe(&pdev->dev, irq, "failed to get irq\n");
ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,
0, dev_name(&pdev->dev), info);
if (ret < 0) {
dev_err(&pdev->dev, "failed requesting irq %d\n", irq);
return ret;
}
info->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
if (IS_ERR(info->pclk))
return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk),
"failed to get pclk\n");
info->clk = devm_clk_get(&pdev->dev, "saradc");
if (IS_ERR(info->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(info->clk),
"failed to get adc clock\n");
info->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(info->vref))
return dev_err_probe(&pdev->dev, PTR_ERR(info->vref),
"failed to get regulator\n");
if (info->reset)
rockchip_saradc_reset_controller(info->reset);
/*
* Use a default value for the converter clock.
* This may become user-configurable in the future.
*/
ret = clk_set_rate(info->clk, info->data->clk_rate);
if (ret < 0) {
dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret);
return ret;
}
ret = regulator_enable(info->vref);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable vref regulator\n");
return ret;
}
ret = devm_add_action_or_reset(&pdev->dev,
rockchip_saradc_regulator_disable, info);
if (ret) {
dev_err(&pdev->dev, "failed to register devm action, %d\n",
ret);
return ret;
}
ret = regulator_get_voltage(info->vref);
if (ret < 0)
return ret;
info->uv_vref = ret;
ret = clk_prepare_enable(info->pclk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable pclk\n");
return ret;
}
ret = devm_add_action_or_reset(&pdev->dev,
rockchip_saradc_pclk_disable, info);
if (ret) {
dev_err(&pdev->dev, "failed to register devm action, %d\n",
ret);
return ret;
}
ret = clk_prepare_enable(info->clk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable converter clock\n");
return ret;
}
ret = devm_add_action_or_reset(&pdev->dev,
rockchip_saradc_clk_disable, info);
if (ret) {
dev_err(&pdev->dev, "failed to register devm action, %d\n",
ret);
return ret;
}
platform_set_drvdata(pdev, indio_dev);
indio_dev->name = dev_name(&pdev->dev);
indio_dev->info = &rockchip_saradc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = info->data->channels;
indio_dev->num_channels = info->data->num_channels;
ret = devm_iio_triggered_buffer_setup(&indio_dev->dev, indio_dev, NULL,
rockchip_saradc_trigger_handler,
NULL);
if (ret)
return ret;
info->nb.notifier_call = rockchip_saradc_volt_notify;
ret = regulator_register_notifier(info->vref, &info->nb);
if (ret)
return ret;
ret = devm_add_action_or_reset(&pdev->dev,
rockchip_saradc_regulator_unreg_notifier,
info);
if (ret)
return ret;
return devm_iio_device_register(&pdev->dev, indio_dev);
}