static int yas5xx_probe()

in magnetometer/yamaha-yas530.c [817:944]


static int yas5xx_probe(struct i2c_client *i2c,
			const struct i2c_device_id *id)
{
	struct iio_dev *indio_dev;
	struct device *dev = &i2c->dev;
	struct yas5xx *yas5xx;
	int ret;

	indio_dev = devm_iio_device_alloc(dev, sizeof(*yas5xx));
	if (!indio_dev)
		return -ENOMEM;

	yas5xx = iio_priv(indio_dev);
	i2c_set_clientdata(i2c, indio_dev);
	yas5xx->dev = dev;
	mutex_init(&yas5xx->lock);

	ret = iio_read_mount_matrix(dev, &yas5xx->orientation);
	if (ret)
		return ret;

	yas5xx->regs[0].supply = "vdd";
	yas5xx->regs[1].supply = "iovdd";
	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(yas5xx->regs),
				      yas5xx->regs);
	if (ret)
		return dev_err_probe(dev, ret, "cannot get regulators\n");

	ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);
	if (ret) {
		dev_err(dev, "cannot enable regulators\n");
		return ret;
	}

	/* See comment in runtime resume callback */
	usleep_range(31000, 40000);

	/* This will take the device out of reset if need be */
	yas5xx->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
	if (IS_ERR(yas5xx->reset)) {
		ret = dev_err_probe(dev, PTR_ERR(yas5xx->reset),
				    "failed to get reset line\n");
		goto reg_off;
	}

	yas5xx->map = devm_regmap_init_i2c(i2c, &yas5xx_regmap_config);
	if (IS_ERR(yas5xx->map)) {
		dev_err(dev, "failed to allocate register map\n");
		ret = PTR_ERR(yas5xx->map);
		goto assert_reset;
	}

	ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &yas5xx->devid);
	if (ret)
		goto assert_reset;

	switch (yas5xx->devid) {
	case YAS530_DEVICE_ID:
		ret = yas530_get_calibration_data(yas5xx);
		if (ret)
			goto assert_reset;
		dev_info(dev, "detected YAS530 MS-3E %s",
			 yas5xx->version ? "B" : "A");
		strncpy(yas5xx->name, "yas530", sizeof(yas5xx->name));
		break;
	case YAS532_DEVICE_ID:
		ret = yas532_get_calibration_data(yas5xx);
		if (ret)
			goto assert_reset;
		dev_info(dev, "detected YAS532/YAS533 MS-3R/F %s",
			 yas5xx->version ? "AC" : "AB");
		strncpy(yas5xx->name, "yas532", sizeof(yas5xx->name));
		break;
	default:
		ret = -ENODEV;
		dev_err(dev, "unhandled device ID %02x\n", yas5xx->devid);
		goto assert_reset;
	}

	yas5xx_dump_calibration(yas5xx);
	ret = yas5xx_power_on(yas5xx);
	if (ret)
		goto assert_reset;
	ret = yas5xx_meaure_offsets(yas5xx);
	if (ret)
		goto assert_reset;

	indio_dev->info = &yas5xx_info;
	indio_dev->available_scan_masks = yas5xx_scan_masks;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->name = yas5xx->name;
	indio_dev->channels = yas5xx_channels;
	indio_dev->num_channels = ARRAY_SIZE(yas5xx_channels);

	ret = iio_triggered_buffer_setup(indio_dev, NULL,
					 yas5xx_handle_trigger,
					 NULL);
	if (ret) {
		dev_err(dev, "triggered buffer setup failed\n");
		goto assert_reset;
	}

	ret = iio_device_register(indio_dev);
	if (ret) {
		dev_err(dev, "device register failed\n");
		goto cleanup_buffer;
	}

	/* Take runtime PM online */
	pm_runtime_get_noresume(dev);
	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);

	pm_runtime_set_autosuspend_delay(dev, YAS5XX_AUTOSUSPEND_DELAY_MS);
	pm_runtime_use_autosuspend(dev);
	pm_runtime_put(dev);

	return 0;

cleanup_buffer:
	iio_triggered_buffer_cleanup(indio_dev);
assert_reset:
	gpiod_set_value_cansleep(yas5xx->reset, 1);
reg_off:
	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);

	return ret;
}