static int mma8452_probe()

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