mfd: Add phoenix lite (twl6025) support to twl6030
[pandora-kernel.git] / drivers / mfd / twl-core.c
index 2bd9e06..b8f2a4e 100644 (file)
 #define TWL6030_BASEADD_GASGAUGE       0x00C0
 #define TWL6030_BASEADD_PIH            0x00D0
 #define TWL6030_BASEADD_CHARGER                0x00E0
+#define TWL6025_BASEADD_CHARGER                0x00DA
 
 /* subchip/slave 2 0x4A - DFT */
 #define TWL6030_BASEADD_DIEID          0x00C0
@@ -331,6 +332,7 @@ static struct twl_mapping twl6030_map[] = {
 
        { SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
        { SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
+       { SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER },
 };
 
 /*----------------------------------------------------------------------*/
@@ -604,7 +606,7 @@ static inline struct device *add_child(unsigned chip, const char *name,
 static struct device *
 add_regulator_linked(int num, struct regulator_init_data *pdata,
                struct regulator_consumer_supply *consumers,
-               unsigned num_consumers)
+               unsigned num_consumers, unsigned long features)
 {
        unsigned sub_chip_id;
        /* regulator framework demands init_data ... */
@@ -616,6 +618,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
                pdata->num_consumer_supplies = num_consumers;
        }
 
+       pdata->driver_data = (void *)features;
+
        /* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
        sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
        return add_numbered_child(sub_chip_id, "twl_reg", num,
@@ -623,9 +627,10 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
 }
 
 static struct device *
-add_regulator(int num, struct regulator_init_data *pdata)
+add_regulator(int num, struct regulator_init_data *pdata,
+               unsigned long features)
 {
-       return add_regulator_linked(num, pdata, NULL, 0);
+       return add_regulator_linked(num, pdata, NULL, 0, features);
 }
 
 /*
@@ -705,17 +710,20 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                        };
 
                        child = add_regulator_linked(TWL4030_REG_VUSB1V5,
-                                                     &usb_fixed, &usb1v5, 1);
+                                                     &usb_fixed, &usb1v5, 1,
+                                                     features);
                        if (IS_ERR(child))
                                return PTR_ERR(child);
 
                        child = add_regulator_linked(TWL4030_REG_VUSB1V8,
-                                                     &usb_fixed, &usb1v8, 1);
+                                                     &usb_fixed, &usb1v8, 1,
+                                                     features);
                        if (IS_ERR(child))
                                return PTR_ERR(child);
 
                        child = add_regulator_linked(TWL4030_REG_VUSB3V1,
-                                                     &usb_fixed, &usb3v1, 1);
+                                                     &usb_fixed, &usb3v1, 1,
+                                                     features);
                        if (IS_ERR(child))
                                return PTR_ERR(child);
 
@@ -740,9 +748,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        }
        if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
 
-               static struct regulator_consumer_supply usb3v3 = {
-                       .supply =       "vusb",
-               };
+               static struct regulator_consumer_supply usb3v3;
+               int regulator;
 
                if (twl_has_regulator()) {
                        /* this is a template that gets copied */
@@ -755,12 +762,22 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                                        | REGULATOR_CHANGE_STATUS,
                        };
 
-                       child = add_regulator_linked(TWL6030_REG_VUSB,
-                                                     &usb_fixed, &usb3v3, 1);
+                       if (features & TWL6025_SUBCLASS) {
+                               usb3v3.supply = "ldousb";
+                               regulator = TWL6025_REG_LDOUSB;
+                       } else {
+                               usb3v3.supply = "vusb";
+                               regulator = TWL6030_REG_VUSB;
+                       }
+                       child = add_regulator_linked(regulator, &usb_fixed,
+                                                       &usb3v3, 1,
+                                                       features);
                        if (IS_ERR(child))
                                return PTR_ERR(child);
                }
 
+               pdata->usb->features = features;
+
                child = add_child(0, "twl6030_usb",
                        pdata->usb, sizeof(*pdata->usb),
                        true,
@@ -773,7 +790,16 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
                /* we need to connect regulators to this transceiver */
                if (twl_has_regulator() && child)
                        usb3v3.dev = child;
+       } else if (twl_has_regulator() && twl_class_is_6030()) {
+               if (features & TWL6025_SUBCLASS)
+                       child = add_regulator(TWL6025_REG_LDOUSB,
+                                               pdata->ldousb, features);
+               else
+                       child = add_regulator(TWL6030_REG_VUSB,
+                                               pdata->vusb, features);
 
+                       if (IS_ERR(child))
+                                       return PTR_ERR(child);
        }
 
        if (twl_has_watchdog() && twl_class_is_4030()) {
@@ -810,46 +836,55 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
 
        /* twl4030 regulators */
        if (twl_has_regulator() && twl_class_is_4030()) {
-               child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
+               child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VIO, pdata->vio);
+               child = add_regulator(TWL4030_REG_VIO, pdata->vio,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1);
+               child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2);
+               child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1);
+               child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VDAC, pdata->vdac);
+               child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
                child = add_regulator((features & TWL4030_VAUX2)
                                        ? TWL4030_REG_VAUX2_4030
                                        : TWL4030_REG_VAUX2,
-                               pdata->vaux2);
+                               pdata->vaux2, features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1);
+               child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2);
+               child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig);
+               child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
@@ -857,72 +892,152 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
        /* maybe add LDOs that are omitted on cost-reduced parts */
        if (twl_has_regulator() && !(features & TPS_SUBSET)
          && twl_class_is_4030()) {
-               child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
+               child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2);
+               child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VSIM, pdata->vsim);
+               child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1);
+               child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3);
+               child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4);
+               child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
 
        /* twl6030 regulators */
+       if (twl_has_regulator() && twl_class_is_6030() &&
+                       !(features & TWL6025_SUBCLASS)) {
+               child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
+               child = add_regulator(TWL6030_REG_VPP, pdata->vpp,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
+               child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
+               child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
+               child = add_regulator(TWL6030_REG_VDAC, pdata->vdac,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
+               child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
+               child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
+               child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
+               child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+       }
+
+       /* 6030 and 6025 share this regulator */
        if (twl_has_regulator() && twl_class_is_6030()) {
-               child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc);
+               child = add_regulator(TWL6030_REG_VANA, pdata->vana,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+       }
+
+       /* twl6025 regulators */
+       if (twl_has_regulator() && twl_class_is_6030() &&
+                       (features & TWL6025_SUBCLASS)) {
+               child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_VPP, pdata->vpp);
+               child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim);
+               child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_VANA, pdata->vana);
+               child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio);
+               child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_VDAC, pdata->vdac);
+               child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1);
+               child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2);
+               child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3);
+               child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
 
-               child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg);
+               child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4,
+                                       features);
                if (IS_ERR(child))
                        return PTR_ERR(child);
+
+               child = add_regulator(TWL6025_REG_VIO, pdata->vio6025,
+                                       features);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+
        }
 
        if (twl_has_bci() && pdata->bci &&
@@ -1170,6 +1285,7 @@ static const struct i2c_device_id twl_ids[] = {
        { "tps65930", TPS_SUBSET },     /* fewer LDOs and DACs; no charger */
        { "tps65920", TPS_SUBSET },     /* fewer LDOs; no codec or charger */
        { "twl6030", TWL6030_CLASS },   /* "Phoenix power chip" */
+       { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
        { /* end of list */ },
 };
 MODULE_DEVICE_TABLE(i2c, twl_ids);