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