|
@@ -62,6 +62,7 @@ static unsigned int fmax = 515633;
|
|
|
* @signal_direction: input/out direction of bus signals can be indicated
|
|
|
* @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
|
|
|
* @busy_detect: true if busy detection on dat0 is supported
|
|
|
+ * @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
|
|
|
*/
|
|
|
struct variant_data {
|
|
|
unsigned int clkreg;
|
|
@@ -76,6 +77,7 @@ struct variant_data {
|
|
|
bool signal_direction;
|
|
|
bool pwrreg_clkgate;
|
|
|
bool busy_detect;
|
|
|
+ bool pwrreg_nopower;
|
|
|
};
|
|
|
|
|
|
static struct variant_data variant_arm = {
|
|
@@ -109,6 +111,7 @@ static struct variant_data variant_u300 = {
|
|
|
.pwrreg_powerup = MCI_PWR_ON,
|
|
|
.signal_direction = true,
|
|
|
.pwrreg_clkgate = true,
|
|
|
+ .pwrreg_nopower = true,
|
|
|
};
|
|
|
|
|
|
static struct variant_data variant_nomadik = {
|
|
@@ -121,6 +124,7 @@ static struct variant_data variant_nomadik = {
|
|
|
.pwrreg_powerup = MCI_PWR_ON,
|
|
|
.signal_direction = true,
|
|
|
.pwrreg_clkgate = true,
|
|
|
+ .pwrreg_nopower = true,
|
|
|
};
|
|
|
|
|
|
static struct variant_data variant_ux500 = {
|
|
@@ -135,6 +139,7 @@ static struct variant_data variant_ux500 = {
|
|
|
.signal_direction = true,
|
|
|
.pwrreg_clkgate = true,
|
|
|
.busy_detect = true,
|
|
|
+ .pwrreg_nopower = true,
|
|
|
};
|
|
|
|
|
|
static struct variant_data variant_ux500v2 = {
|
|
@@ -150,6 +155,7 @@ static struct variant_data variant_ux500v2 = {
|
|
|
.signal_direction = true,
|
|
|
.pwrreg_clkgate = true,
|
|
|
.busy_detect = true,
|
|
|
+ .pwrreg_nopower = true,
|
|
|
};
|
|
|
|
|
|
static int mmci_card_busy(struct mmc_host *mmc)
|
|
@@ -189,6 +195,21 @@ static int mmci_validate_data(struct mmci_host *host,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void mmci_reg_delay(struct mmci_host *host)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * According to the spec, at least three feedback clock cycles
|
|
|
+ * of max 52 MHz must pass between two writes to the MMCICLOCK reg.
|
|
|
+ * Three MCLK clock cycles must pass between two MMCIPOWER reg writes.
|
|
|
+ * Worst delay time during card init is at 100 kHz => 30 us.
|
|
|
+ * Worst delay time when up and running is at 25 MHz => 120 ns.
|
|
|
+ */
|
|
|
+ if (host->cclk < 25000000)
|
|
|
+ udelay(30);
|
|
|
+ else
|
|
|
+ ndelay(120);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* This must be called with host->lock held
|
|
|
*/
|
|
@@ -1264,6 +1285,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|
|
|
|
|
mmci_set_clkreg(host, ios->clock);
|
|
|
mmci_write_pwrreg(host, pwr);
|
|
|
+ mmci_reg_delay(host);
|
|
|
|
|
|
spin_unlock_irqrestore(&host->lock, flags);
|
|
|
|
|
@@ -1510,23 +1532,6 @@ static int mmci_probe(struct amba_device *dev,
|
|
|
mmc->f_max = min(host->mclk, fmax);
|
|
|
dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
|
|
|
|
|
|
- host->pinctrl = devm_pinctrl_get(&dev->dev);
|
|
|
- if (IS_ERR(host->pinctrl)) {
|
|
|
- ret = PTR_ERR(host->pinctrl);
|
|
|
- goto clk_disable;
|
|
|
- }
|
|
|
-
|
|
|
- host->pins_default = pinctrl_lookup_state(host->pinctrl,
|
|
|
- PINCTRL_STATE_DEFAULT);
|
|
|
-
|
|
|
- /* enable pins to be muxed in and configured */
|
|
|
- if (!IS_ERR(host->pins_default)) {
|
|
|
- ret = pinctrl_select_state(host->pinctrl, host->pins_default);
|
|
|
- if (ret)
|
|
|
- dev_warn(&dev->dev, "could not set default pins\n");
|
|
|
- } else
|
|
|
- dev_warn(&dev->dev, "could not get default pinstate\n");
|
|
|
-
|
|
|
/* Get regulators and the supported OCR mask */
|
|
|
mmc_regulator_get_supply(mmc);
|
|
|
if (!mmc->ocr_avail)
|
|
@@ -1760,6 +1765,41 @@ static int mmci_resume(struct device *dev)
|
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_PM_RUNTIME
|
|
|
+static void mmci_save(struct mmci_host *host)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (host->variant->pwrreg_nopower) {
|
|
|
+ spin_lock_irqsave(&host->lock, flags);
|
|
|
+
|
|
|
+ writel(0, host->base + MMCIMASK0);
|
|
|
+ writel(0, host->base + MMCIDATACTRL);
|
|
|
+ writel(0, host->base + MMCIPOWER);
|
|
|
+ writel(0, host->base + MMCICLOCK);
|
|
|
+ mmci_reg_delay(host);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&host->lock, flags);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void mmci_restore(struct mmci_host *host)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ if (host->variant->pwrreg_nopower) {
|
|
|
+ spin_lock_irqsave(&host->lock, flags);
|
|
|
+
|
|
|
+ writel(host->clk_reg, host->base + MMCICLOCK);
|
|
|
+ writel(host->datactrl_reg, host->base + MMCIDATACTRL);
|
|
|
+ writel(host->pwr_reg, host->base + MMCIPOWER);
|
|
|
+ writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
|
|
+ mmci_reg_delay(host);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&host->lock, flags);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int mmci_runtime_suspend(struct device *dev)
|
|
|
{
|
|
|
struct amba_device *adev = to_amba_device(dev);
|
|
@@ -1767,6 +1807,8 @@ static int mmci_runtime_suspend(struct device *dev)
|
|
|
|
|
|
if (mmc) {
|
|
|
struct mmci_host *host = mmc_priv(mmc);
|
|
|
+ pinctrl_pm_select_sleep_state(dev);
|
|
|
+ mmci_save(host);
|
|
|
clk_disable_unprepare(host->clk);
|
|
|
}
|
|
|
|
|
@@ -1781,6 +1823,8 @@ static int mmci_runtime_resume(struct device *dev)
|
|
|
if (mmc) {
|
|
|
struct mmci_host *host = mmc_priv(mmc);
|
|
|
clk_prepare_enable(host->clk);
|
|
|
+ mmci_restore(host);
|
|
|
+ pinctrl_pm_select_default_state(dev);
|
|
|
}
|
|
|
|
|
|
return 0;
|