power: tps80031: battery-gauge: register as mfd sub device
[linux-2.6.git] / drivers / mfd / tps80031.c
index e6bfd47..f9f3f09 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps80031.h>
 #define TPS80031_PREQ3_RES_ASS_A       0xDD
 #define TPS80031_PHOENIX_MSK_TRANSITION 0x20
 
+#define TPS80031_CFG_INPUT_PUPD1 0xF0
+#define TPS80031_CFG_INPUT_PUPD2 0xF1
+#define TPS80031_CFG_INPUT_PUPD3 0xF2
+#define TPS80031_CFG_INPUT_PUPD4 0xF3
+
+#define TPS80031_BBSPOR_CFG    0xE6
+#define TPS80031_BBSPOR_CHG_EN 0x8
+
+/* Valid Address ranges */
+#define TPS80031_ID0_PMIC_SLAVE_SMPS_DVS       0x55 ... 0x5C
+
+#define TPS80031_ID1_RTC                       0x00 ... 0x16
+#define TPS80031_ID1_MEMORY                    0x17 ... 0x1E
+#define TPS80031_ID1_PMC_MASTER                        0x1F ... 0x2D
+#define TPS80031_ID1_PMC_SLAVE_MISC            0x31 ... 0x34
+#define TPS80031_ID1_PMC_SLAVE_SMPS            0x40 ... 0x68
+#define TPS80031_ID1_PMC_SLAVE_LDO             0x80 ... 0xA7
+#define TPS80031_ID1_PMC_SLAVE_REOSURCES       0XAD ... 0xD0
+#define TPS80031_ID1_PMC_PREQ_ASSIGN           0XD7 ... 0xDF
+#define TPS80031_ID1_PMC_MISC                  0xE2 ... 0xEF
+#define TPS80031_ID1_PMC_PU_PD_HZ              0xF0 ... 0xF6
+#define TPS80031_ID1_PMC_BACKUP                        0xFA
+
+#define TPS80031_ID2_USB                       0x00 ... 0x1A
+#define TPS80031_ID2_GPADC_CONTROL             0x2E ... 0x36
+#define TPS80031_ID2_GPADC_RESULTS             0x37 ... 0x3C
+#define TPS80031_ID2_AUXILLIARIES              0x90 ... 0x9C
+#define TPS80031_ID2_CUSTOM                    0xA0 ... 0xB9
+#define TPS80031_ID2_PWM                       0xBA ... 0xBE
+#define TPS80031_ID2_FUEL_GAUSE                        0xC0 ... 0xCB
+#define TPS80031_ID2_INTERFACE_INTERRUPTS      0xD0 ... 0xD8
+#define TPS80031_ID2_CHARGER                   0xDA ... 0xF5
+
+#define TPS80031_ID3_TEST_LDO                  0x00 ... 0x09
+#define TPS80031_ID3_TEST_SMPS                 0x10 ... 0x2B
+#define TPS80031_ID3_TEST_POWER                        0x30 ... 0x36
+#define TPS80031_ID3_TEST_CHARGER              0x40 ... 0x48
+#define TPS80031_ID3_TEST_AUXILIIARIES         0x50 ... 0xB1
+
+#define TPS80031_ID3_DIEID                     0xC0 ... 0xC8
+#define TPS80031_ID3_TRIM_PHOENIX              0xCC ... 0xEA
+#define TPS80031_ID3_TRIM_CUSTOM               0xEC ... 0xED
+
+#define TPS80031_MAX_REGISTER  0x100
+
+struct tps80031_pupd_data {
+       u8      reg;
+       u8      pullup_bit;
+       u8      pulldown_bit;
+};
 
 static u8 pmc_ext_control_base[] = {
        REGEN1_BASE_ADD,
@@ -182,6 +234,31 @@ static const struct tps80031_irq_data tps80031_irqs[] = {
                                                MLINCH_GATED,   LINCH_GATED),
 };
 
