int ad7606_probe()

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);
}