in adc/at91-sama5d2_adc.c [1921:2087]
static int at91_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct at91_adc_state *st;
struct resource *res;
int ret, i;
u32 edge_type = IRQ_TYPE_NONE;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
st->indio_dev = indio_dev;
st->soc_info.platform = of_device_get_match_data(&pdev->dev);
indio_dev->name = dev_name(&pdev->dev);
indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
indio_dev->info = &at91_adc_info;
indio_dev->channels = *st->soc_info.platform->adc_channels;
indio_dev->num_channels = st->soc_info.platform->max_channels;
bitmap_set(&st->touch_st.channels_bitmask,
st->soc_info.platform->touch_chan_x, 1);
bitmap_set(&st->touch_st.channels_bitmask,
st->soc_info.platform->touch_chan_y, 1);
bitmap_set(&st->touch_st.channels_bitmask,
st->soc_info.platform->touch_chan_p, 1);
st->oversampling_ratio = AT91_OSR_1SAMPLES;
ret = of_property_read_u32(pdev->dev.of_node,
"atmel,min-sample-rate-hz",
&st->soc_info.min_sample_rate);
if (ret) {
dev_err(&pdev->dev,
"invalid or missing value for atmel,min-sample-rate-hz\n");
return ret;
}
ret = of_property_read_u32(pdev->dev.of_node,
"atmel,max-sample-rate-hz",
&st->soc_info.max_sample_rate);
if (ret) {
dev_err(&pdev->dev,
"invalid or missing value for atmel,max-sample-rate-hz\n");
return ret;
}
ret = of_property_read_u32(pdev->dev.of_node, "atmel,startup-time-ms",
&st->soc_info.startup_time);
if (ret) {
dev_err(&pdev->dev,
"invalid or missing value for atmel,startup-time-ms\n");
return ret;
}
ret = of_property_read_u32(pdev->dev.of_node,
"atmel,trigger-edge-type", &edge_type);
if (ret) {
dev_dbg(&pdev->dev,
"atmel,trigger-edge-type not specified, only software trigger available\n");
}
st->selected_trig = NULL;
/* find the right trigger, or no trigger at all */
for (i = 0; i < st->soc_info.platform->hw_trig_cnt + 1; i++)
if (at91_adc_trigger_list[i].edge_type == edge_type) {
st->selected_trig = &at91_adc_trigger_list[i];
break;
}
if (!st->selected_trig) {
dev_err(&pdev->dev, "invalid external trigger edge value\n");
return -EINVAL;
}
init_waitqueue_head(&st->wq_data_available);
mutex_init(&st->lock);
INIT_WORK(&st->touch_st.workq, at91_adc_workq_handler);
st->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(st->base))
return PTR_ERR(st->base);
/* if we plan to use DMA, we need the physical address of the regs */
st->dma_st.phys_addr = res->start;
st->irq = platform_get_irq(pdev, 0);
if (st->irq <= 0) {
if (!st->irq)
st->irq = -ENXIO;
return st->irq;
}
st->per_clk = devm_clk_get(&pdev->dev, "adc_clk");
if (IS_ERR(st->per_clk))
return PTR_ERR(st->per_clk);
st->reg = devm_regulator_get(&pdev->dev, "vddana");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
st->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(st->vref))
return PTR_ERR(st->vref);
ret = devm_request_irq(&pdev->dev, st->irq, at91_adc_interrupt, 0,
pdev->dev.driver->name, indio_dev);
if (ret)
return ret;
ret = regulator_enable(st->reg);
if (ret)
return ret;
ret = regulator_enable(st->vref);
if (ret)
goto reg_disable;
st->vref_uv = regulator_get_voltage(st->vref);
if (st->vref_uv <= 0) {
ret = -EINVAL;
goto vref_disable;
}
ret = clk_prepare_enable(st->per_clk);
if (ret)
goto vref_disable;
at91_adc_hw_init(indio_dev);
platform_set_drvdata(pdev, indio_dev);
ret = at91_adc_buffer_and_trigger_init(&pdev->dev, indio_dev);
if (ret < 0)
goto per_clk_disable_unprepare;
if (dma_coerce_mask_and_coherent(&indio_dev->dev, DMA_BIT_MASK(32)))
dev_info(&pdev->dev, "cannot set DMA mask to 32-bit\n");
ret = iio_device_register(indio_dev);
if (ret < 0)
goto dma_disable;
if (st->selected_trig->hw_trig)
dev_info(&pdev->dev, "setting up trigger as %s\n",
st->selected_trig->name);
dev_info(&pdev->dev, "version: %x\n",
readl_relaxed(st->base + st->soc_info.platform->layout->VERSION));
return 0;
dma_disable:
at91_adc_dma_disable(st);
per_clk_disable_unprepare:
clk_disable_unprepare(st->per_clk);
vref_disable:
regulator_disable(st->vref);
reg_disable:
regulator_disable(st->reg);
return ret;
}