+#define PUPD_DATA(_reg, _pulldown_bit, _pullup_bit)    \
+       {                                               \
+               .reg = TPS80031_CFG_INPUT_PUPD##_reg,   \
+               .pulldown_bit = _pulldown_bit,          \
+               .pullup_bit = _pullup_bit,              \
+       }
+
+static const struct tps80031_pupd_data tps80031_pupds[] = {
+       [TPS80031_PREQ1]                = PUPD_DATA(1, 1 << 0,  1 << 1  ),
+       [TPS80031_PREQ2A]               = PUPD_DATA(1, 1 << 2,  1 << 3  ),
+       [TPS80031_PREQ2B]               = PUPD_DATA(1, 1 << 4,  1 << 5  ),
+       [TPS80031_PREQ2C]               = PUPD_DATA(1, 1 << 6,  1 << 7  ),
+       [TPS80031_PREQ3]                = PUPD_DATA(2, 1 << 0,  1 << 1  ),
+       [TPS80031_NRES_WARM]            = PUPD_DATA(2, 0,       1 << 2  ),
+       [TPS80031_PWM_FORCE]            = PUPD_DATA(2, 1 << 5,  0       ),
+       [TPS80031_CHRG_EXT_CHRG_STATZ]  = PUPD_DATA(2, 0,       1 << 6  ),
+       [TPS80031_SIM]                  = PUPD_DATA(3, 1 << 0,  1 << 1  ),
+       [TPS80031_MMC]                  = PUPD_DATA(3, 1 << 2,  1 << 3  ),
+       [TPS80031_GPADC_START]          = PUPD_DATA(3, 1 << 4,  0       ),
+       [TPS80031_DVSI2C_SCL]           = PUPD_DATA(4, 0,       1 << 0  ),
+       [TPS80031_DVSI2C_SDA]           = PUPD_DATA(4, 0,       1 << 1  ),
+       [TPS80031_CTLI2C_SCL]           = PUPD_DATA(4, 0,       1 << 2  ),
+       [TPS80031_CTLI2C_SDA]           = PUPD_DATA(4, 0,       1 << 3  ),
+};
+
 static const int controller_stat1_irq_nr[] = {
        TPS80031_INT_BAT_TEMP_OVRANGE,
        TPS80031_INT_BAT_REMOVED,
@@ -217,159 +294,78 @@ struct tps80031 {
        u8                      cont_int_en;
        u8                      prev_cont_stat1;
        struct tps80031_client  tps_clients[TPS_NUM_SLAVES];
+       struct regmap           *regmap[TPS_NUM_SLAVES];
 };
 
-static inline int __tps80031_read(struct i2c_client *client,
-                                 int reg, uint8_t *val)
-{
-       int ret;
-
-       ret = i2c_smbus_read_byte_data(client, reg);
-       if (ret < 0) {
-               dev_err(&client->dev,
-                       "failed reading from addr 0x%02x, reg 0x%02x\n",
-                       client->addr, reg);
-               return ret;
-       }
-
-       *val = (uint8_t)ret;
-
-       return 0;
-}
-
-static inline int __tps80031_reads(struct i2c_client *client, int reg,
-                               int len, uint8_t *val)
-{
-       int ret;
-
-       ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
-       if (ret < 0) {
-               dev_err(&client->dev,
-                       "failed reading from addr 0x%02x, reg   0x%02x\n",
-                        client->addr, reg);
-               return ret;
-       }
-
-       return 0;
-}
-
-static inline int __tps80031_write(struct i2c_client *client,
-                                int reg, uint8_t val)
-{
-       int ret;
-       ret = i2c_smbus_write_byte_data(client, reg, val);
-       if (ret < 0) {
-               dev_err(&client->dev,
-                       "failed writing 0x%02x to 0x%02x\n", val, reg);
-               return ret;
-       }
-
-       return 0;
-}
-
-static inline int __tps80031_writes(struct i2c_client *client, int reg,
-                                 int len, uint8_t *val)
-{
-       int ret;
-
-       ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
-               return ret;
-       }
+/* TPS80031 sub mfd devices */
+static struct mfd_cell tps80031_cell[] = {
+       {
+               .name = "tps80031-regulators",
+       },
+       {
+               .name = "tps80031-rtc",
+       },
+       {
+               .name = "tps80031-battery-gauge",
+       },
+};
 
-       return 0;
-}
 
 int tps80031_write(struct device *dev, int sid, int reg, uint8_t val)
 {
        struct tps80031 *tps80031 = dev_get_drvdata(dev);
-       struct tps80031_client *tps = &tps80031->tps_clients[sid];
-       int ret;
 
-       mutex_lock(&tps->lock);
-       ret = __tps80031_write(tps->client, reg, val);
-       mutex_unlock(&tps->lock);
-
-       return ret;
+       return regmap_write(tps80031->regmap[sid], reg, val);
 }
 EXPORT_SYMBOL_GPL(tps80031_write);
 
 int tps80031_writes(struct device *dev, int sid, int reg, int len, uint8_t *val)
 {
        struct tps80031 *tps80031 = dev_get_drvdata(dev);
-       struct tps80031_client *tps = &tps80031->tps_clients[sid];
-       int ret;
-
-       mutex_lock(&tps->lock);
-       ret = __tps80031_writes(tps->client, reg, len, val);
-       mutex_unlock(&tps->lock);
 
-       return ret;
+       return regmap_bulk_write(tps80031->regmap[sid], reg, val, len);
 }
 EXPORT_SYMBOL_GPL(tps80031_writes);
 
 int tps80031_read(struct device *dev, int sid, int reg, uint8_t *val)
 {
        struct tps80031 *tps80031 = dev_get_drvdata(dev);
-       struct tps80031_client *tps = &tps80031->tps_clients[sid];
+       unsigned int ival;
+       int ret;
+
+       ret = regmap_read(tps80031->regmap[sid], reg, &ival);
+       if (ret < 0) {
+               dev_err(dev, "failed reading from reg 0x%02x\n", reg);
+               return ret;
+       }
 
-       return __tps80031_read(tps->client, reg, val);
+       *val = ival;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(tps80031_read);
 
 int tps80031_reads(struct device *dev, int sid, int reg, int len, uint8_t *val)
 {
        struct tps80031 *tps80031 = dev_get_drvdata(dev);
-       struct tps80031_client *tps = &tps80031->tps_clients[sid];
 
-       return __tps80031_reads(tps->client, reg, len, val);
+       return regmap_bulk_read(tps80031->regmap[sid], reg, val, len);
 }
 EXPORT_SYMBOL_GPL(tps80031_reads);
 
 int tps80031_set_bits(struct device *dev, int sid, int reg, uint8_t bit_mask)
 {
        struct tps80031 *tps80031 = dev_get_drvdata(dev);
-       struct tps80031_client *tps = &tps80031->tps_clients[sid];
-       uint8_t reg_val;
-       int ret = 0;
-
-       mutex_lock(&tps->lock);
 
-       ret = __tps80031_read(tps->client, reg, &reg_val);
-       if (ret)
-               goto out;
-
-       if ((reg_val & bit_mask) != bit_mask) {
-               reg_val |= bit_mask;
-               ret = __tps80031_write(tps->client, reg, reg_val);
-       }
-out:
-       mutex_unlock(&tps->lock);
-       return ret;
+       return regmap_update_bits(tps80031->regmap[sid], reg,
+                               bit_mask, bit_mask);
 }
 EXPORT_SYMBOL_GPL(tps80031_set_bits);
 
 int tps80031_clr_bits(struct device *dev, int sid, int reg, uint8_t bit_mask)
 {
        struct tps80031 *tps80031 = dev_get_drvdata(dev);
-       struct tps80031_client *tps = &tps80031->tps_clients[sid];
-       uint8_t reg_val;
-       int ret = 0;
-
-       mutex_lock(&tps->lock);
 
-       ret = __tps80031_read(tps->client, reg, &reg_val);
-       if (ret)
-               goto out;
-
-       if (reg_val & bit_mask) {
-               reg_val &= ~bit_mask;
-               ret = __tps80031_write(tps->client, reg, reg_val);
-       }
-out:
-       mutex_unlock(&tps->lock);
-       return ret;
+       return regmap_update_bits(tps80031->regmap[sid], reg, bit_mask, 0);
 }
 EXPORT_SYMBOL_GPL(tps80031_clr_bits);
 
@@ -377,23 +373,8 @@ int tps80031_update(struct device *dev, int sid, int reg, uint8_t val,
                uint8_t mask)
 {
        struct tps80031 *tps80031 = dev_get_drvdata(dev);
-       struct tps80031_client *tps = &tps80031->tps_clients[sid];
-       uint8_t reg_val;
-       int ret = 0;
 
-       mutex_lock(&tps->lock);
-
-       ret = __tps80031_read(tps->client, reg, &reg_val);
-       if (ret)
-               goto out;
-
-       if ((reg_val & mask) != val) {
-               reg_val = (reg_val & ~mask) | (val & mask);
-               ret = __tps80031_write(tps->client, reg, reg_val);
-       }
-out:
-       mutex_unlock(&tps->lock);
-       return ret;
+       return regmap_update_bits(tps80031->regmap[sid], reg, mask, val);
 }
 EXPORT_SYMBOL_GPL(tps80031_update);
 
@@ -407,12 +388,12 @@ int tps80031_force_update(struct device *dev, int sid, int reg, uint8_t val,
 
        mutex_lock(&tps->lock);
 
-       ret = __tps80031_read(tps->client, reg, &reg_val);
+       ret = tps80031_read(dev, sid, reg, &reg_val);
        if (ret)
                goto out;
 
        reg_val = (reg_val & ~mask) | (val & mask);
-       ret = __tps80031_write(tps->client, reg, reg_val);
+       ret = tps80031_write(dev, sid, reg, reg_val);
 
 out:
        mutex_unlock(&tps->lock);
@@ -498,14 +479,50 @@ int tps80031_get_pmu_version(struct device *dev)
 EXPORT_SYMBOL_GPL(tps80031_get_pmu_version);
 
 static struct tps80031 *tps80031_dev;
-int tps80031_power_off(void)
+static void tps80031_power_off(void)
 {
        struct tps80031_client *tps = &tps80031_dev->tps_clients[SLAVE_ID1];
 
        if (!tps->client)
-               return -EINVAL;
+               return;
        dev_info(&tps->client->dev, "switching off PMU\n");
-       return __tps80031_write(tps->client, TPS80031_PHOENIX_DEV_ON, DEVOFF);
+       tps80031_write(&tps->client->dev, SLAVE_ID1,
+                               TPS80031_PHOENIX_DEV_ON, DEVOFF);
+}
+
+static void tps80031_pupd_init(struct tps80031 *tps80031,
+                              struct tps80031_platform_data *pdata)
+{
+       struct tps80031_pupd_init_data *pupd_init_data = pdata->pupd_init_data;
+       int data_size = pdata->pupd_init_data_size;
+       int i;
+
+       for (i = 0; i < data_size; ++i) {
+               struct tps80031_pupd_init_data *pupd_init = &pupd_init_data[i];
+               const struct tps80031_pupd_data *pupd =
+                       &tps80031_pupds[pupd_init->input_pin];
+               u8 update_value = 0;
+               u8 update_mask = pupd->pulldown_bit | pupd->pullup_bit;
+
+               if (pupd_init->setting == TPS80031_PUPD_PULLDOWN)
+                       update_value = pupd->pulldown_bit;
+               else if (pupd_init->setting == TPS80031_PUPD_PULLUP)
+                       update_value = pupd->pullup_bit;
+
+               tps80031_update(tps80031->dev, SLAVE_ID1, pupd->reg,
+                               update_value, update_mask);
+       }
+}
+
+static void tps80031_backup_battery_charger_control(struct tps80031 *tps80031,
+                                                   int enable)
+{
+       if (enable)
+               tps80031_update(tps80031->dev, SLAVE_ID1, TPS80031_BBSPOR_CFG,
+                               TPS80031_BBSPOR_CHG_EN, TPS80031_BBSPOR_CHG_EN);
+       else
+               tps80031_update(tps80031->dev, SLAVE_ID1, TPS80031_BBSPOR_CFG,
+                               0, TPS80031_BBSPOR_CHG_EN);
 }
 
 static void tps80031_init_ext_control(struct tps80031 *tps80031,
@@ -515,7 +532,7 @@ static void tps80031_init_ext_control(struct tps80031 *tps80031,
 
        /* Clear all external control for this rail */
        for (i = 0; i < 9; ++i) {
-               tps80031_write(tps80031->dev, SLAVE_ID1,
+               ret = tps80031_write(tps80031->dev, SLAVE_ID1,
                                TPS80031_PREQ1_RES_ASS_A + i, 0);
                if (ret < 0)
                        dev_err(tps80031->dev, "%s() Error in clearing "
@@ -539,14 +556,14 @@ static int tps80031_gpio_get(struct gpio_chip *gc, unsigned offset)
        uint8_t trans;
        int ret;
 
-       ret = __tps80031_read(tps->client,
+       ret = tps80031_read(&tps->client->dev, SLAVE_ID1,
                        pmc_ext_control_base[offset] +
                                EXT_CONTROL_CFG_STATE, &state);
        if (ret)
                return ret;
 
        if (state != 0) {
-               ret = __tps80031_read(tps->client,
+               ret = tps80031_read(&tps->client->dev, SLAVE_ID1,
                                pmc_ext_control_base[offset] +
                                        EXT_CONTROL_CFG_TRANS, &trans);
                if (ret)
@@ -814,8 +831,22 @@ static irqreturn_t tps80031_irq(int irq, void *data)
        acks = (tmp[2] << 16) | (tmp[1] << 8) | tmp[0];
 
        if (acks) {
-               ret = tps80031_writes(tps80031->dev, SLAVE_ID2,
-                                     TPS80031_INT_STS_A, 3, tmp);
+               /*
+                * Hardware behavior: hardware have the shadow register for
+                * interrupt status register which is updated if interrupt
+                * comes just after the interrupt status read. This shadow
+                * register gets written to main status register and cleared
+                * if any byte write happens in any of status register like
+                * STS_A, STS_B or STS_C.
+                * Hence here to clear the original interrupt status and
+                * updating the STS register with the shadow register, it is
+                * require to write only one byte in any of STS register.
+                * Having multiple register write can cause the STS register
+                * to clear without handling those interrupt and can cause
+                * interrupt miss.
+                */
+               ret = tps80031_write(tps80031->dev, SLAVE_ID2,
+                                     TPS80031_INT_STS_A, 0);
                if (ret < 0) {
                        dev_err(tps80031->dev, "failed to write "
                                                "interrupt status\n");
@@ -1027,7 +1058,7 @@ static void print_regs(const char *header, struct seq_file *s,
 
        seq_printf(s, "%s\n", header);
        for (i = start_offset; i <= end_offset; ++i) {
-               ret = __tps80031_read(tps->client, i, &reg_val);
+               ret = tps80031_read(&tps->client->dev, sid, i, &reg_val);
                if (ret >= 0)
                        seq_printf(s, "Addr = 0x%02x Reg 0x%02x Value 0x%02x\n",
                                                tps->client->addr, i, reg_val);
@@ -1101,11 +1132,116 @@ static void __init tps80031_debuginit(struct tps80031 *tpsi)
 }
 #endif
 
+static bool rd_wr_reg_id0(struct device *dev, unsigned int reg)
+{
+       switch(reg) {
+       case TPS80031_ID0_PMIC_SLAVE_SMPS_DVS:
+               return true;
+       default:
+               pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+               BUG();
+               return false;
+       }
+}
+
+static bool rd_wr_reg_id1(struct device *dev, unsigned int reg)
+{
+       switch(reg) {
+       case TPS80031_ID1_RTC:
+       case TPS80031_ID1_MEMORY:
+       case TPS80031_ID1_PMC_MASTER:
+       case TPS80031_ID1_PMC_SLAVE_SMPS:
+       case TPS80031_ID1_PMC_SLAVE_MISC:
+       case TPS80031_ID1_PMC_SLAVE_LDO:
+       case TPS80031_ID1_PMC_SLAVE_REOSURCES:
+       case TPS80031_ID1_PMC_PREQ_ASSIGN:
+       case TPS80031_ID1_PMC_MISC:
+       case TPS80031_ID1_PMC_PU_PD_HZ:
+       case TPS80031_ID1_PMC_BACKUP:
+               return true;
+       default:
+               pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+               BUG();
+               return false;
+       }
+}
+
+static bool rd_wr_reg_id2(struct device *dev, unsigned int reg)
+{
+       switch(reg) {
+       case TPS80031_ID2_USB:
+       case TPS80031_ID2_GPADC_CONTROL:
+       case TPS80031_ID2_GPADC_RESULTS:
+       case TPS80031_ID2_AUXILLIARIES:
+       case TPS80031_ID2_CUSTOM:
+       case TPS80031_ID2_PWM:
+       case TPS80031_ID2_FUEL_GAUSE:
+       case TPS80031_ID2_INTERFACE_INTERRUPTS:
+       case TPS80031_ID2_CHARGER:
+               return true;
+       default:
+               pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+               BUG();
+               return false;
+       }
+}
+static bool rd_wr_reg_id3(struct device *dev, unsigned int reg)
+{
+       switch(reg) {
+       case TPS80031_ID3_TEST_LDO:
+       case TPS80031_ID3_TEST_SMPS:
+       case TPS80031_ID3_TEST_POWER:
+       case TPS80031_ID3_TEST_CHARGER:
+       case TPS80031_ID3_TEST_AUXILIIARIES:
+       case TPS80031_ID3_DIEID:
+       case TPS80031_ID3_TRIM_PHOENIX:
+       case TPS80031_ID3_TRIM_CUSTOM:
+               return true;
+       default:
+               pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+               BUG();
+               return false;
+       }
+}
+
+static const struct regmap_config tps80031_regmap_configs[] = {
+       {
+               .reg_bits = 8,
+               .val_bits = 8,
+               .writeable_reg = rd_wr_reg_id0,
+               .readable_reg = rd_wr_reg_id0,
+               .max_register = TPS80031_MAX_REGISTER - 1,
+       },
+       {
+               .reg_bits = 8,
+               .val_bits = 8,
+               .writeable_reg = rd_wr_reg_id1,
+               .readable_reg = rd_wr_reg_id1,
+               .max_register = TPS80031_MAX_REGISTER - 1,
+       },
+       {
+               .reg_bits = 8,
+               .val_bits = 8,
+               .writeable_reg = rd_wr_reg_id2,
+               .readable_reg = rd_wr_reg_id2,
+               .max_register = TPS80031_MAX_REGISTER - 1,
+       },
+       {
+               .reg_bits = 8,
+               .val_bits = 8,
+               .writeable_reg = rd_wr_reg_id3,
+               .readable_reg = rd_wr_reg_id3,
+               .max_register = TPS80031_MAX_REGISTER - 1,
+       },
+};
+
 static int __devexit tps80031_i2c_remove(struct i2c_client *client)
 {
        struct tps80031 *tps80031 = i2c_get_clientdata(client);
        int i;
 
+       mfd_remove_devices(tps80031->dev);
+
        if (client->irq)
                free_irq(client->irq, tps80031);
 
@@ -1121,7 +1257,6 @@ static int __devexit tps80031_i2c_remove(struct i2c_client *client)
                mutex_destroy(&tps->lock);
        }
 
-       kfree(tps80031);
        return 0;
 }
 
@@ -1158,9 +1293,11 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
        dev_info(&client->dev, "Jtag version 0x%02x and Eeprom version 0x%02x\n",
                                                jtag_ver, ep_ver);
 
-       tps80031 = kzalloc(sizeof(struct tps80031), GFP_KERNEL);
-       if (tps80031 == NULL)
+       tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL);
+       if (!tps80031) {
+               dev_err(&client->dev, "Memory alloc for tps80031 failed\n");
                return -ENOMEM;
+       }
 
        tps80031->es_version = jtag_ver;
        tps80031->dev = &client->dev;
@@ -1182,10 +1319,19 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
                if (!tps->client) {
                        dev_err(&client->dev, "can't attach client %d\n", i);
                        ret = -ENOMEM;
-                       goto fail;
+                       goto fail_client_reg;
                }
                i2c_set_clientdata(tps->client, tps80031);
                mutex_init(&tps->lock);
+
+               tps80031->regmap[i] = devm_regmap_init_i2c(tps->client,
+                                       &tps80031_regmap_configs[i]);
+               if (IS_ERR(tps80031->regmap[i])) {
+                       ret = PTR_ERR(tps80031->regmap[i]);
+                       dev_err(&client->dev,
+                               "regmap %d init failed, err %d\n", i, ret);
+                       goto fail_client_reg;
+               }
        }
 
        if (client->irq) {
@@ -1193,15 +1339,25 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
                                        pdata->irq_base);
                if (ret) {
                        dev_err(&client->dev, "IRQ init failed: %d\n", ret);
-                       goto fail;
+                       goto fail_client_reg;
                }
        }
+
+       tps80031_pupd_init(tps80031, pdata);
+
        tps80031_init_ext_control(tps80031, pdata);
 
+       ret = mfd_add_devices(tps80031->dev, -1,
+                       tps80031_cell, ARRAY_SIZE(tps80031_cell), NULL, 0);
+       if (ret < 0) {
+               dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
+               goto fail_mfd_add;
+       }
+
        ret = tps80031_add_subdevs(tps80031, pdata);
        if (ret) {
                dev_err(&client->dev, "add devices failed: %d\n", ret);
-               goto fail;
+               goto fail_add_subdev;
        }
 
        tps80031_gpio_init(tps80031, pdata);
@@ -1210,29 +1366,59 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
 
        tps80031_debuginit(tps80031);
 
+       tps80031_backup_battery_charger_control(tps80031, 1);
+
+       if (pdata->use_power_off && !pm_power_off)
+               pm_power_off = tps80031_power_off;
+
        tps80031_dev = tps80031;
 
        return 0;
 
-fail:
-       tps80031_i2c_remove(client);
+fail_add_subdev:
+       mfd_remove_devices(tps80031->dev);
+
+fail_mfd_add:
+       if (client->irq)
+               free_irq(client->irq, tps80031);
+fail_client_reg:
+       for (i = 0; i < TPS_NUM_SLAVES; i++) {
+               struct tps80031_client *tps = &tps80031->tps_clients[i];
+               if (tps->client && tps->client != client)
+                       i2c_unregister_device(tps->client);
+               tps80031->tps_clients[i].client = NULL;
+               mutex_destroy(&tps->lock);
+       }
        return ret;
 }
 
 #ifdef CONFIG_PM
-static int tps80031_i2c_suspend(struct i2c_client *client, pm_message_t state)
+static int tps80031_i2c_suspend(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
+       struct tps80031 *tps80031 = i2c_get_clientdata(client);
        if (client->irq)
                disable_irq(client->irq);
+       tps80031_backup_battery_charger_control(tps80031, 0);
        return 0;
 }
 
-static int tps80031_i2c_resume(struct i2c_client *client)
+static int tps80031_i2c_resume(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
+       struct tps80031 *tps80031 = i2c_get_clientdata(client);
+       tps80031_backup_battery_charger_control(tps80031, 1);
        if (client->irq)
                enable_irq(client->irq);
        return 0;
 }
+static const struct dev_pm_ops tps80031_dev_pm_ops = {
+       .suspend        = tps80031_i2c_suspend,
+       .resume         = tps80031_i2c_resume,
+};
+#define TPS80031_DEV_PM (&tps80031_dev_pm_ops)
+#else
+#define TPS80031_DEV_PM NULL
 #endif
 
 
@@ -1246,13 +1432,10 @@ static struct i2c_driver tps80031_driver = {
        .driver = {
                .name   = "tps80031",
                .owner  = THIS_MODULE,
+               .pm     = TPS80031_DEV_PM,
        },
        .probe          = tps80031_i2c_probe,
        .remove         = __devexit_p(tps80031_i2c_remove),
-#ifdef CONFIG_PM
-       .suspend        = tps80031_i2c_suspend,
-       .resume         = tps80031_i2c_resume,
-#endif
        .id_table       = tps80031_id_table,
 };