|
27 | 27 | #define SDMMC_MC1R_DDR BIT(3) |
28 | 28 | #define SDMMC_MC1R_RSTN BIT(6) |
29 | 29 | #define SDMMC_MC1R_FCD BIT(7) |
| 30 | +#define SDMMC_MC3R 0x206 |
| 31 | +#define SDMMC_MC3R_HS400EN BIT(0) |
| 32 | +#define SDMMC_MC3R_ESMEN BIT(1) |
30 | 33 | #define SDMMC_CACR 0x230 |
31 | 34 | #define SDMMC_CACR_CAPWREN BIT(0) |
32 | 35 | #define SDMMC_CACR_KEY (0x46 << 8) |
@@ -103,14 +106,32 @@ static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock) |
103 | 106 | static void sdhci_at91_set_uhs_signaling(struct sdhci_host *host, |
104 | 107 | unsigned int timing) |
105 | 108 | { |
106 | | - u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); |
| 109 | + u16 clk; |
| 110 | + u8 mc3r, mc1r; |
| 111 | + |
| 112 | + mc1r = readb(host->ioaddr + SDMMC_MC1R); |
| 113 | + mc3r = readb(host->ioaddr + SDMMC_MC3R); |
| 114 | + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); |
| 115 | + |
107 | 116 | /* SDCLK must be disabled while changing the mode */ |
108 | 117 | if (clk & SDHCI_CLOCK_CARD_EN) |
109 | 118 | sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, |
110 | 119 | SDHCI_CLOCK_CONTROL); |
111 | 120 |
|
112 | | - if (timing == MMC_TIMING_MMC_DDR52) |
113 | | - sdhci_writeb(host, SDMMC_MC1R_DDR, SDMMC_MC1R); |
| 121 | + if (timing == MMC_TIMING_MMC_DDR52 || timing == MMC_TIMING_MMC_HS400) |
| 122 | + mc1r |= SDMMC_MC1R_DDR; |
| 123 | + else |
| 124 | + mc1r &= ~SDMMC_MC1R_DDR; |
| 125 | + |
| 126 | + sdhci_writeb(host, mc1r, SDMMC_MC1R); |
| 127 | + |
| 128 | + if (timing == MMC_TIMING_MMC_HS400) |
| 129 | + mc3r |= SDMMC_MC3R_HS400EN; |
| 130 | + else |
| 131 | + mc3r &= ~SDMMC_MC3R_HS400EN; |
| 132 | + |
| 133 | + writeb(mc3r, host->ioaddr + SDMMC_MC3R); |
| 134 | + |
114 | 135 | sdhci_set_uhs_signaling(host, timing); |
115 | 136 |
|
116 | 137 | /* reenable SDCLK */ |
@@ -362,6 +383,20 @@ static const struct dev_pm_ops sdhci_at91_dev_pm_ops = { |
362 | 383 | NULL) |
363 | 384 | }; |
364 | 385 |
|
| 386 | +static void at91_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios) |
| 387 | +{ |
| 388 | + struct sdhci_host *host = mmc_priv(mmc); |
| 389 | + u8 mc3r; |
| 390 | + |
| 391 | + mc3r = readb(host->ioaddr + SDMMC_MC3R); |
| 392 | + if (ios->enhanced_strobe) |
| 393 | + mc3r |= SDMMC_MC3R_ESMEN; |
| 394 | + else |
| 395 | + mc3r &= ~SDMMC_MC3R_ESMEN; |
| 396 | + |
| 397 | + writeb(mc3r, host->ioaddr + SDMMC_MC3R); |
| 398 | +} |
| 399 | + |
365 | 400 | static int sdhci_at91_probe(struct platform_device *pdev) |
366 | 401 | { |
367 | 402 | const struct of_device_id *match; |
@@ -446,6 +481,8 @@ static int sdhci_at91_probe(struct platform_device *pdev) |
446 | 481 | if (ret) |
447 | 482 | goto pm_runtime_disable; |
448 | 483 |
|
| 484 | + host->mmc_host_ops.hs400_enhanced_strobe = at91_sdhci_hs400_enhanced_strobe; |
| 485 | + |
449 | 486 | /* |
450 | 487 | * When calling sdhci_runtime_suspend_host(), the sdhci layer makes |
451 | 488 | * the assumption that all the clocks of the controller are disabled. |
|
0 commit comments