in accel/mma8452.c [1519:1701]
static int mma8452_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mma8452_data *data;
struct iio_dev *indio_dev;
int ret;
const struct of_device_id *match;
match = of_match_device(mma8452_dt_ids, &client->dev);
if (!match) {
dev_err(&client->dev, "unknown device model\n");
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
data->client = client;
mutex_init(&data->lock);
data->chip_info = match->data;
data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(data->vdd_reg))
return dev_err_probe(&client->dev, PTR_ERR(data->vdd_reg),
"failed to get VDD regulator!\n");
data->vddio_reg = devm_regulator_get(&client->dev, "vddio");
if (IS_ERR(data->vddio_reg))
return dev_err_probe(&client->dev, PTR_ERR(data->vddio_reg),
"failed to get VDDIO regulator!\n");
ret = regulator_enable(data->vdd_reg);
if (ret) {
dev_err(&client->dev, "failed to enable VDD regulator!\n");
return ret;
}
ret = regulator_enable(data->vddio_reg);
if (ret) {
dev_err(&client->dev, "failed to enable VDDIO regulator!\n");
goto disable_regulator_vdd;
}
ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I);
if (ret < 0)
goto disable_regulators;
switch (ret) {
case MMA8451_DEVICE_ID:
case MMA8452_DEVICE_ID:
case MMA8453_DEVICE_ID:
case MMA8652_DEVICE_ID:
case MMA8653_DEVICE_ID:
case FXLS8471_DEVICE_ID:
if (ret == data->chip_info->chip_id)
break;
fallthrough;
default:
ret = -ENODEV;
goto disable_regulators;
}
dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n",
match->compatible, data->chip_info->chip_id);
i2c_set_clientdata(client, indio_dev);
indio_dev->info = &mma8452_info;
indio_dev->name = id->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = data->chip_info->channels;
indio_dev->num_channels = data->chip_info->num_channels;
indio_dev->available_scan_masks = mma8452_scan_masks;
ret = mma8452_reset(client);
if (ret < 0)
goto disable_regulators;
data->data_cfg = MMA8452_DATA_CFG_FS_2G;
ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG,
data->data_cfg);
if (ret < 0)
goto disable_regulators;
/*
* By default set transient threshold to max to avoid events if
* enabling without configuring threshold.
*/
ret = i2c_smbus_write_byte_data(client, MMA8452_TRANSIENT_THS,
MMA8452_TRANSIENT_THS_MASK);
if (ret < 0)
goto disable_regulators;
if (client->irq) {
int irq2;
irq2 = of_irq_get_byname(client->dev.of_node, "INT2");
if (irq2 == client->irq) {
dev_dbg(&client->dev, "using interrupt line INT2\n");
} else {
ret = i2c_smbus_write_byte_data(client,
MMA8452_CTRL_REG5,
data->chip_info->all_events);
if (ret < 0)
goto disable_regulators;
dev_dbg(&client->dev, "using interrupt line INT1\n");
}
ret = i2c_smbus_write_byte_data(client,
MMA8452_CTRL_REG4,
data->chip_info->enabled_events);
if (ret < 0)
goto disable_regulators;
ret = mma8452_trigger_setup(indio_dev);
if (ret < 0)
goto disable_regulators;
}
data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
(MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
data->sleep_val = mma8452_calculate_sleep(data);
ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
data->ctrl_reg1);
if (ret < 0)
goto trigger_cleanup;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
mma8452_trigger_handler, NULL);
if (ret < 0)
goto trigger_cleanup;
if (client->irq) {
ret = devm_request_threaded_irq(&client->dev,
client->irq,
NULL, mma8452_interrupt,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
client->name, indio_dev);
if (ret)
goto buffer_cleanup;
}
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto buffer_cleanup;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
MMA8452_AUTO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
ret = iio_device_register(indio_dev);
if (ret < 0)
goto buffer_cleanup;
ret = mma8452_set_freefall_mode(data, false);
if (ret < 0)
goto unregister_device;
return 0;
unregister_device:
iio_device_unregister(indio_dev);
buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
trigger_cleanup:
mma8452_trigger_cleanup(indio_dev);
disable_regulators:
regulator_disable(data->vddio_reg);
disable_regulator_vdd:
regulator_disable(data->vdd_reg);
return ret;
}