Revert "regulator: Move VCOINCELL to be the last element of mc13892_regulators array"
[pandora-kernel.git] / drivers / regulator / twl-regulator.c
index 6a29285..2a808c2 100644 (file)
@@ -76,6 +76,17 @@ struct twlreg_info {
 #define VREG_BC_PROC           3
 #define VREG_BC_CLK_RST                4
 
+/* TWL6030 LDO register values for CFG_STATE */
+#define TWL6030_CFG_STATE_OFF  0x00
+#define TWL6030_CFG_STATE_ON   0x01
+#define TWL6030_CFG_STATE_OFF2 0x02
+#define TWL6030_CFG_STATE_SLEEP        0x03
+#define TWL6030_CFG_STATE_GRP_SHIFT    5
+#define TWL6030_CFG_STATE_APP_SHIFT    2
+#define TWL6030_CFG_STATE_APP_MASK     (0x03 << TWL6030_CFG_STATE_APP_SHIFT)
+#define TWL6030_CFG_STATE_APP(v)       (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
+                                               TWL6030_CFG_STATE_APP_SHIFT)
+
 static inline int
 twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
 {
@@ -118,18 +129,31 @@ static int twlreg_grp(struct regulator_dev *rdev)
 #define P2_GRP_6030    BIT(1)          /* "peripherals" */
 #define P1_GRP_6030    BIT(0)          /* CPU/Linux */
 
-static int twlreg_is_enabled(struct regulator_dev *rdev)
+static int twl4030reg_is_enabled(struct regulator_dev *rdev)
 {
        int     state = twlreg_grp(rdev);
 
        if (state < 0)
                return state;
 
-       if (twl_class_is_4030())
-               state &= P1_GRP_4030;
-       else
-               state &= P1_GRP_6030;
-       return state;
+       return state & P1_GRP_4030;
+}
+
+static int twl6030reg_is_enabled(struct regulator_dev *rdev)
+{
+       struct twlreg_info      *info = rdev_get_drvdata(rdev);
+       int                     grp, val;
+
+       grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+       if (grp < 0)
+               return grp;
+
+       grp &= P1_GRP_6030;
+
+       val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
+       val = TWL6030_CFG_STATE_APP(val);
+
+       return grp && (val == TWL6030_CFG_STATE_ON);
 }
 
 static int twlreg_enable(struct regulator_dev *rdev)
@@ -149,6 +173,11 @@ static int twlreg_enable(struct regulator_dev *rdev)
 
        ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
 
+       if (!ret && twl_class_is_6030())
+               ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+                               grp << TWL6030_CFG_STATE_GRP_SHIFT |
+                               TWL6030_CFG_STATE_ON);
+
        udelay(info->delay);
 
        return ret;
@@ -158,26 +187,42 @@ static int twlreg_disable(struct regulator_dev *rdev)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
        int                     grp;
+       int                     ret;
 
        grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
        if (grp < 0)
                return grp;
 
+       /* For 6030, set the off state for all grps enabled */
+       if (twl_class_is_6030()) {
+               ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+                       (grp & (P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030)) <<
+                               TWL6030_CFG_STATE_GRP_SHIFT |
+                       TWL6030_CFG_STATE_OFF);
+               if (ret)
+                       return ret;
+       }
+
        if (twl_class_is_4030())
                grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030);
        else
                grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030);
 
-       return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
+       ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
+
+       /* Next, associate cleared grp in state register */
+       if (!ret && twl_class_is_6030())
+               ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
+                               grp << TWL6030_CFG_STATE_GRP_SHIFT |
+                               TWL6030_CFG_STATE_OFF);
+
+       return ret;
 }
 
-static int twlreg_get_status(struct regulator_dev *rdev)
+static int twl4030reg_get_status(struct regulator_dev *rdev)
 {
        int     state = twlreg_grp(rdev);
 
-       if (twl_class_is_6030())
-               return 0; /* FIXME return for 6030 regulator */
-
        if (state < 0)
                return state;
        state &= 0x0f;
@@ -190,15 +235,39 @@ static int twlreg_get_status(struct regulator_dev *rdev)
                : REGULATOR_STATUS_STANDBY;
 }
 
-static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode)
+static int twl6030reg_get_status(struct regulator_dev *rdev)
+{
+       struct twlreg_info      *info = rdev_get_drvdata(rdev);
+       int                     val;
+
+       val = twlreg_grp(rdev);
+       if (val < 0)
+               return val;
+
+       val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
+
+       switch (TWL6030_CFG_STATE_APP(val)) {
+       case TWL6030_CFG_STATE_ON:
+               return REGULATOR_STATUS_NORMAL;
+
+       case TWL6030_CFG_STATE_SLEEP:
+               return REGULATOR_STATUS_STANDBY;
+
+       case TWL6030_CFG_STATE_OFF:
+       case TWL6030_CFG_STATE_OFF2:
+       default:
+               break;
+       }
+
+       return REGULATOR_STATUS_OFF;
+}
+
+static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
        unsigned                message;
        int                     status;
 
-       if (twl_class_is_6030())
-               return 0; /* FIXME return for 6030 regulator */
-
        /* We can only set the mode through state machine commands... */
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
@@ -227,6 +296,35 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode)
                        message & 0xff, TWL4030_PM_MASTER_PB_WORD_LSB);
 }
 
