iio: inv_mpu6050: Check WHO_AM_I register on probe
authorCrestez Dan Leonard <leonard.crestez@intel.com>
Wed, 20 Apr 2016 13:15:11 +0000 (16:15 +0300)
committerJonathan Cameron <jic23@kernel.org>
Mon, 25 Apr 2016 19:19:15 +0000 (20:19 +0100)
This can be used to distinguish mpu6500. This is a warning rather than
an error because the differences are mostly irrelevant and it's nice to
avoid breaking users with slightly incorrect ACPI/DT.

Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com>
Acked-by: Ge Gao <ggao@invensense.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h

index 84d5b6939e6adb27f9c5bc3e272121425825ab38..4152f2fcf598c2f3fffe99f7981c0378467db4fa 100644 (file)
@@ -91,16 +91,19 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = {
 /* Indexed by enum inv_devices */
 static const struct inv_mpu6050_hw hw_info[] = {
        {
+               .whoami = INV_MPU6050_WHOAMI_VALUE,
                .name = "MPU6050",
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
        },
        {
+               .whoami = INV_MPU6500_WHOAMI_VALUE,
                .name = "MPU6500",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
        },
        {
+               .whoami = INV_MPU6000_WHOAMI_VALUE,
                .name = "MPU6000",
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
@@ -749,6 +752,7 @@ static const struct iio_info mpu_info = {
 static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
 {
        int result;
+       unsigned int regval;
 
        st->hw  = &hw_info[st->chip_type];
        st->reg = hw_info[st->chip_type].reg;
@@ -759,6 +763,17 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
        if (result)
                return result;
        msleep(INV_MPU6050_POWER_UP_TIME);
+
+       /* check chip self-identification */
+       result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
+       if (result)
+               return result;
+       if (regval != st->hw->whoami) {
+               dev_warn(regmap_get_device(st->map),
+                               "whoami mismatch got %#02x expected %#02hhx for %s\n",
+                               regval, st->hw->whoami, st->hw->name);
+       }
+
        /*
         * toggle power state. After reset, the sleep bit could be on
         * or off depending on the OTP settings. Toggling power would
index 26b63993ba00c40850560efddc98c0b961dc9868..fb45cc76e4e4493fb63e3945d20853388b3e3b19 100644 (file)
@@ -93,11 +93,13 @@ struct inv_mpu6050_chip_config {
 
 /**
  *  struct inv_mpu6050_hw - Other important hardware information.
+ *  @whoami:   Self identification byte from WHO_AM_I register
  *  @name:      name of the chip.
  *  @reg:   register map of the chip.
  *  @config:    configuration of the chip.
  */
 struct inv_mpu6050_hw {
+       u8 whoami;
        u8 *name;
        const struct inv_mpu6050_reg_map *reg;
        const struct inv_mpu6050_chip_config *config;
@@ -215,6 +217,12 @@ struct inv_mpu6050_state {
 #define INV_MPU6050_MIN_FIFO_RATE            4
 #define INV_MPU6050_ONE_K_HZ                 1000
 
+#define INV_MPU6050_REG_WHOAMI                 117
+
+#define INV_MPU6000_WHOAMI_VALUE               0x68
+#define INV_MPU6050_WHOAMI_VALUE               0x68
+#define INV_MPU6500_WHOAMI_VALUE               0x70
+
 /* scan element definition */
 enum inv_mpu6050_scan {
        INV_MPU6050_SCAN_ACCL_X,