xref: /openbmc/linux/drivers/iio/gyro/mpu3050-i2c.c (revision 7cf15f42)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23904b28eSLinus Walleij #include <linux/err.h>
33904b28eSLinus Walleij #include <linux/i2c.h>
43904b28eSLinus Walleij #include <linux/i2c-mux.h>
53904b28eSLinus Walleij #include <linux/iio/iio.h>
63904b28eSLinus Walleij #include <linux/module.h>
73904b28eSLinus Walleij #include <linux/regmap.h>
83904b28eSLinus Walleij #include <linux/pm_runtime.h>
93904b28eSLinus Walleij 
103904b28eSLinus Walleij #include "mpu3050.h"
113904b28eSLinus Walleij 
123904b28eSLinus Walleij static const struct regmap_config mpu3050_i2c_regmap_config = {
133904b28eSLinus Walleij 	.reg_bits = 8,
143904b28eSLinus Walleij 	.val_bits = 8,
153904b28eSLinus Walleij };
163904b28eSLinus Walleij 
mpu3050_i2c_bypass_select(struct i2c_mux_core * mux,u32 chan_id)173904b28eSLinus Walleij static int mpu3050_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id)
183904b28eSLinus Walleij {
193904b28eSLinus Walleij 	struct mpu3050 *mpu3050 = i2c_mux_priv(mux);
203904b28eSLinus Walleij 
213904b28eSLinus Walleij 	/* Just power up the device, that is all that is needed */
223904b28eSLinus Walleij 	pm_runtime_get_sync(mpu3050->dev);
233904b28eSLinus Walleij 	return 0;
243904b28eSLinus Walleij }
253904b28eSLinus Walleij 
mpu3050_i2c_bypass_deselect(struct i2c_mux_core * mux,u32 chan_id)263904b28eSLinus Walleij static int mpu3050_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id)
273904b28eSLinus Walleij {
283904b28eSLinus Walleij 	struct mpu3050 *mpu3050 = i2c_mux_priv(mux);
293904b28eSLinus Walleij 
303904b28eSLinus Walleij 	pm_runtime_mark_last_busy(mpu3050->dev);
313904b28eSLinus Walleij 	pm_runtime_put_autosuspend(mpu3050->dev);
323904b28eSLinus Walleij 	return 0;
333904b28eSLinus Walleij }
343904b28eSLinus Walleij 
mpu3050_i2c_probe(struct i2c_client * client)35b97db528SUwe Kleine-König static int mpu3050_i2c_probe(struct i2c_client *client)
363904b28eSLinus Walleij {
37b97db528SUwe Kleine-König 	const struct i2c_device_id *id = i2c_client_get_device_id(client);
383904b28eSLinus Walleij 	struct regmap *regmap;
393904b28eSLinus Walleij 	const char *name;
403904b28eSLinus Walleij 	struct mpu3050 *mpu3050;
413904b28eSLinus Walleij 	int ret;
423904b28eSLinus Walleij 
433904b28eSLinus Walleij 	if (!i2c_check_functionality(client->adapter,
443904b28eSLinus Walleij 				     I2C_FUNC_SMBUS_I2C_BLOCK))
453904b28eSLinus Walleij 		return -EOPNOTSUPP;
463904b28eSLinus Walleij 
473904b28eSLinus Walleij 	if (id)
483904b28eSLinus Walleij 		name = id->name;
493904b28eSLinus Walleij 	else
503904b28eSLinus Walleij 		return -ENODEV;
513904b28eSLinus Walleij 
523904b28eSLinus Walleij 	regmap = devm_regmap_init_i2c(client, &mpu3050_i2c_regmap_config);
533904b28eSLinus Walleij 	if (IS_ERR(regmap)) {
540e5fd387SNishant Malpani 		dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
550e5fd387SNishant Malpani 			regmap);
563904b28eSLinus Walleij 		return PTR_ERR(regmap);
573904b28eSLinus Walleij 	}
583904b28eSLinus Walleij 
593904b28eSLinus Walleij 	ret = mpu3050_common_probe(&client->dev, regmap, client->irq, name);
603904b28eSLinus Walleij 	if (ret)
613904b28eSLinus Walleij 		return ret;
623904b28eSLinus Walleij 
633904b28eSLinus Walleij 	/* The main driver is up, now register the I2C mux */
643904b28eSLinus Walleij 	mpu3050 = iio_priv(dev_get_drvdata(&client->dev));
653904b28eSLinus Walleij 	mpu3050->i2cmux = i2c_mux_alloc(client->adapter, &client->dev,
663904b28eSLinus Walleij 					1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
673904b28eSLinus Walleij 					mpu3050_i2c_bypass_select,
683904b28eSLinus Walleij 					mpu3050_i2c_bypass_deselect);
693904b28eSLinus Walleij 	/* Just fail the mux, there is no point in killing the driver */
703904b28eSLinus Walleij 	if (!mpu3050->i2cmux)
713904b28eSLinus Walleij 		dev_err(&client->dev, "failed to allocate I2C mux\n");
723904b28eSLinus Walleij 	else {
733904b28eSLinus Walleij 		mpu3050->i2cmux->priv = mpu3050;
746a95d825SPeter Rosin 		/* Ignore failure, not critical */
756a95d825SPeter Rosin 		i2c_mux_add_adapter(mpu3050->i2cmux, 0, 0, 0);
763904b28eSLinus Walleij 	}
773904b28eSLinus Walleij 
783904b28eSLinus Walleij 	return 0;
793904b28eSLinus Walleij }
803904b28eSLinus Walleij 
mpu3050_i2c_remove(struct i2c_client * client)81ed5c2f5fSUwe Kleine-König static void mpu3050_i2c_remove(struct i2c_client *client)
823904b28eSLinus Walleij {
833904b28eSLinus Walleij 	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
843904b28eSLinus Walleij 	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
853904b28eSLinus Walleij 
863904b28eSLinus Walleij 	if (mpu3050->i2cmux)
873904b28eSLinus Walleij 		i2c_mux_del_adapters(mpu3050->i2cmux);
883904b28eSLinus Walleij 
89d3beaf18SUwe Kleine-König 	mpu3050_common_remove(&client->dev);
903904b28eSLinus Walleij }
913904b28eSLinus Walleij 
923904b28eSLinus Walleij /*
933904b28eSLinus Walleij  * device id table is used to identify what device can be
943904b28eSLinus Walleij  * supported by this driver
953904b28eSLinus Walleij  */
963904b28eSLinus Walleij static const struct i2c_device_id mpu3050_i2c_id[] = {
973904b28eSLinus Walleij 	{ "mpu3050" },
983904b28eSLinus Walleij 	{}
993904b28eSLinus Walleij };
1003904b28eSLinus Walleij MODULE_DEVICE_TABLE(i2c, mpu3050_i2c_id);
1013904b28eSLinus Walleij 
1023904b28eSLinus Walleij static const struct of_device_id mpu3050_i2c_of_match[] = {
1033904b28eSLinus Walleij 	{ .compatible = "invensense,mpu3050", .data = "mpu3050" },
1043904b28eSLinus Walleij 	/* Deprecated vendor ID from the Input driver */
1053904b28eSLinus Walleij 	{ .compatible = "invn,mpu3050", .data = "mpu3050" },
1063904b28eSLinus Walleij 	{ },
1073904b28eSLinus Walleij };
1083904b28eSLinus Walleij MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match);
1093904b28eSLinus Walleij 
1103904b28eSLinus Walleij static struct i2c_driver mpu3050_i2c_driver = {
111*7cf15f42SUwe Kleine-König 	.probe = mpu3050_i2c_probe,
1123904b28eSLinus Walleij 	.remove = mpu3050_i2c_remove,
1133904b28eSLinus Walleij 	.id_table = mpu3050_i2c_id,
1143904b28eSLinus Walleij 	.driver = {
1153904b28eSLinus Walleij 		.of_match_table = mpu3050_i2c_of_match,
1163904b28eSLinus Walleij 		.name = "mpu3050-i2c",
117feb0bd2bSJonathan Cameron 		.pm = pm_ptr(&mpu3050_dev_pm_ops),
1183904b28eSLinus Walleij 	},
1193904b28eSLinus Walleij };
1203904b28eSLinus Walleij module_i2c_driver(mpu3050_i2c_driver);
1213904b28eSLinus Walleij 
1223904b28eSLinus Walleij MODULE_AUTHOR("Linus Walleij");
1233904b28eSLinus Walleij MODULE_DESCRIPTION("Invensense MPU3050 gyroscope driver");
1243904b28eSLinus Walleij MODULE_LICENSE("GPL");
125