int trans_bytes = 0, is_aligned = 1;
u32 mask, flags, mode;
unsigned int timeout, start_addr = 0;
+ unsigned int retry = 10000;
/* Wait max 10 ms */
timeout = 10;
stat = sdhci_readl(host, SDHCI_INT_STATUS);
if (stat & SDHCI_INT_ERROR)
break;
+ if (--retry == 0)
+ break;
} while ((stat & mask) != mask);
+ if (retry == 0) {
+ if (host->quirks & SDHCI_QUIRK_BROKEN_R1B)
+ return 0;
+ else {
+ printf("Timeout for status update!\n");
+ return TIMEOUT;
+ }
+ }
+
if ((stat & (SDHCI_INT_ERROR | mask)) == mask) {
sdhci_cmd_done(host, cmd);
sdhci_writel(host, mask, SDHCI_INT_STATUS);
if (clock == 0)
return 0;
- if (host->version >= SDHCI_SPEC_300) {
+ if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
/* Version 3.00 divisors must be a multiple of 2. */
if (mmc->f_max <= clock)
div = 1;
}
div >>= 1;
+ if (host->set_clock)
+ host->set_clock(host->index, div);
+
clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
<< SDHCI_DIVIDER_HI_SHIFT;
u32 ctrl;
struct sdhci_host *host = (struct sdhci_host *)mmc->priv;
+ if (host->set_control_reg)
+ host->set_control_reg(host);
+
if (mmc->clock != host->clock)
sdhci_set_clock(mmc, mmc->clock);
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
if (mmc->bus_width == 8) {
ctrl &= ~SDHCI_CTRL_4BITBUS;
- if (host->version >= SDHCI_SPEC_300)
+ if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
ctrl |= SDHCI_CTRL_8BITBUS;
} else {
- if (host->version >= SDHCI_SPEC_300)
+ if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
ctrl &= ~SDHCI_CTRL_8BITBUS;
if (mmc->bus_width == 4)
ctrl |= SDHCI_CTRL_4BITBUS;
else
ctrl &= ~SDHCI_CTRL_HISPD;
+ if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)
+ ctrl &= ~SDHCI_CTRL_HISPD;
+
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}
}
}
+ sdhci_set_power(host, fls(mmc->voltages) - 1);
+
+ if (host->quirks & SDHCI_QUIRK_NO_CD) {
+ unsigned int status;
+
+ sdhci_writel(host, SDHCI_CTRL_CD_TEST_INS | SDHCI_CTRL_CD_TEST,
+ SDHCI_HOST_CONTROL);
+
+ status = sdhci_readl(host, SDHCI_PRESENT_STATE);
+ while ((!(status & SDHCI_CARD_PRESENT)) ||
+ (!(status & SDHCI_CARD_STATE_STABLE)) ||
+ (!(status & SDHCI_CARD_DETECT_PIN_LEVEL)))
+ status = sdhci_readl(host, SDHCI_PRESENT_STATE);
+ }
+
/* Eable all state */
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_ENABLE);
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_SIGNAL_ENABLE);
- sdhci_set_power(host, fls(mmc->voltages) - 1);
-
return 0;
}
if (max_clk)
mmc->f_max = max_clk;
else {
- if (host->version >= SDHCI_SPEC_300)
+ if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
mmc->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
>> SDHCI_CLOCK_BASE_SHIFT;
else
if (min_clk)
mmc->f_min = min_clk;
else {
- if (host->version >= SDHCI_SPEC_300)
+ if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_300;
else
mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_200;
mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
if (caps & SDHCI_CAN_VDD_180)
mmc->voltages |= MMC_VDD_165_195;
+
+ if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
+ mmc->voltages |= host->voltages;
+
mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
if (caps & SDHCI_CAN_DO_8BIT)
mmc->host_caps |= MMC_MODE_8BIT;
+ if (host->host_caps)
+ mmc->host_caps |= host->host_caps;
sdhci_reset(host, SDHCI_RESET_ALL);
mmc_register(mmc);