in adc/ti-ads131e08.c [803:929]
static int ads131e08_probe(struct spi_device *spi)
{
const struct ads131e08_info *info;
struct ads131e08_state *st;
struct iio_dev *indio_dev;
unsigned long adc_clk_hz;
unsigned long adc_clk_ns;
int ret;
info = device_get_match_data(&spi->dev);
if (!info) {
dev_err(&spi->dev, "failed to get match data\n");
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev) {
dev_err(&spi->dev, "failed to allocate IIO device\n");
return -ENOMEM;
}
st = iio_priv(indio_dev);
st->info = info;
st->spi = spi;
ret = ads131e08_alloc_channels(indio_dev);
if (ret)
return ret;
indio_dev->name = st->info->name;
indio_dev->info = &ads131e08_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
init_completion(&st->completion);
if (spi->irq) {
ret = devm_request_irq(&spi->dev, spi->irq,
ads131e08_interrupt,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
spi->dev.driver->name, indio_dev);
if (ret)
return dev_err_probe(&spi->dev, ret,
"request irq failed\n");
} else {
dev_err(&spi->dev, "data ready IRQ missing\n");
return -ENODEV;
}
st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
indio_dev->name, iio_device_id(indio_dev));
if (!st->trig) {
dev_err(&spi->dev, "failed to allocate IIO trigger\n");
return -ENOMEM;
}
st->trig->ops = &ads131e08_trigger_ops;
st->trig->dev.parent = &spi->dev;
iio_trigger_set_drvdata(st->trig, indio_dev);
ret = devm_iio_trigger_register(&spi->dev, st->trig);
if (ret) {
dev_err(&spi->dev, "failed to register IIO trigger\n");
return -ENOMEM;
}
indio_dev->trig = iio_trigger_get(st->trig);
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
NULL, &ads131e08_trigger_handler, NULL);
if (ret) {
dev_err(&spi->dev, "failed to setup IIO buffer\n");
return ret;
}
st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
if (!IS_ERR(st->vref_reg)) {
ret = regulator_enable(st->vref_reg);
if (ret) {
dev_err(&spi->dev,
"failed to enable external vref supply\n");
return ret;
}
ret = devm_add_action_or_reset(&spi->dev, ads131e08_regulator_disable, st);
if (ret)
return ret;
} else {
if (PTR_ERR(st->vref_reg) != -ENODEV)
return PTR_ERR(st->vref_reg);
st->vref_reg = NULL;
}
st->adc_clk = devm_clk_get(&spi->dev, "adc-clk");
if (IS_ERR(st->adc_clk))
return dev_err_probe(&spi->dev, PTR_ERR(st->adc_clk),
"failed to get the ADC clock\n");
ret = clk_prepare_enable(st->adc_clk);
if (ret) {
dev_err(&spi->dev, "failed to prepare/enable the ADC clock\n");
return ret;
}
ret = devm_add_action_or_reset(&spi->dev, ads131e08_clk_disable, st);
if (ret)
return ret;
adc_clk_hz = clk_get_rate(st->adc_clk);
if (!adc_clk_hz) {
dev_err(&spi->dev, "failed to get the ADC clock rate\n");
return -EINVAL;
}
adc_clk_ns = NSEC_PER_SEC / adc_clk_hz;
st->sdecode_delay_us = DIV_ROUND_UP(
ADS131E08_WAIT_SDECODE_CYCLES * adc_clk_ns, NSEC_PER_USEC);
st->reset_delay_us = DIV_ROUND_UP(
ADS131E08_WAIT_RESET_CYCLES * adc_clk_ns, NSEC_PER_USEC);
ret = ads131e08_initial_config(indio_dev);
if (ret) {
dev_err(&spi->dev, "initial configuration failed\n");
return ret;
}
return devm_iio_device_register(&spi->dev, indio_dev);
}