in adc/ad7606.c [566:695]
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
const char *name, unsigned int id,
const struct ad7606_bus_ops *bops)
{
struct ad7606_state *st;
int ret;
struct iio_dev *indio_dev;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
dev_set_drvdata(dev, indio_dev);
st->dev = dev;
mutex_init(&st->lock);
st->bops = bops;
st->base_address = base_address;
/* tied to logic low, analog input range is +/- 5V */
st->range[0] = 0;
st->oversampling = 1;
st->scale_avail = ad7606_scale_avail;
st->num_scales = ARRAY_SIZE(ad7606_scale_avail);
st->reg = devm_regulator_get(dev, "avcc");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
ret = regulator_enable(st->reg);
if (ret) {
dev_err(dev, "Failed to enable specified AVcc supply\n");
return ret;
}
ret = devm_add_action_or_reset(dev, ad7606_regulator_disable, st);
if (ret)
return ret;
st->chip_info = &ad7606_chip_info_tbl[id];
if (st->chip_info->oversampling_num) {
st->oversampling_avail = st->chip_info->oversampling_avail;
st->num_os_ratios = st->chip_info->oversampling_num;
}
ret = ad7606_request_gpios(st);
if (ret)
return ret;
if (st->gpio_os) {
if (st->gpio_range)
indio_dev->info = &ad7606_info_os_and_range;
else
indio_dev->info = &ad7606_info_os;
} else {
if (st->gpio_range)
indio_dev->info = &ad7606_info_range;
else
indio_dev->info = &ad7606_info_no_os_or_range;
}
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->name = name;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
init_completion(&st->completion);
ret = ad7606_reset(st);
if (ret)
dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");
/* AD7616 requires al least 15ms to reconfigure after a reset */
if (st->chip_info->init_delay_ms) {
if (msleep_interruptible(st->chip_info->init_delay_ms))
return -ERESTARTSYS;
}
st->write_scale = ad7606_write_scale_hw;
st->write_os = ad7606_write_os_hw;
if (st->bops->sw_mode_config)
st->sw_mode_en = device_property_present(st->dev,
"adi,sw-mode");
if (st->sw_mode_en) {
/* Scale of 0.076293 is only available in sw mode */
st->scale_avail = ad7616_sw_scale_avail;
st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail);
/* After reset, in software mode, ±10 V is set by default */
memset32(st->range, 2, ARRAY_SIZE(st->range));
indio_dev->info = &ad7606_info_os_range_and_debug;
ret = st->bops->sw_mode_config(indio_dev);
if (ret < 0)
return ret;
}
st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
indio_dev->name,
iio_device_id(indio_dev));
if (!st->trig)
return -ENOMEM;
st->trig->ops = &ad7606_trigger_ops;
iio_trigger_set_drvdata(st->trig, indio_dev);
ret = devm_iio_trigger_register(dev, st->trig);
if (ret)
return ret;
indio_dev->trig = iio_trigger_get(st->trig);
ret = devm_request_threaded_irq(dev, irq,
NULL,
&ad7606_interrupt,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
name, indio_dev);
if (ret)
return ret;
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
&iio_pollfunc_store_time,
&ad7606_trigger_handler,
&ad7606_buffer_ops);
if (ret)
return ret;
return devm_iio_device_register(dev, indio_dev);
}