root/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. inv_mpu6050_select_bypass
  2. inv_mpu6050_deselect_bypass
  3. inv_mpu_match_acpi_device
  4. inv_mpu_probe
  5. inv_mpu_remove

   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 
  15 static const struct regmap_config inv_mpu_regmap_config = {
  16         .reg_bits = 8,
  17         .val_bits = 8,
  18 };
  19 
  20 static 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 
  35 error_unlock:
  36         mutex_unlock(&st->lock);
  37 
  38         return ret;
  39 }
  40 
  41 static 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 
  57 static 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  */
  78 static 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 
 145 out_del_mux:
 146         i2c_mux_del_adapters(st->muxc);
 147         return result;
 148 }
 149 
 150 static 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  */
 167 static 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 
 179 MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
 180 
 181 static 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 };
 216 MODULE_DEVICE_TABLE(of, inv_of_match);
 217 
 218 static const struct acpi_device_id inv_acpi_match[] = {
 219         {"INVN6500", INV_MPU6500},
 220         { },
 221 };
 222 
 223 MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
 224 
 225 static 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 
 237 module_i2c_driver(inv_mpu_driver);
 238 
 239 MODULE_AUTHOR("Invensense Corporation");
 240 MODULE_DESCRIPTION("Invensense device MPU6050 driver");
 241 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */