]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/power/supply/axp288_fuel_gauge.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / drivers / power / supply / axp288_fuel_gauge.c
index 326eb08beaa27f3c55d04f7754c6af78fe029f2a..a8dcabc32721df7f6064f33b1940ac2a0182258c 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/iio/consumer.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <asm/unaligned.h>
 
 #define CHRG_STAT_BAT_SAFE_MODE                (1 << 3)
 #define CHRG_STAT_BAT_VALID                    (1 << 4)
 #define CHRG_CCCV_CV_4350MV                    0x3     /* 4.35V */
 #define CHRG_CCCV_CHG_EN                       (1 << 7)
 
-#define TEMP_IRQ_CFG_QWBTU                     (1 << 0)
-#define TEMP_IRQ_CFG_WBTU                      (1 << 1)
-#define TEMP_IRQ_CFG_QWBTO                     (1 << 2)
-#define TEMP_IRQ_CFG_WBTO                      (1 << 3)
-#define TEMP_IRQ_CFG_MASK                      0xf
-
-#define FG_IRQ_CFG_LOWBATT_WL2         (1 << 0)
-#define FG_IRQ_CFG_LOWBATT_WL1         (1 << 1)
-#define FG_IRQ_CFG_LOWBATT_MASK                0x3
-#define LOWBAT_IRQ_STAT_LOWBATT_WL2    (1 << 0)
-#define LOWBAT_IRQ_STAT_LOWBATT_WL1    (1 << 1)
-
 #define FG_CNTL_OCV_ADJ_STAT           (1 << 2)
 #define FG_CNTL_OCV_ADJ_EN                     (1 << 3)
 #define FG_CNTL_CAP_ADJ_STAT           (1 << 4)
 #define FG_CNTL_CC_EN                          (1 << 6)
 #define FG_CNTL_GAUGE_EN                       (1 << 7)
 
+#define FG_15BIT_WORD_VALID                    (1 << 15)
+#define FG_15BIT_VAL_MASK                      0x7fff
+
 #define FG_REP_CAP_VALID                       (1 << 7)
 #define FG_REP_CAP_VAL_MASK                    0x7F
 
 #define FG_DES_CAP1_VALID                      (1 << 7)
-#define FG_DES_CAP1_VAL_MASK           0x7F
-#define FG_DES_CAP0_VAL_MASK           0xFF
 #define FG_DES_CAP_RES_LSB                     1456    /* 1.456mAhr */
 
-#define FG_CC_MTR1_VALID                       (1 << 7)
-#define FG_CC_MTR1_VAL_MASK                    0x7F
-#define FG_CC_MTR0_VAL_MASK                    0xFF
 #define FG_DES_CC_RES_LSB                      1456    /* 1.456mAhr */
 
 #define FG_OCV_CAP_VALID                       (1 << 7)
@@ -154,8 +141,10 @@ static int fuel_gauge_reg_readb(struct axp288_fg_info *info, int reg)
                        break;
        }
 
-       if (ret < 0)
+       if (ret < 0) {
                dev_err(&info->pdev->dev, "axp288 reg read err:%d\n", ret);
+               return ret;
+       }
 
        return val;
 }
@@ -172,6 +161,44 @@ static int fuel_gauge_reg_writeb(struct axp288_fg_info *info, int reg, u8 val)
        return ret;
 }
 
+static int fuel_gauge_read_15bit_word(struct axp288_fg_info *info, int reg)
+{
+       unsigned char buf[2];
+       int ret;
+
+       ret = regmap_bulk_read(info->regmap, reg, buf, 2);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev, "Error reading reg 0x%02x err: %d\n",
+                       reg, ret);
+               return ret;
+       }
+
+       ret = get_unaligned_be16(buf);
+       if (!(ret & FG_15BIT_WORD_VALID)) {
+               dev_err(&info->pdev->dev, "Error reg 0x%02x contents not valid\n",
+                       reg);
+               return -ENXIO;
+       }
+
+       return ret & FG_15BIT_VAL_MASK;
+}
+
+static int fuel_gauge_read_12bit_word(struct axp288_fg_info *info, int reg)
+{
+       unsigned char buf[2];
+       int ret;
+
+       ret = regmap_bulk_read(info->regmap, reg, buf, 2);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev, "Error reading reg 0x%02x err: %d\n",
+                       reg, ret);
+               return ret;
+       }
+
+       /* 12-bit data values have upper 8 bits in buf[0], lower 4 in buf[1] */
+       return (buf[0] << 4) | ((buf[1] >> 4) & 0x0f);
+}
+
 static int pmic_read_adc_val(const char *name, int *raw_val,
                struct axp288_fg_info *info)
 {
@@ -232,24 +259,15 @@ static int fuel_gauge_debug_show(struct seq_file *s, void *data)
        seq_printf(s, "    FG_RDC0[%02x] : %02x\n",
                AXP288_FG_RDC0_REG,
                fuel_gauge_reg_readb(info, AXP288_FG_RDC0_REG));
-       seq_printf(s, "    FG_OCVH[%02x] : %02x\n",
+       seq_printf(s, "     FG_OCV[%02x] : %04x\n",
                AXP288_FG_OCVH_REG,
-               fuel_gauge_reg_readb(info, AXP288_FG_OCVH_REG));
-       seq_printf(s, "    FG_OCVL[%02x] : %02x\n",
-               AXP288_FG_OCVL_REG,
-               fuel_gauge_reg_readb(info, AXP288_FG_OCVL_REG));
-       seq_printf(s, "FG_DES_CAP1[%02x] : %02x\n",
+               fuel_gauge_read_12bit_word(info, AXP288_FG_OCVH_REG));
+       seq_printf(s, " FG_DES_CAP[%02x] : %04x\n",
                AXP288_FG_DES_CAP1_REG,
-               fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG));
-       seq_printf(s, "FG_DES_CAP0[%02x] : %02x\n",
-               AXP288_FG_DES_CAP0_REG,
-               fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP0_REG));
-       seq_printf(s, " FG_CC_MTR1[%02x] : %02x\n",
+               fuel_gauge_read_15bit_word(info, AXP288_FG_DES_CAP1_REG));
+       seq_printf(s, "  FG_CC_MTR[%02x] : %04x\n",
                AXP288_FG_CC_MTR1_REG,
-               fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR1_REG));
-       seq_printf(s, " FG_CC_MTR0[%02x] : %02x\n",
-               AXP288_FG_CC_MTR0_REG,
-               fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR0_REG));
+               fuel_gauge_read_15bit_word(info, AXP288_FG_CC_MTR1_REG));
        seq_printf(s, " FG_OCV_CAP[%02x] : %02x\n",
                AXP288_FG_OCV_CAP_REG,
                fuel_gauge_reg_readb(info, AXP288_FG_OCV_CAP_REG));
