mpu3050-i2c.c (3196B)
1// SPDX-License-Identifier: GPL-2.0-only 2#include <linux/err.h> 3#include <linux/i2c.h> 4#include <linux/i2c-mux.h> 5#include <linux/iio/iio.h> 6#include <linux/module.h> 7#include <linux/regmap.h> 8#include <linux/pm_runtime.h> 9 10#include "mpu3050.h" 11 12static const struct regmap_config mpu3050_i2c_regmap_config = { 13 .reg_bits = 8, 14 .val_bits = 8, 15}; 16 17static int mpu3050_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id) 18{ 19 struct mpu3050 *mpu3050 = i2c_mux_priv(mux); 20 21 /* Just power up the device, that is all that is needed */ 22 pm_runtime_get_sync(mpu3050->dev); 23 return 0; 24} 25 26static int mpu3050_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id) 27{ 28 struct mpu3050 *mpu3050 = i2c_mux_priv(mux); 29 30 pm_runtime_mark_last_busy(mpu3050->dev); 31 pm_runtime_put_autosuspend(mpu3050->dev); 32 return 0; 33} 34 35static int mpu3050_i2c_probe(struct i2c_client *client, 36 const struct i2c_device_id *id) 37{ 38 struct regmap *regmap; 39 const char *name; 40 struct mpu3050 *mpu3050; 41 int ret; 42 43 if (!i2c_check_functionality(client->adapter, 44 I2C_FUNC_SMBUS_I2C_BLOCK)) 45 return -EOPNOTSUPP; 46 47 if (id) 48 name = id->name; 49 else 50 return -ENODEV; 51 52 regmap = devm_regmap_init_i2c(client, &mpu3050_i2c_regmap_config); 53 if (IS_ERR(regmap)) { 54 dev_err(&client->dev, "Failed to register i2c regmap: %pe\n", 55 regmap); 56 return PTR_ERR(regmap); 57 } 58 59 ret = mpu3050_common_probe(&client->dev, regmap, client->irq, name); 60 if (ret) 61 return ret; 62 63 /* The main driver is up, now register the I2C mux */ 64 mpu3050 = iio_priv(dev_get_drvdata(&client->dev)); 65 mpu3050->i2cmux = i2c_mux_alloc(client->adapter, &client->dev, 66 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE, 67 mpu3050_i2c_bypass_select, 68 mpu3050_i2c_bypass_deselect); 69 /* Just fail the mux, there is no point in killing the driver */ 70 if (!mpu3050->i2cmux) 71 dev_err(&client->dev, "failed to allocate I2C mux\n"); 72 else { 73 mpu3050->i2cmux->priv = mpu3050; 74 /* Ignore failure, not critical */ 75 i2c_mux_add_adapter(mpu3050->i2cmux, 0, 0, 0); 76 } 77 78 return 0; 79} 80 81static int mpu3050_i2c_remove(struct i2c_client *client) 82{ 83 struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); 84 struct mpu3050 *mpu3050 = iio_priv(indio_dev); 85 86 if (mpu3050->i2cmux) 87 i2c_mux_del_adapters(mpu3050->i2cmux); 88 89 mpu3050_common_remove(&client->dev); 90 91 return 0; 92} 93 94/* 95 * device id table is used to identify what device can be 96 * supported by this driver 97 */ 98static const struct i2c_device_id mpu3050_i2c_id[] = { 99 { "mpu3050" }, 100 {} 101}; 102MODULE_DEVICE_TABLE(i2c, mpu3050_i2c_id); 103 104static const struct of_device_id mpu3050_i2c_of_match[] = { 105 { .compatible = "invensense,mpu3050", .data = "mpu3050" }, 106 /* Deprecated vendor ID from the Input driver */ 107 { .compatible = "invn,mpu3050", .data = "mpu3050" }, 108 { }, 109}; 110MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match); 111 112static struct i2c_driver mpu3050_i2c_driver = { 113 .probe = mpu3050_i2c_probe, 114 .remove = mpu3050_i2c_remove, 115 .id_table = mpu3050_i2c_id, 116 .driver = { 117 .of_match_table = mpu3050_i2c_of_match, 118 .name = "mpu3050-i2c", 119 .pm = &mpu3050_dev_pm_ops, 120 }, 121}; 122module_i2c_driver(mpu3050_i2c_driver); 123 124MODULE_AUTHOR("Linus Walleij"); 125MODULE_DESCRIPTION("Invensense MPU3050 gyroscope driver"); 126MODULE_LICENSE("GPL");