-binding for LTC2941 and LTC2943 battery gauges
+binding for LTC2941, LTC2942 and LTC2943 battery gauges
 
-Both the LTC2941 and LTC2943 measure battery capacity.
-The LTC2943 is compatible with the LTC2941, it adds voltage and
-temperature monitoring, and uses a slightly different conversion
-formula for the charge counter.
+All chips measure battery capacity.
+The LTC2942 is pin compatible with the LTC2941, it adds voltage and
+temperature monitoring, and is runtime detected. LTC2943 is software
+compatible, uses a slightly different conversion formula for the
+charge counter and adds voltage, current and temperature monitoring.
 
 Required properties:
-- compatible: Should contain "lltc,ltc2941" or "lltc,ltc2943" which also
-    indicates the type of I2C chip attached.
+- compatible: Should contain "lltc,ltc2941", "lltc,ltc2942" or "lltc,ltc2943"
+    which also indicates the type of I2C chip attached.
 - reg: The 7-bit I2C address.
 - lltc,resistor-sense: The sense resistor value in milli-ohms. Can be a 32-bit
     negative value when the battery has been connected to the wrong end of the
 
 /*
- * I2C client/driver for the Linear Technology LTC2941 and LTC2943
+ * I2C client/driver for the Linear Technology LTC2941, LTC2942 and LTC2943
  * Battery Gas Gauge IC
  *
  * Copyright (C) 2014 Topic Embedded Systems
 
 enum ltc294x_id {
        LTC2941_ID,
+       LTC2942_ID,
        LTC2943_ID,
 };
 
-#define LTC2943_REG_CONTROL_MODE_MASK (BIT(7) | BIT(6))
-#define LTC2943_REG_CONTROL_MODE_SCAN BIT(7)
+#define LTC2941_REG_STATUS_CHIP_ID     BIT(7)
+
+#define LTC2942_REG_CONTROL_MODE_SCAN  (BIT(7) | BIT(6))
+#define LTC2943_REG_CONTROL_MODE_SCAN  BIT(7)
 #define LTC294X_REG_CONTROL_PRESCALER_MASK     (BIT(5) | BIT(4) | BIT(3))
 #define LTC294X_REG_CONTROL_SHUTDOWN_MASK      (BIT(0))
 #define LTC294X_REG_CONTROL_PRESCALER_SET(x) \
 
        control = LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp) |
                                LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED;
-       /* Put the 2943 into "monitor" mode, so it measures every 10 sec */
-       if (info->id == LTC2941_ID)
+       /* Put device into "monitor" mode */
+       switch (info->id) {
+       case LTC2942_ID:        /* 2942 measures every 2 sec */
+               control |= LTC2942_REG_CONTROL_MODE_SCAN;
+               break;
+       case LTC2943_ID:        /* 2943 measures every 10 sec */
                control |= LTC2943_REG_CONTROL_MODE_SCAN;
+               break;
+       default:
+               break;
+       }
 
        if (value != control) {
                ret = ltc294x_write_regs(info->client,
        ret = ltc294x_read_regs(info->client,
                LTC294X_REG_VOLTAGE_MSB, &datar[0], 2);
        value = (datar[0] << 8) | datar[1];
-       *val = ((value * 23600) / 0xFFFF) * 1000; /* in uV */
+       switch (info->id) {
+       case LTC2943_ID:
+               value *= 23600 * 2;
+               value /= 0xFFFF;
+               value *= 1000 / 2;
+               break;
+       default:
+               value *= 6000 * 10;
+               value /= 0xFFFF;
+               value *= 1000 / 10;
+               break;
+       }
+       *val = value;
        return ret;
 }
 
 
 static int ltc294x_get_temperature(const struct ltc294x_info *info, int *val)
 {
+       enum ltc294x_reg reg;
        int ret;
        u8 datar[2];
        u32 value;
 
-       ret = ltc294x_read_regs(info->client,
-               LTC2943_REG_TEMPERATURE_MSB, &datar[0], 2);
-       value = (datar[0] << 8) | datar[1];
-       /* Full-scale is 510 Kelvin, convert to centidegrees  */
-       *val = (((51000 * value) / 0xFFFF) - 27215);
+       if (info->id == LTC2942_ID) {
+               reg = LTC2942_REG_TEMPERATURE_MSB;
+               value = 60000;  /* Full-scale is 600 Kelvin */
+       } else {
+               reg = LTC2943_REG_TEMPERATURE_MSB;
+               value = 51000;  /* Full-scale is 510 Kelvin */
+       }
+       ret = ltc294x_read_regs(info->client, reg, &datar[0], 2);
+       value *= (datar[0] << 8) | datar[1];
+       /* Convert to centidegrees  */
+       *val = value / 0xFFFF - 27215;
        return ret;
 }
 
 {
        struct power_supply_config psy_cfg = {};
        struct ltc294x_info *info;
+       struct device_node *np;
        int ret;
        u32 prescaler_exp;
        s32 r_sense;
-       struct device_node *np;
+       u8 status;
 
        info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
        if (info == NULL)
                                (128 / (1 << prescaler_exp));
        }
 
+       /* Read status register to check for LTC2942 */
+       if (info->id == LTC2941_ID || info->id == LTC2942_ID) {
+               ret = ltc294x_read_regs(client, LTC294X_REG_STATUS, &status, 1);
+               if (ret < 0) {
+                       dev_err(&client->dev,
+                               "Could not read status register\n");
+                       return ret;
+               }
+               if (status & LTC2941_REG_STATUS_CHIP_ID)
+                       info->id = LTC2941_ID;
+               else
+                       info->id = LTC2942_ID;
+       }
+
        info->client = client;
        info->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY;
        info->supply_desc.properties = ltc294x_properties;
                info->supply_desc.num_properties =
                        ARRAY_SIZE(ltc294x_properties);
                break;
+       case LTC2942_ID:
+               info->supply_desc.num_properties =
+                       ARRAY_SIZE(ltc294x_properties) - 1;
+               break;
        case LTC2941_ID:
        default:
                info->supply_desc.num_properties =
 
 static const struct i2c_device_id ltc294x_i2c_id[] = {
        { "ltc2941", LTC2941_ID, },
+       { "ltc2942", LTC2942_ID, },
        { "ltc2943", LTC2943_ID, },
        { },
 };
                .compatible = "lltc,ltc2941",
                .data = (void *)LTC2941_ID,
        },
+       {
+               .compatible = "lltc,ltc2942",
+               .data = (void *)LTC2942_ID,
+       },
        {
                .compatible = "lltc,ltc2943",
                .data = (void *)LTC2943_ID,
 
 MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems");
 MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products");
-MODULE_DESCRIPTION("LTC2941/LTC2943 Battery Gas Gauge IC driver");
+MODULE_DESCRIPTION("LTC2941/LTC2942/LTC2943 Battery Gas Gauge IC driver");
 MODULE_LICENSE("GPL");