@@ -404,21 +422,12 @@ static int fuel_gauge_get_current(struct axp288_fg_info *info, int *cur)
 
 static int fuel_gauge_get_vocv(struct axp288_fg_info *info, int *vocv)
 {
-       int ret, value;
-
-       /* 12-bit data value, upper 8 in OCVH, lower 4 in OCVL */
-       ret = fuel_gauge_reg_readb(info, AXP288_FG_OCVH_REG);
-       if (ret < 0)
-               goto vocv_read_fail;
-       value = ret << 4;
+       int ret;
 
-       ret = fuel_gauge_reg_readb(info, AXP288_FG_OCVL_REG);
-       if (ret < 0)
-               goto vocv_read_fail;
-       value |= (ret & 0xf);
+       ret = fuel_gauge_read_12bit_word(info, AXP288_FG_OCVH_REG);
+       if (ret >= 0)
+               *vocv = VOLTAGE_FROM_ADC(ret);
 
-       *vocv = VOLTAGE_FROM_ADC(value);
-vocv_read_fail:
        return ret;
 }
 
@@ -503,28 +512,18 @@ static int fuel_gauge_get_property(struct power_supply *ps,
                val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
                break;
        case POWER_SUPPLY_PROP_CHARGE_NOW:
-               ret = fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR1_REG);
+               ret = fuel_gauge_read_15bit_word(info, AXP288_FG_CC_MTR1_REG);
                if (ret < 0)
                        goto fuel_gauge_read_err;
 
-               value = (ret & FG_CC_MTR1_VAL_MASK) << 8;
-               ret = fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR0_REG);
-               if (ret < 0)
-                       goto fuel_gauge_read_err;
-               value |= (ret & FG_CC_MTR0_VAL_MASK);
-               val->intval = value * FG_DES_CAP_RES_LSB;
+               val->intval = ret * FG_DES_CAP_RES_LSB;
                break;
        case POWER_SUPPLY_PROP_CHARGE_FULL:
-               ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG);
+               ret = fuel_gauge_read_15bit_word(info, AXP288_FG_DES_CAP1_REG);
                if (ret < 0)
                        goto fuel_gauge_read_err;
 
-               value = (ret & FG_DES_CAP1_VAL_MASK) << 8;
-               ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP0_REG);
-               if (ret < 0)
-                       goto fuel_gauge_read_err;
-               value |= (ret & FG_DES_CAP0_VAL_MASK);
-               val->intval = value * FG_DES_CAP_RES_LSB;
+               val->intval = ret * FG_DES_CAP_RES_LSB;
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
                val->intval = PROP_VOLT(info->max_volt);
@@ -699,20 +698,6 @@ static void fuel_gauge_init_irq(struct axp288_fg_info *info)
        }
 }
 
-static void fuel_gauge_init_hw_regs(struct axp288_fg_info *info)
-{
-       unsigned int val;
-
-       /* enable interrupts */
-       val = fuel_gauge_reg_readb(info, AXP20X_IRQ3_EN);
-       val |= TEMP_IRQ_CFG_MASK;
-       fuel_gauge_reg_writeb(info, AXP20X_IRQ3_EN, val);
-
-       val = fuel_gauge_reg_readb(info, AXP20X_IRQ4_EN);
-       val |= FG_IRQ_CFG_LOWBATT_MASK;
-       val = fuel_gauge_reg_writeb(info, AXP20X_IRQ4_EN, val);
-}
-
 static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 {
        int ret = 0;
@@ -771,7 +756,6 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 
        fuel_gauge_create_debugfs(info);
        fuel_gauge_init_irq(info);
-       fuel_gauge_init_hw_regs(info);
        schedule_delayed_work(&info->status_monitor, STATUS_MON_DELAY_JIFFIES);
 
        return 0;