+static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
+{
+       struct twlreg_info      *info = rdev_get_drvdata(rdev);
+       int grp;
+       int val;
+
+       grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+
+       if (grp < 0)
+               return grp;
+
+       /* Compose the state register settings */
+       val = grp << TWL6030_CFG_STATE_GRP_SHIFT;
+       /* We can only set the mode through state machine commands... */
+       switch (mode) {
+       case REGULATOR_MODE_NORMAL:
+               val |= TWL6030_CFG_STATE_ON;
+               break;
+       case REGULATOR_MODE_STANDBY:
+               val |= TWL6030_CFG_STATE_SLEEP;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, val);
+}
+
 /*----------------------------------------------------------------------*/
 
 /*
@@ -377,11 +475,11 @@ static struct regulator_ops twl4030ldo_ops = {
 
        .enable         = twlreg_enable,
        .disable        = twlreg_disable,
-       .is_enabled     = twlreg_is_enabled,
+       .is_enabled     = twl4030reg_is_enabled,
 
-       .set_mode       = twlreg_set_mode,
+       .set_mode       = twl4030reg_set_mode,
 
-       .get_status     = twlreg_get_status,
+       .get_status     = twl4030reg_get_status,
 };
 
 static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
@@ -435,11 +533,11 @@ static struct regulator_ops twl6030ldo_ops = {
 
        .enable         = twlreg_enable,
        .disable        = twlreg_disable,
-       .is_enabled     = twlreg_is_enabled,
+       .is_enabled     = twl6030reg_is_enabled,
 
-       .set_mode       = twlreg_set_mode,
+       .set_mode       = twl6030reg_set_mode,
 
-       .get_status     = twlreg_get_status,
+       .get_status     = twl6030reg_get_status,
 };
 
 /*----------------------------------------------------------------------*/
@@ -461,25 +559,39 @@ static int twlfixed_get_voltage(struct regulator_dev *rdev)
        return info->min_mV * 1000;
 }
 
-static struct regulator_ops twlfixed_ops = {
+static struct regulator_ops twl4030fixed_ops = {
+       .list_voltage   = twlfixed_list_voltage,
+
+       .get_voltage    = twlfixed_get_voltage,
+
+       .enable         = twlreg_enable,
+       .disable        = twlreg_disable,
+       .is_enabled     = twl4030reg_is_enabled,
+
+       .set_mode       = twl4030reg_set_mode,
+
+       .get_status     = twl4030reg_get_status,
+};
+
+static struct regulator_ops twl6030fixed_ops = {
        .list_voltage   = twlfixed_list_voltage,
 
        .get_voltage    = twlfixed_get_voltage,
 
        .enable         = twlreg_enable,
        .disable        = twlreg_disable,
-       .is_enabled     = twlreg_is_enabled,
+       .is_enabled     = twl6030reg_is_enabled,
 
-       .set_mode       = twlreg_set_mode,
+       .set_mode       = twl6030reg_set_mode,
 
-       .get_status     = twlreg_get_status,
+       .get_status     = twl6030reg_get_status,
 };
 
 static struct regulator_ops twl6030_fixed_resource = {
        .enable         = twlreg_enable,
        .disable        = twlreg_disable,
-       .is_enabled     = twlreg_is_enabled,
-       .get_status     = twlreg_get_status,
+       .is_enabled     = twl6030reg_is_enabled,
+       .get_status     = twl6030reg_get_status,
 };
 
 /*----------------------------------------------------------------------*/
@@ -487,11 +599,10 @@ static struct regulator_ops twl6030_fixed_resource = {
 #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
                        remap_conf) \
                TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
-                       remap_conf, TWL4030)
-#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
-                       remap_conf) \
+                       remap_conf, TWL4030, twl4030fixed_ops)
+#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \
                TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
-                       remap_conf, TWL6030)
+                       0x0, TWL6030, twl6030fixed_ops)
 
 #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \
        .base = offset, \
@@ -510,13 +621,11 @@ static struct regulator_ops twl6030_fixed_resource = {
                }, \
        }
 
-#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num, \
-               remap_conf) { \
+#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
        .base = offset, \
        .id = num, \
        .min_mV = min_mVolts, \
        .max_mV = max_mVolts, \
-       .remap = remap_conf, \
        .desc = { \
                .name = #label, \
                .id = TWL6030_REG_##label, \
@@ -529,7 +638,7 @@ static struct regulator_ops twl6030_fixed_resource = {
 
 
 #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
-               family) { \
+               family, operations) { \
        .base = offset, \
        .id = num, \
        .min_mV = mVolts, \
@@ -539,17 +648,16 @@ static struct regulator_ops twl6030_fixed_resource = {
                .name = #label, \
                .id = family##_REG_##label, \
                .n_voltages = 1, \
-               .ops = &twlfixed_ops, \
+               .ops = &operations, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
                }, \
        }
 
-#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay, remap_conf) { \
+#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \
        .base = offset, \
        .id = num, \
        .delay = turnon_delay, \
-       .remap = remap_conf, \
        .desc = { \
                .name = #label, \
                .id = TWL6030_REG_##label, \
@@ -589,17 +697,17 @@ static struct twlreg_info twl_regs[] = {
        /* 6030 REG with base as PMC Slave Misc : 0x0030 */
        /* Turnon-delay and remap configuration values for 6030 are not
           verified since the specification is not public */
-       TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1, 0x21),
-       TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2, 0x21),
-       TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3, 0x21),
-       TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4, 0x21),
-       TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5, 0x21),
-       TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7, 0x21),
-       TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21),
-       TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21),
-       TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21),
-       TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21),
-       TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0, 0x21),
+       TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1),
+       TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2),
+       TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3),
+       TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4),
+       TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5),
+       TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7),
+       TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0),
+       TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0),
+       TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0),
+       TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0),
+       TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0),
 };
 
 static int __devinit twlreg_probe(struct platform_device *pdev)
@@ -653,7 +761,8 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
        }
        platform_set_drvdata(pdev, rdev);
 
-       twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP,
+       if (twl_class_is_4030())
+               twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP,
                                                info->remap);
 
        /* NOTE:  many regulators support short-circuit IRQs (presentable