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