linux/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3* Copyright (C) 2012 Invensense, Inc.
   4*/
   5
   6#include <linux/acpi.h>
   7#include <linux/delay.h>
   8#include <linux/err.h>
   9#include <linux/i2c.h>
  10#include <linux/iio/iio.h>
  11#include <linux/module.h>
  12#include <linux/of_device.h>
  13#include "inv_mpu_iio.h"
  14
  15static const struct regmap_config inv_mpu_regmap_config = {
  16        .reg_bits = 8,
  17        .val_bits = 8,
  18};
  19
  20static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
  21{
  22        struct iio_dev *indio_dev = i2c_mux_priv(muxc);
  23        struct inv_mpu6050_state *st = iio_priv(indio_dev);
  24        int ret;
  25
  26        mutex_lock(&st->lock);
  27
  28        ret = inv_mpu6050_set_power_itg(st, true);
  29        if (ret)
  30                goto error_unlock;
  31
  32        ret = regmap_write(st->map, st->reg->int_pin_cfg,
  33                           st->irq_mask | INV_MPU6050_BIT_BYPASS_EN);
  34
  35error_unlock:
  36        mutex_unlock(&st->lock);
  37
  38        return ret;
  39}
  40
  41static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
  42{
  43        struct iio_dev *indio_dev = i2c_mux_priv(muxc);
  44        struct inv_mpu6050_state *st = iio_priv(indio_dev);
  45
  46        mutex_lock(&st->lock);
  47
  48        /* It doesn't really matter if any of the calls fail */
  49        regmap_write(st->map, st->reg->int_pin_cfg, st->irq_mask);
  50        inv_mpu6050_set_power_itg(st, false);
  51
  52        mutex_unlock(&st->lock);
  53
  54        return 0;
  55}
  56
  57static const char *inv_mpu_match_acpi_device(struct device *dev,
  58                                             enum inv_devices *chip_id)
  59{
  60        const struct acpi_device_id *id;
  61
  62        id = acpi_match_device(dev->driver->acpi_match_table, dev);
  63        if (!id)
  64                return NULL;
  65
  66        *chip_id = (int)id->driver_data;
  67
  68        return dev_name(dev);
  69}
  70
  71/**
  72 *  inv_mpu_probe() - probe function.
  73 *  @client:          i2c client.
  74 *  @id:              i2c device id.
  75 *
  76 *  Returns 0 on success, a negative error code otherwise.
  77 */
  78static int inv_mpu_probe(struct i2c_client *client,
  79                         const struct i2c_device_id *id)
  80{
  81        struct inv_mpu6050_state *st;
  82        int result;
  83        enum inv_devices chip_type;
  84        struct regmap *regmap;
  85        const char *name;
  86
  87        if (!i2c_check_functionality(client->adapter,
  88                                     I2C_FUNC_SMBUS_I2C_BLOCK))
  89                return -EOPNOTSUPP;
  90
  91        if (client->dev.of_node) {
  92                chip_type = (enum inv_devices)
  93                        of_device_get_match_data(&client->dev);
  94                name = client->name;
  95        } else if (id) {
  96                chip_type = (enum inv_devices)
  97                        id->driver_data;
  98                name = id->name;
  99        } else if (ACPI_HANDLE(&client->dev)) {
 100                name = inv_mpu_match_acpi_device(&client->dev, &chip_type);
 101                if (!name)
 102                        return -ENODEV;
 103        } else {
 104                return -ENOSYS;
 105        }
 106
 107        regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
 108        if (IS_ERR(regmap)) {
 109                dev_err(&client->dev, "Failed to register i2c regmap %d\n",
 110                        (int)PTR_ERR(regmap));
 111                return PTR_ERR(regmap);
 112        }
 113
 114        result = inv_mpu_core_probe(regmap, client->irq, name,
 115                                    NULL, chip_type);
 116        if (result < 0)
 117                return result;
 118
 119        st = iio_priv(dev_get_drvdata(&client->dev));
 120        switch (st->chip_type) {
 121        case INV_ICM20608:
 122        case INV_ICM20602:
 123                /* no i2c auxiliary bus on the chip */
 124                break;
 125        default:
 126                /* declare i2c auxiliary bus */
 127                st->muxc = i2c_mux_alloc(client->adapter, &client->dev,
 128                                         1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
 129                                         inv_mpu6050_select_bypass,
 130                                         inv_mpu6050_deselect_bypass);
 131                if (!st->muxc)
 132                        return -ENOMEM;
 133                st->muxc->priv = dev_get_drvdata(&client->dev);
 134                result = i2c_mux_add_adapter(st->muxc, 0, 0, 0);
 135                if (result)
 136                        return result;
 137                result = inv_mpu_acpi_create_mux_client(client);
 138                if (result)
 139                        goto out_del_mux;
 140                break;
 141        }
 142
 143        return 0;
 144
 145out_del_mux:
 146        i2c_mux_del_adapters(st->muxc);
 147        return result;
 148}
 149
 150static int inv_mpu_remove(struct i2c_client *client)
 151{
 152        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 153        struct inv_mpu6050_state *st = iio_priv(indio_dev);
 154
 155        if (st->muxc) {
 156                inv_mpu_acpi_delete_mux_client(client);
 157                i2c_mux_del_adapters(st->muxc);
 158        }
 159
 160        return 0;
 161}
 162
 163/*
 164 * device id table is used to identify what device can be
 165 * supported by this driver
 166 */
 167static const struct i2c_device_id inv_mpu_id[] = {
 168        {"mpu6050", INV_MPU6050},
 169        {"mpu6500", INV_MPU6500},
 170        {"mpu6515", INV_MPU6515},
 171        {"mpu9150", INV_MPU9150},
 172        {"mpu9250", INV_MPU9250},
 173        {"mpu9255", INV_MPU9255},
 174        {"icm20608", INV_ICM20608},
 175        {"icm20602", INV_ICM20602},
 176        {}
 177};
 178
 179MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
 180
 181static const struct of_device_id inv_of_match[] = {
 182        {
 183                .compatible = "invensense,mpu6050",
 184                .data = (void *)INV_MPU6050
 185        },
 186        {
 187                .compatible = "invensense,mpu6500",
 188                .data = (void *)INV_MPU6500
 189        },
 190        {
 191                .compatible = "invensense,mpu6515",
 192                .data = (void *)INV_MPU6515
 193        },
 194        {
 195                .compatible = "invensense,mpu9150",
 196                .data = (void *)INV_MPU9150
 197        },
 198        {
 199                .compatible = "invensense,mpu9250",
 200                .data = (void *)INV_MPU9250
 201        },
 202        {
 203                .compatible = "invensense,mpu9255",
 204                .data = (void *)INV_MPU9255
 205        },
 206        {
 207                .compatible = "invensense,icm20608",
 208                .data = (void *)INV_ICM20608
 209        },
 210        {
 211                .compatible = "invensense,icm20602",
 212                .data = (void *)INV_ICM20602
 213        },
 214        { }
 215};
 216MODULE_DEVICE_TABLE(of, inv_of_match);
 217
 218static const struct acpi_device_id inv_acpi_match[] = {
 219        {"INVN6500", INV_MPU6500},
 220        { },
 221};
 222
 223MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
 224
 225static struct i2c_driver inv_mpu_driver = {
 226        .probe          =       inv_mpu_probe,
 227        .remove         =       inv_mpu_remove,
 228        .id_table       =       inv_mpu_id,
 229        .driver = {
 230                .of_match_table = inv_of_match,
 231                .acpi_match_table = ACPI_PTR(inv_acpi_match),
 232                .name   =       "inv-mpu6050-i2c",
 233                .pm     =       &inv_mpu_pmops,
 234        },
 235};
 236
 237module_i2c_driver(inv_mpu_driver);
 238
 239MODULE_AUTHOR("Invensense Corporation");
 240MODULE_DESCRIPTION("Invensense device MPU6050 driver");
 241MODULE_LICENSE("GPL");
 242