@@ -179,6 +179,9 @@ static int __devinit sdhci_of_probe(struct platform_device *ofdev)
if (sdhci_of_wp_inverted(np))
host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+ if (of_device_is_compatible(np, "fsl,esdhc"))
+ host->quirks |= SDHCI_QUIRK_QORIQ_PROCTL_WEIRD;
+
clk = of_get_property(np, "clock-frequency", &size);
if (clk && size == sizeof(*clk) && *clk)
of_host->clock = be32_to_cpup(clk);
@@ -674,7 +674,7 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)
static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
{
u8 count;
- u8 ctrl;
+ u32 ctrl;
struct mmc_data *data = cmd->data;
int ret;
@@ -807,14 +807,28 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
* is ADMA.
*/
if (host->version >= SDHCI_SPEC_200) {
- ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
- ctrl &= ~SDHCI_CTRL_DMA_MASK;
- if ((host->flags & SDHCI_REQ_USE_DMA) &&
- (host->flags & SDHCI_USE_ADMA))
- ctrl |= SDHCI_CTRL_ADMA32;
- else
- ctrl |= SDHCI_CTRL_SDMA;
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+ if (host->quirks & SDHCI_QUIRK_QORIQ_PROCTL_WEIRD) {
+#define ESDHCI_PROCTL_DMAS_MASK 0x00000300
+#define ESDHCI_PROCTL_ADMA32 0x00000200
+#define ESDHCI_PROCTL_SDMA 0x00000000
+ ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
+ ctrl &= ~ESDHCI_PROCTL_DMAS_MASK;
+ if ((host->flags & SDHCI_REQ_USE_DMA) &&
+ (host->flags & SDHCI_USE_ADMA))
+ ctrl |= ESDHCI_PROCTL_ADMA32;
+ else
+ ctrl |= ESDHCI_PROCTL_SDMA;
+ sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
+ } else {
+ ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+ ctrl &= ~SDHCI_CTRL_DMA_MASK;
+ if ((host->flags & SDHCI_REQ_USE_DMA) &&
+ (host->flags & SDHCI_USE_ADMA))
+ ctrl |= SDHCI_CTRL_ADMA32;
+ else
+ ctrl |= SDHCI_CTRL_SDMA;
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+ }
}
if (!(host->flags & SDHCI_REQ_USE_DMA)) {
@@ -1138,19 +1152,32 @@ out:
static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
{
u8 pwr = 0;
+ u8 volt = 0;
if (power != (unsigned short)-1) {
switch (1 << power) {
+#define ESDHCI_FSL_POWER_MASK 0x40
+#define ESDHCI_FSL_POWER_180 0x00
+#define ESDHCI_FSL_POWER_300 0x40
case MMC_VDD_165_195:
- pwr = SDHCI_POWER_180;
+ if (host->quirks & SDHCI_QUIRK_QORIQ_PROCTL_WEIRD)
+ pwr = ESDHCI_FSL_POWER_180;
+ else
+ pwr = SDHCI_POWER_180;
break;
case MMC_VDD_29_30:
case MMC_VDD_30_31:
- pwr = SDHCI_POWER_300;
+ if (host->quirks & SDHCI_QUIRK_QORIQ_PROCTL_WEIRD)
+ pwr = ESDHCI_FSL_POWER_300;
+ else
+ pwr = SDHCI_POWER_300;
break;
case MMC_VDD_32_33:
case MMC_VDD_33_34:
- pwr = SDHCI_POWER_330;
+ if (host->quirks & SDHCI_QUIRK_QORIQ_PROCTL_WEIRD)
+ pwr = ESDHCI_FSL_POWER_300;
+ else
+ pwr = SDHCI_POWER_330;
break;
default:
BUG();
@@ -1162,6 +1189,19 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
host->pwr = pwr;
+ /*
+ * FSL ESDHC Controller has no Bus Power bit,
+ * and PROCTL[21] bit is for voltage selection.
+ */
+ if (host->quirks & SDHCI_QUIRK_QORIQ_PROCTL_WEIRD) {
+ volt = sdhci_readb(host, SDHCI_POWER_CONTROL);
+ volt &= ~ESDHCI_FSL_POWER_MASK;
+ volt |= pwr;
+ sdhci_writeb(host, volt, SDHCI_POWER_CONTROL);
+
+ return;
+ }
+
if (pwr == 0) {
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
return;
@@ -21,7 +21,7 @@ struct sdhci_host {
/* Data set by hardware interface driver */
const char *hw_name; /* Hardware bus name */
- unsigned int quirks; /* Deviations from spec. */
+ u64 quirks; /* Deviations from spec. */
/* Controller doesn't honor resets unless we touch the clock register */
#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0)
@@ -86,7 +86,9 @@ struct sdhci_host {
/* Controller treats ADMA descriptors with length 0000h incorrectly */
#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30)
/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
-#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1<<31)
+#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1U<<31)
+/* Controller has weird bit setting for Protocol Control Register */
+#define SDHCI_QUIRK_QORIQ_PROCTL_WEIRD (0x100000000U)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */