Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / arch / arm / mach-omap2 / mmc-twl4030.c
index 3c04c2f..c9c59a2 100644 (file)
@@ -198,6 +198,18 @@ static int twl_mmc_resume(struct device *dev, int slot)
 #define twl_mmc_resume NULL
 #endif
 
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
+
+static int twl4030_mmc_get_context_loss(struct device *dev)
+{
+       /* FIXME: PM DPS not implemented yet */
+       return 0;
+}
+
+#else
+#define twl4030_mmc_get_context_loss NULL
+#endif
+
 static int twl_mmc1_set_power(struct device *dev, int slot, int power_on,
                                int vdd)
 {
@@ -328,6 +340,61 @@ static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int v
        return ret;
 }
 
+static int twl_mmc1_set_sleep(struct device *dev, int slot, int sleep, int vdd,
+                             int cardsleep)
+{
+       struct twl_mmc_controller *c = &hsmmc[0];
+       int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
+
+       return regulator_set_mode(c->vcc, mode);
+}
+
+static int twl_mmc23_set_sleep(struct device *dev, int slot, int sleep, int vdd,
+                              int cardsleep)
+{
+       struct twl_mmc_controller *c = NULL;
+       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       int i, err, mode;
+
+       for (i = 1; i < ARRAY_SIZE(hsmmc); i++) {
+               if (mmc == hsmmc[i].mmc) {
+                       c = &hsmmc[i];
+                       break;
+               }
+       }
+
+       if (c == NULL)
+               return -ENODEV;
+
+       /*
+        * If we don't see a Vcc regulator, assume it's a fixed
+        * voltage always-on regulator.
+        */
+       if (!c->vcc)
+               return 0;
+
+       mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
+
+       if (!c->vcc_aux)
+               return regulator_set_mode(c->vcc, mode);
+
+       if (cardsleep) {
+               /* VCC can be turned off if card is asleep */
+               struct regulator *vcc_aux = c->vcc_aux;
+
+               c->vcc_aux = NULL;
+               if (sleep)
+                       err = twl_mmc23_set_power(dev, slot, 0, 0);
+               else
+                       err = twl_mmc23_set_power(dev, slot, 1, vdd);
+               c->vcc_aux = vcc_aux;
+       } else
+               err = regulator_set_mode(c->vcc, mode);
+       if (err)
+               return err;
+       return regulator_set_mode(c->vcc_aux, mode);
+}
+
 static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
 
 void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
@@ -390,6 +457,9 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
                } else
                        mmc->slots[0].switch_pin = -EINVAL;
 
+               mmc->get_context_loss_count =
+                               twl4030_mmc_get_context_loss;
+
                /* write protect normally uses an OMAP gpio */
                if (gpio_is_valid(c->gpio_wp)) {
                        gpio_request(c->gpio_wp, "mmc_wp");
@@ -400,6 +470,12 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
                } else
                        mmc->slots[0].gpio_wp = -EINVAL;
 
+               if (c->nonremovable)
+                       mmc->slots[0].nonremovable = 1;
+
+               if (c->power_saving)
+                       mmc->slots[0].power_saving = 1;
+
                /* NOTE:  MMC slots should have a Vcc regulator set up.
                 * This may be from a TWL4030-family chip, another
                 * controllable regulator, or a fixed supply.
@@ -412,6 +488,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
                case 1:
                        /* on-chip level shifting via PBIAS0/PBIAS1 */
                        mmc->slots[0].set_power = twl_mmc1_set_power;
+                       mmc->slots[0].set_sleep = twl_mmc1_set_sleep;
                        break;
                case 2:
                        if (c->ext_clock)
@@ -422,6 +499,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
                case 3:
                        /* off-chip level shifting, or none */
                        mmc->slots[0].set_power = twl_mmc23_set_power;
+                       mmc->slots[0].set_sleep = twl_mmc23_set_sleep;
                        break;
                default:
                        pr_err("MMC%d configuration not supported!\n", c->mmc);