12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 27657c3a7SAlbert Herranz /* 37657c3a7SAlbert Herranz * Freescale eSDHC controller driver. 47657c3a7SAlbert Herranz * 5f060bc9cSJerry Huang * Copyright (c) 2007, 2010, 2012 Freescale Semiconductor, Inc. 67657c3a7SAlbert Herranz * Copyright (c) 2009 MontaVista Software, Inc. 77657c3a7SAlbert Herranz * 87657c3a7SAlbert Herranz * Authors: Xiaobo Xie <X.Xie@freescale.com> 97657c3a7SAlbert Herranz * Anton Vorontsov <avorontsov@ru.mvista.com> 107657c3a7SAlbert Herranz */ 117657c3a7SAlbert Herranz 1266b50a00SOded Gabbay #include <linux/err.h> 137657c3a7SAlbert Herranz #include <linux/io.h> 14f060bc9cSJerry Huang #include <linux/of.h> 15ea35645aSyangbo lu #include <linux/of_address.h> 167657c3a7SAlbert Herranz #include <linux/delay.h> 1788b47679SPaul Gortmaker #include <linux/module.h> 18151ede40Syangbo lu #include <linux/sys_soc.h> 1919c3a0efSyangbo lu #include <linux/clk.h> 2019c3a0efSyangbo lu #include <linux/ktime.h> 215552d7adSLaurentiu Tudor #include <linux/dma-mapping.h> 227657c3a7SAlbert Herranz #include <linux/mmc/host.h> 23b214fe59SYinbo Zhu #include <linux/mmc/mmc.h> 2438576af1SShawn Guo #include "sdhci-pltfm.h" 2580872e21SWolfram Sang #include "sdhci-esdhc.h" 267657c3a7SAlbert Herranz 27137ccd46SJerry Huang #define VENDOR_V_22 0x12 28a4071fbbSHaijun Zhang #define VENDOR_V_23 0x13 29f4932cfdSyangbo lu 3067fdfbdfSyinbo.zhu #define MMC_TIMING_NUM (MMC_TIMING_MMC_HS400 + 1) 3167fdfbdfSyinbo.zhu 3267fdfbdfSyinbo.zhu struct esdhc_clk_fixup { 3367fdfbdfSyinbo.zhu const unsigned int sd_dflt_max_clk; 3467fdfbdfSyinbo.zhu const unsigned int max_clk[MMC_TIMING_NUM]; 3567fdfbdfSyinbo.zhu }; 3667fdfbdfSyinbo.zhu 3767fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup ls1021a_esdhc_clk = { 3867fdfbdfSyinbo.zhu .sd_dflt_max_clk = 25000000, 3967fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS] = 46500000, 4067fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_SD_HS] = 46500000, 4167fdfbdfSyinbo.zhu }; 4267fdfbdfSyinbo.zhu 4367fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup ls1046a_esdhc_clk = { 4467fdfbdfSyinbo.zhu .sd_dflt_max_clk = 25000000, 4567fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_UHS_SDR104] = 167000000, 4667fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS200] = 167000000, 4767fdfbdfSyinbo.zhu }; 4867fdfbdfSyinbo.zhu 4967fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup ls1012a_esdhc_clk = { 5067fdfbdfSyinbo.zhu .sd_dflt_max_clk = 25000000, 5167fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_UHS_SDR104] = 125000000, 5267fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS200] = 125000000, 5367fdfbdfSyinbo.zhu }; 5467fdfbdfSyinbo.zhu 5567fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup p1010_esdhc_clk = { 5667fdfbdfSyinbo.zhu .sd_dflt_max_clk = 20000000, 5767fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_LEGACY] = 20000000, 5867fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS] = 42000000, 5967fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_SD_HS] = 40000000, 6067fdfbdfSyinbo.zhu }; 6167fdfbdfSyinbo.zhu 6267fdfbdfSyinbo.zhu static const struct of_device_id sdhci_esdhc_of_match[] = { 6367fdfbdfSyinbo.zhu { .compatible = "fsl,ls1021a-esdhc", .data = &ls1021a_esdhc_clk}, 6467fdfbdfSyinbo.zhu { .compatible = "fsl,ls1046a-esdhc", .data = &ls1046a_esdhc_clk}, 6567fdfbdfSyinbo.zhu { .compatible = "fsl,ls1012a-esdhc", .data = &ls1012a_esdhc_clk}, 6667fdfbdfSyinbo.zhu { .compatible = "fsl,p1010-esdhc", .data = &p1010_esdhc_clk}, 6767fdfbdfSyinbo.zhu { .compatible = "fsl,mpc8379-esdhc" }, 6867fdfbdfSyinbo.zhu { .compatible = "fsl,mpc8536-esdhc" }, 6967fdfbdfSyinbo.zhu { .compatible = "fsl,esdhc" }, 7067fdfbdfSyinbo.zhu { } 7167fdfbdfSyinbo.zhu }; 7267fdfbdfSyinbo.zhu MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match); 7367fdfbdfSyinbo.zhu 74f4932cfdSyangbo lu struct sdhci_esdhc { 75f4932cfdSyangbo lu u8 vendor_ver; 76f4932cfdSyangbo lu u8 spec_ver; 77151ede40Syangbo lu bool quirk_incorrect_hostver; 786079e63cSYangbo Lu bool quirk_limited_clk_division; 7948e304ccSYangbo Lu bool quirk_unreliable_pulse_detection; 8022dc132dSYangbo Lu bool quirk_tuning_erratum_type1; 8122dc132dSYangbo Lu bool quirk_tuning_erratum_type2; 821f1929f3SYangbo Lu bool quirk_ignore_data_inhibit; 8322dc132dSYangbo Lu bool in_sw_tuning; 8419c3a0efSyangbo lu unsigned int peripheral_clock; 8567fdfbdfSyinbo.zhu const struct esdhc_clk_fixup *clk_fixup; 86b1f378abSYinbo Zhu u32 div_ratio; 87f4932cfdSyangbo lu }; 88f4932cfdSyangbo lu 89f4932cfdSyangbo lu /** 90f4932cfdSyangbo lu * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register 91f4932cfdSyangbo lu * to make it compatible with SD spec. 92f4932cfdSyangbo lu * 93f4932cfdSyangbo lu * @host: pointer to sdhci_host 94f4932cfdSyangbo lu * @spec_reg: SD spec register address 95f4932cfdSyangbo lu * @value: 32bit eSDHC register value on spec_reg address 96f4932cfdSyangbo lu * 97f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 98f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 99f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 100f4932cfdSyangbo lu * and SD spec. 101f4932cfdSyangbo lu * 102f4932cfdSyangbo lu * Return a fixed up register value 103f4932cfdSyangbo lu */ 104f4932cfdSyangbo lu static u32 esdhc_readl_fixup(struct sdhci_host *host, 105f4932cfdSyangbo lu int spec_reg, u32 value) 106137ccd46SJerry Huang { 107f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1088605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 109137ccd46SJerry Huang u32 ret; 110137ccd46SJerry Huang 111137ccd46SJerry Huang /* 112137ccd46SJerry Huang * The bit of ADMA flag in eSDHC is not compatible with standard 113137ccd46SJerry Huang * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is 114137ccd46SJerry Huang * supported by eSDHC. 115137ccd46SJerry Huang * And for many FSL eSDHC controller, the reset value of field 116f4932cfdSyangbo lu * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA, 117137ccd46SJerry Huang * only these vendor version is greater than 2.2/0x12 support ADMA. 118137ccd46SJerry Huang */ 119f4932cfdSyangbo lu if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) { 120f4932cfdSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) { 121f4932cfdSyangbo lu ret = value | SDHCI_CAN_DO_ADMA2; 122f4932cfdSyangbo lu return ret; 123137ccd46SJerry Huang } 124f4932cfdSyangbo lu } 125b0921d5cSMichael Walle /* 126b0921d5cSMichael Walle * The DAT[3:0] line signal levels and the CMD line signal level are 127b0921d5cSMichael Walle * not compatible with standard SDHC register. The line signal levels 128b0921d5cSMichael Walle * DAT[7:0] are at bits 31:24 and the command line signal level is at 129b0921d5cSMichael Walle * bit 23. All other bits are the same as in the standard SDHC 130b0921d5cSMichael Walle * register. 131b0921d5cSMichael Walle */ 132b0921d5cSMichael Walle if (spec_reg == SDHCI_PRESENT_STATE) { 133b0921d5cSMichael Walle ret = value & 0x000fffff; 134b0921d5cSMichael Walle ret |= (value >> 4) & SDHCI_DATA_LVL_MASK; 135b0921d5cSMichael Walle ret |= (value << 1) & SDHCI_CMD_LVL; 136b0921d5cSMichael Walle return ret; 137b0921d5cSMichael Walle } 138b0921d5cSMichael Walle 1392f3110ccSyangbo lu /* 1402f3110ccSyangbo lu * DTS properties of mmc host are used to enable each speed mode 1412f3110ccSyangbo lu * according to soc and board capability. So clean up 1422f3110ccSyangbo lu * SDR50/SDR104/DDR50 support bits here. 1432f3110ccSyangbo lu */ 1442f3110ccSyangbo lu if (spec_reg == SDHCI_CAPABILITIES_1) { 1452f3110ccSyangbo lu ret = value & ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | 1462f3110ccSyangbo lu SDHCI_SUPPORT_DDR50); 1472f3110ccSyangbo lu return ret; 1482f3110ccSyangbo lu } 1492f3110ccSyangbo lu 1501f1929f3SYangbo Lu /* 1511f1929f3SYangbo Lu * Some controllers have unreliable Data Line Active 1521f1929f3SYangbo Lu * bit for commands with busy signal. This affects 1531f1929f3SYangbo Lu * Command Inhibit (data) bit. Just ignore it since 1541f1929f3SYangbo Lu * MMC core driver has already polled card status 1551f1929f3SYangbo Lu * with CMD13 after any command with busy siganl. 1561f1929f3SYangbo Lu */ 1571f1929f3SYangbo Lu if ((spec_reg == SDHCI_PRESENT_STATE) && 1581f1929f3SYangbo Lu (esdhc->quirk_ignore_data_inhibit == true)) { 1591f1929f3SYangbo Lu ret = value & ~SDHCI_DATA_INHIBIT; 1601f1929f3SYangbo Lu return ret; 1611f1929f3SYangbo Lu } 1621f1929f3SYangbo Lu 163f4932cfdSyangbo lu ret = value; 164137ccd46SJerry Huang return ret; 165137ccd46SJerry Huang } 166137ccd46SJerry Huang 167f4932cfdSyangbo lu static u16 esdhc_readw_fixup(struct sdhci_host *host, 168f4932cfdSyangbo lu int spec_reg, u32 value) 1697657c3a7SAlbert Herranz { 170151ede40Syangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 171151ede40Syangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1727657c3a7SAlbert Herranz u16 ret; 173f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 1747657c3a7SAlbert Herranz 175f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_VERSION) 176f4932cfdSyangbo lu ret = value & 0xffff; 1777657c3a7SAlbert Herranz else 178f4932cfdSyangbo lu ret = (value >> shift) & 0xffff; 179151ede40Syangbo lu /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect 180151ede40Syangbo lu * vendor version and spec version information. 181151ede40Syangbo lu */ 182151ede40Syangbo lu if ((spec_reg == SDHCI_HOST_VERSION) && 183151ede40Syangbo lu (esdhc->quirk_incorrect_hostver)) 184151ede40Syangbo lu ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200; 185e51cbc9eSXu lei return ret; 186e51cbc9eSXu lei } 187e51cbc9eSXu lei 188f4932cfdSyangbo lu static u8 esdhc_readb_fixup(struct sdhci_host *host, 189f4932cfdSyangbo lu int spec_reg, u32 value) 190e51cbc9eSXu lei { 191f4932cfdSyangbo lu u8 ret; 192f4932cfdSyangbo lu u8 dma_bits; 193f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 194f4932cfdSyangbo lu 195f4932cfdSyangbo lu ret = (value >> shift) & 0xff; 196ba8c4dc9SRoy Zang 197ba8c4dc9SRoy Zang /* 198ba8c4dc9SRoy Zang * "DMA select" locates at offset 0x28 in SD specification, but on 199ba8c4dc9SRoy Zang * P5020 or P3041, it locates at 0x29. 200ba8c4dc9SRoy Zang */ 201f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 202ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 203f4932cfdSyangbo lu dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK; 204ba8c4dc9SRoy Zang /* fixup the result */ 205ba8c4dc9SRoy Zang ret &= ~SDHCI_CTRL_DMA_MASK; 206ba8c4dc9SRoy Zang ret |= dma_bits; 207ba8c4dc9SRoy Zang } 208f4932cfdSyangbo lu return ret; 209f4932cfdSyangbo lu } 210f4932cfdSyangbo lu 211f4932cfdSyangbo lu /** 212f4932cfdSyangbo lu * esdhc_write*_fixup - Fixup the SD spec register value so that it could be 213f4932cfdSyangbo lu * written into eSDHC register. 214f4932cfdSyangbo lu * 215f4932cfdSyangbo lu * @host: pointer to sdhci_host 216f4932cfdSyangbo lu * @spec_reg: SD spec register address 217f4932cfdSyangbo lu * @value: 8/16/32bit SD spec register value that would be written 218f4932cfdSyangbo lu * @old_value: 32bit eSDHC register value on spec_reg address 219f4932cfdSyangbo lu * 220f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 221f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 222f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 223f4932cfdSyangbo lu * and SD spec. 224f4932cfdSyangbo lu * 225f4932cfdSyangbo lu * Return a fixed up register value 226f4932cfdSyangbo lu */ 227f4932cfdSyangbo lu static u32 esdhc_writel_fixup(struct sdhci_host *host, 228f4932cfdSyangbo lu int spec_reg, u32 value, u32 old_value) 229f4932cfdSyangbo lu { 230f4932cfdSyangbo lu u32 ret; 231f4932cfdSyangbo lu 232f4932cfdSyangbo lu /* 233f4932cfdSyangbo lu * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] 234f4932cfdSyangbo lu * when SYSCTL[RSTD] is set for some special operations. 235f4932cfdSyangbo lu * No any impact on other operation. 236f4932cfdSyangbo lu */ 237f4932cfdSyangbo lu if (spec_reg == SDHCI_INT_ENABLE) 238f4932cfdSyangbo lu ret = value | SDHCI_INT_BLK_GAP; 239f4932cfdSyangbo lu else 240f4932cfdSyangbo lu ret = value; 241ba8c4dc9SRoy Zang 2427657c3a7SAlbert Herranz return ret; 2437657c3a7SAlbert Herranz } 2447657c3a7SAlbert Herranz 245f4932cfdSyangbo lu static u32 esdhc_writew_fixup(struct sdhci_host *host, 246f4932cfdSyangbo lu int spec_reg, u16 value, u32 old_value) 247a4071fbbSHaijun Zhang { 248f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 249f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 250f4932cfdSyangbo lu u32 ret; 251f4932cfdSyangbo lu 252f4932cfdSyangbo lu switch (spec_reg) { 253f4932cfdSyangbo lu case SDHCI_TRANSFER_MODE: 254a4071fbbSHaijun Zhang /* 255f4932cfdSyangbo lu * Postpone this write, we must do it together with a 256f4932cfdSyangbo lu * command write that is down below. Return old value. 257a4071fbbSHaijun Zhang */ 258f4932cfdSyangbo lu pltfm_host->xfer_mode_shadow = value; 259f4932cfdSyangbo lu return old_value; 260f4932cfdSyangbo lu case SDHCI_COMMAND: 261f4932cfdSyangbo lu ret = (value << 16) | pltfm_host->xfer_mode_shadow; 262f4932cfdSyangbo lu return ret; 263a4071fbbSHaijun Zhang } 264a4071fbbSHaijun Zhang 265f4932cfdSyangbo lu ret = old_value & (~(0xffff << shift)); 266f4932cfdSyangbo lu ret |= (value << shift); 267f4932cfdSyangbo lu 268f4932cfdSyangbo lu if (spec_reg == SDHCI_BLOCK_SIZE) { 2697657c3a7SAlbert Herranz /* 2707657c3a7SAlbert Herranz * Two last DMA bits are reserved, and first one is used for 2717657c3a7SAlbert Herranz * non-standard blksz of 4096 bytes that we don't support 2727657c3a7SAlbert Herranz * yet. So clear the DMA boundary bits. 2737657c3a7SAlbert Herranz */ 274f4932cfdSyangbo lu ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0)); 2757657c3a7SAlbert Herranz } 276f4932cfdSyangbo lu return ret; 2777657c3a7SAlbert Herranz } 2787657c3a7SAlbert Herranz 279f4932cfdSyangbo lu static u32 esdhc_writeb_fixup(struct sdhci_host *host, 280f4932cfdSyangbo lu int spec_reg, u8 value, u32 old_value) 2817657c3a7SAlbert Herranz { 282f4932cfdSyangbo lu u32 ret; 283f4932cfdSyangbo lu u32 dma_bits; 284f4932cfdSyangbo lu u8 tmp; 285f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 286f4932cfdSyangbo lu 287ba8c4dc9SRoy Zang /* 2889e4703dfSyangbo lu * eSDHC doesn't have a standard power control register, so we do 2899e4703dfSyangbo lu * nothing here to avoid incorrect operation. 2909e4703dfSyangbo lu */ 2919e4703dfSyangbo lu if (spec_reg == SDHCI_POWER_CONTROL) 2929e4703dfSyangbo lu return old_value; 2939e4703dfSyangbo lu /* 294ba8c4dc9SRoy Zang * "DMA select" location is offset 0x28 in SD specification, but on 295ba8c4dc9SRoy Zang * P5020 or P3041, it's located at 0x29. 296ba8c4dc9SRoy Zang */ 297f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 298dcaff04dSOded Gabbay /* 299dcaff04dSOded Gabbay * If host control register is not standard, exit 300dcaff04dSOded Gabbay * this function 301dcaff04dSOded Gabbay */ 302dcaff04dSOded Gabbay if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) 303f4932cfdSyangbo lu return old_value; 304dcaff04dSOded Gabbay 305ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 306f4932cfdSyangbo lu dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5; 307f4932cfdSyangbo lu ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits; 308f4932cfdSyangbo lu tmp = (value & (~SDHCI_CTRL_DMA_MASK)) | 309f4932cfdSyangbo lu (old_value & SDHCI_CTRL_DMA_MASK); 310f4932cfdSyangbo lu ret = (ret & (~0xff)) | tmp; 311f4932cfdSyangbo lu 312f4932cfdSyangbo lu /* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */ 313f4932cfdSyangbo lu ret &= ~ESDHC_HOST_CONTROL_RES; 314f4932cfdSyangbo lu return ret; 315ba8c4dc9SRoy Zang } 316ba8c4dc9SRoy Zang 317f4932cfdSyangbo lu ret = (old_value & (~(0xff << shift))) | (value << shift); 318f4932cfdSyangbo lu return ret; 319f4932cfdSyangbo lu } 320f4932cfdSyangbo lu 321f4932cfdSyangbo lu static u32 esdhc_be_readl(struct sdhci_host *host, int reg) 322f4932cfdSyangbo lu { 323f4932cfdSyangbo lu u32 ret; 324f4932cfdSyangbo lu u32 value; 325f4932cfdSyangbo lu 3262f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3272f3110ccSyangbo lu value = ioread32be(host->ioaddr + ESDHC_CAPABILITIES_1); 3282f3110ccSyangbo lu else 329f4932cfdSyangbo lu value = ioread32be(host->ioaddr + reg); 3302f3110ccSyangbo lu 331f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 332f4932cfdSyangbo lu 333f4932cfdSyangbo lu return ret; 334f4932cfdSyangbo lu } 335f4932cfdSyangbo lu 336f4932cfdSyangbo lu static u32 esdhc_le_readl(struct sdhci_host *host, int reg) 337f4932cfdSyangbo lu { 338f4932cfdSyangbo lu u32 ret; 339f4932cfdSyangbo lu u32 value; 340f4932cfdSyangbo lu 3412f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3422f3110ccSyangbo lu value = ioread32(host->ioaddr + ESDHC_CAPABILITIES_1); 3432f3110ccSyangbo lu else 344f4932cfdSyangbo lu value = ioread32(host->ioaddr + reg); 3452f3110ccSyangbo lu 346f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 347f4932cfdSyangbo lu 348f4932cfdSyangbo lu return ret; 349f4932cfdSyangbo lu } 350f4932cfdSyangbo lu 351f4932cfdSyangbo lu static u16 esdhc_be_readw(struct sdhci_host *host, int reg) 352f4932cfdSyangbo lu { 353f4932cfdSyangbo lu u16 ret; 354f4932cfdSyangbo lu u32 value; 355f4932cfdSyangbo lu int base = reg & ~0x3; 356f4932cfdSyangbo lu 357f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 358f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 359f4932cfdSyangbo lu return ret; 360f4932cfdSyangbo lu } 361f4932cfdSyangbo lu 362f4932cfdSyangbo lu static u16 esdhc_le_readw(struct sdhci_host *host, int reg) 363f4932cfdSyangbo lu { 364f4932cfdSyangbo lu u16 ret; 365f4932cfdSyangbo lu u32 value; 366f4932cfdSyangbo lu int base = reg & ~0x3; 367f4932cfdSyangbo lu 368f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 369f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 370f4932cfdSyangbo lu return ret; 371f4932cfdSyangbo lu } 372f4932cfdSyangbo lu 373f4932cfdSyangbo lu static u8 esdhc_be_readb(struct sdhci_host *host, int reg) 374f4932cfdSyangbo lu { 375f4932cfdSyangbo lu u8 ret; 376f4932cfdSyangbo lu u32 value; 377f4932cfdSyangbo lu int base = reg & ~0x3; 378f4932cfdSyangbo lu 379f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 380f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 381f4932cfdSyangbo lu return ret; 382f4932cfdSyangbo lu } 383f4932cfdSyangbo lu 384f4932cfdSyangbo lu static u8 esdhc_le_readb(struct sdhci_host *host, int reg) 385f4932cfdSyangbo lu { 386f4932cfdSyangbo lu u8 ret; 387f4932cfdSyangbo lu u32 value; 388f4932cfdSyangbo lu int base = reg & ~0x3; 389f4932cfdSyangbo lu 390f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 391f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 392f4932cfdSyangbo lu return ret; 393f4932cfdSyangbo lu } 394f4932cfdSyangbo lu 395f4932cfdSyangbo lu static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg) 396f4932cfdSyangbo lu { 397f4932cfdSyangbo lu u32 value; 398f4932cfdSyangbo lu 399f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 400f4932cfdSyangbo lu iowrite32be(value, host->ioaddr + reg); 401f4932cfdSyangbo lu } 402f4932cfdSyangbo lu 403f4932cfdSyangbo lu static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg) 404f4932cfdSyangbo lu { 405f4932cfdSyangbo lu u32 value; 406f4932cfdSyangbo lu 407f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 408f4932cfdSyangbo lu iowrite32(value, host->ioaddr + reg); 409f4932cfdSyangbo lu } 410f4932cfdSyangbo lu 411f4932cfdSyangbo lu static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg) 412f4932cfdSyangbo lu { 41322dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 41422dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 415f4932cfdSyangbo lu int base = reg & ~0x3; 416f4932cfdSyangbo lu u32 value; 417f4932cfdSyangbo lu u32 ret; 418f4932cfdSyangbo lu 419f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 420f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 421f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 422f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 42322dc132dSYangbo Lu 42422dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 42522dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 42622dc132dSYangbo Lu */ 42722dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 42822dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 42922dc132dSYangbo Lu esdhc->in_sw_tuning) { 43022dc132dSYangbo Lu udelay(1); 43122dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 43222dc132dSYangbo Lu iowrite32be(ret, host->ioaddr + base); 43322dc132dSYangbo Lu } 43422dc132dSYangbo Lu } 435f4932cfdSyangbo lu } 436f4932cfdSyangbo lu 437f4932cfdSyangbo lu static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg) 438f4932cfdSyangbo lu { 43922dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 44022dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 441f4932cfdSyangbo lu int base = reg & ~0x3; 442f4932cfdSyangbo lu u32 value; 443f4932cfdSyangbo lu u32 ret; 444f4932cfdSyangbo lu 445f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 446f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 447f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 448f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 44922dc132dSYangbo Lu 45022dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 45122dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 45222dc132dSYangbo Lu */ 45322dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 45422dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 45522dc132dSYangbo Lu esdhc->in_sw_tuning) { 45622dc132dSYangbo Lu udelay(1); 45722dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 45822dc132dSYangbo Lu iowrite32(ret, host->ioaddr + base); 45922dc132dSYangbo Lu } 46022dc132dSYangbo Lu } 461f4932cfdSyangbo lu } 462f4932cfdSyangbo lu 463f4932cfdSyangbo lu static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg) 464f4932cfdSyangbo lu { 465f4932cfdSyangbo lu int base = reg & ~0x3; 466f4932cfdSyangbo lu u32 value; 467f4932cfdSyangbo lu u32 ret; 468f4932cfdSyangbo lu 469f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 470f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 471f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 472f4932cfdSyangbo lu } 473f4932cfdSyangbo lu 474f4932cfdSyangbo lu static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg) 475f4932cfdSyangbo lu { 476f4932cfdSyangbo lu int base = reg & ~0x3; 477f4932cfdSyangbo lu u32 value; 478f4932cfdSyangbo lu u32 ret; 479f4932cfdSyangbo lu 480f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 481f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 482f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 4837657c3a7SAlbert Herranz } 4847657c3a7SAlbert Herranz 485a4071fbbSHaijun Zhang /* 486a4071fbbSHaijun Zhang * For Abort or Suspend after Stop at Block Gap, ignore the ADMA 487a4071fbbSHaijun Zhang * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) 488a4071fbbSHaijun Zhang * and Block Gap Event(IRQSTAT[BGE]) are also set. 489a4071fbbSHaijun Zhang * For Continue, apply soft reset for data(SYSCTL[RSTD]); 490a4071fbbSHaijun Zhang * and re-issue the entire read transaction from beginning. 491a4071fbbSHaijun Zhang */ 492f4932cfdSyangbo lu static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) 493a4071fbbSHaijun Zhang { 494f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 4958605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 496a4071fbbSHaijun Zhang bool applicable; 497a4071fbbSHaijun Zhang dma_addr_t dmastart; 498a4071fbbSHaijun Zhang dma_addr_t dmanow; 499a4071fbbSHaijun Zhang 500a4071fbbSHaijun Zhang applicable = (intmask & SDHCI_INT_DATA_END) && 501a4071fbbSHaijun Zhang (intmask & SDHCI_INT_BLK_GAP) && 502f4932cfdSyangbo lu (esdhc->vendor_ver == VENDOR_V_23); 503a4071fbbSHaijun Zhang if (!applicable) 504a4071fbbSHaijun Zhang return; 505a4071fbbSHaijun Zhang 506a4071fbbSHaijun Zhang host->data->error = 0; 507a4071fbbSHaijun Zhang dmastart = sg_dma_address(host->data->sg); 508a4071fbbSHaijun Zhang dmanow = dmastart + host->data->bytes_xfered; 509a4071fbbSHaijun Zhang /* 510a4071fbbSHaijun Zhang * Force update to the next DMA block boundary. 511a4071fbbSHaijun Zhang */ 512a4071fbbSHaijun Zhang dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 513a4071fbbSHaijun Zhang SDHCI_DEFAULT_BOUNDARY_SIZE; 514a4071fbbSHaijun Zhang host->data->bytes_xfered = dmanow - dmastart; 515a4071fbbSHaijun Zhang sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); 516a4071fbbSHaijun Zhang } 517a4071fbbSHaijun Zhang 51880872e21SWolfram Sang static int esdhc_of_enable_dma(struct sdhci_host *host) 5197657c3a7SAlbert Herranz { 520f4932cfdSyangbo lu u32 value; 5215552d7adSLaurentiu Tudor struct device *dev = mmc_dev(host->mmc); 5225552d7adSLaurentiu Tudor 5235552d7adSLaurentiu Tudor if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || 5245552d7adSLaurentiu Tudor of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) 5255552d7adSLaurentiu Tudor dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); 526f4932cfdSyangbo lu 527f4932cfdSyangbo lu value = sdhci_readl(host, ESDHC_DMA_SYSCTL); 528121bd08bSRussell King 529121bd08bSRussell King if (of_dma_is_coherent(dev->of_node)) 530f4932cfdSyangbo lu value |= ESDHC_DMA_SNOOP; 531121bd08bSRussell King else 532121bd08bSRussell King value &= ~ESDHC_DMA_SNOOP; 533121bd08bSRussell King 534f4932cfdSyangbo lu sdhci_writel(host, value, ESDHC_DMA_SYSCTL); 5357657c3a7SAlbert Herranz return 0; 5367657c3a7SAlbert Herranz } 5377657c3a7SAlbert Herranz 53880872e21SWolfram Sang static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host) 5397657c3a7SAlbert Herranz { 540e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 54119c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 5427657c3a7SAlbert Herranz 54319c3a0efSyangbo lu if (esdhc->peripheral_clock) 54419c3a0efSyangbo lu return esdhc->peripheral_clock; 54519c3a0efSyangbo lu else 546e307148fSShawn Guo return pltfm_host->clock; 5477657c3a7SAlbert Herranz } 5487657c3a7SAlbert Herranz 54980872e21SWolfram Sang static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) 5507657c3a7SAlbert Herranz { 551e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 55219c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 55319c3a0efSyangbo lu unsigned int clock; 5547657c3a7SAlbert Herranz 55519c3a0efSyangbo lu if (esdhc->peripheral_clock) 55619c3a0efSyangbo lu clock = esdhc->peripheral_clock; 55719c3a0efSyangbo lu else 55819c3a0efSyangbo lu clock = pltfm_host->clock; 55919c3a0efSyangbo lu return clock / 256 / 16; 5607657c3a7SAlbert Herranz } 5617657c3a7SAlbert Herranz 562dd3f6983Syangbo lu static void esdhc_clock_enable(struct sdhci_host *host, bool enable) 563dd3f6983Syangbo lu { 564dd3f6983Syangbo lu u32 val; 565dd3f6983Syangbo lu ktime_t timeout; 566dd3f6983Syangbo lu 567dd3f6983Syangbo lu val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 568dd3f6983Syangbo lu 569dd3f6983Syangbo lu if (enable) 570dd3f6983Syangbo lu val |= ESDHC_CLOCK_SDCLKEN; 571dd3f6983Syangbo lu else 572dd3f6983Syangbo lu val &= ~ESDHC_CLOCK_SDCLKEN; 573dd3f6983Syangbo lu 574dd3f6983Syangbo lu sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL); 575dd3f6983Syangbo lu 576dd3f6983Syangbo lu /* Wait max 20 ms */ 577dd3f6983Syangbo lu timeout = ktime_add_ms(ktime_get(), 20); 578dd3f6983Syangbo lu val = ESDHC_CLOCK_STABLE; 579ea6d0273SAdrian Hunter while (1) { 580ea6d0273SAdrian Hunter bool timedout = ktime_after(ktime_get(), timeout); 581ea6d0273SAdrian Hunter 582ea6d0273SAdrian Hunter if (sdhci_readl(host, ESDHC_PRSSTAT) & val) 583ea6d0273SAdrian Hunter break; 584ea6d0273SAdrian Hunter if (timedout) { 585dd3f6983Syangbo lu pr_err("%s: Internal clock never stabilised.\n", 586dd3f6983Syangbo lu mmc_hostname(host->mmc)); 587dd3f6983Syangbo lu break; 588dd3f6983Syangbo lu } 589dd3f6983Syangbo lu udelay(10); 590dd3f6983Syangbo lu } 591dd3f6983Syangbo lu } 592dd3f6983Syangbo lu 5936e32f65cSYangbo Lu static void esdhc_flush_async_fifo(struct sdhci_host *host) 5946e32f65cSYangbo Lu { 5956e32f65cSYangbo Lu ktime_t timeout; 5966e32f65cSYangbo Lu u32 val; 5976e32f65cSYangbo Lu 5986e32f65cSYangbo Lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 5996e32f65cSYangbo Lu val |= ESDHC_FLUSH_ASYNC_FIFO; 6006e32f65cSYangbo Lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 6016e32f65cSYangbo Lu 6026e32f65cSYangbo Lu /* Wait max 20 ms */ 6036e32f65cSYangbo Lu timeout = ktime_add_ms(ktime_get(), 20); 6046e32f65cSYangbo Lu while (1) { 6056e32f65cSYangbo Lu bool timedout = ktime_after(ktime_get(), timeout); 6066e32f65cSYangbo Lu 6076e32f65cSYangbo Lu if (!(sdhci_readl(host, ESDHC_DMA_SYSCTL) & 6086e32f65cSYangbo Lu ESDHC_FLUSH_ASYNC_FIFO)) 6096e32f65cSYangbo Lu break; 6106e32f65cSYangbo Lu if (timedout) { 6116e32f65cSYangbo Lu pr_err("%s: flushing asynchronous FIFO timeout.\n", 6126e32f65cSYangbo Lu mmc_hostname(host->mmc)); 6136e32f65cSYangbo Lu break; 6146e32f65cSYangbo Lu } 6156e32f65cSYangbo Lu usleep_range(10, 20); 6166e32f65cSYangbo Lu } 6176e32f65cSYangbo Lu } 6186e32f65cSYangbo Lu 619f060bc9cSJerry Huang static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) 620f060bc9cSJerry Huang { 621f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 6228605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 623bd455029SJoakim Tjernlund int pre_div = 1; 624d31fc00aSDong Aisheng int div = 1; 6256079e63cSYangbo Lu int division; 626e145ac45Syangbo lu ktime_t timeout; 62767fdfbdfSyinbo.zhu long fixup = 0; 628d31fc00aSDong Aisheng u32 temp; 629d31fc00aSDong Aisheng 6301650d0c7SRussell King host->mmc->actual_clock = 0; 6311650d0c7SRussell King 632dd3f6983Syangbo lu if (clock == 0) { 633dd3f6983Syangbo lu esdhc_clock_enable(host, false); 634373073efSRussell King return; 635dd3f6983Syangbo lu } 636d31fc00aSDong Aisheng 63777bd2f6fSYangbo Lu /* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */ 638f4932cfdSyangbo lu if (esdhc->vendor_ver < VENDOR_V_23) 63977bd2f6fSYangbo Lu pre_div = 2; 64077bd2f6fSYangbo Lu 64167fdfbdfSyinbo.zhu if (host->mmc->card && mmc_card_sd(host->mmc->card) && 64267fdfbdfSyinbo.zhu esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) 64367fdfbdfSyinbo.zhu fixup = esdhc->clk_fixup->sd_dflt_max_clk; 64467fdfbdfSyinbo.zhu else if (esdhc->clk_fixup) 64567fdfbdfSyinbo.zhu fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; 646a627f025Syangbo lu 64767fdfbdfSyinbo.zhu if (fixup && clock > fixup) 64867fdfbdfSyinbo.zhu clock = fixup; 649f060bc9cSJerry Huang 650d31fc00aSDong Aisheng temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 651e87d2db2Syangbo lu temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | 652e87d2db2Syangbo lu ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); 653d31fc00aSDong Aisheng sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 654d31fc00aSDong Aisheng 655d31fc00aSDong Aisheng while (host->max_clk / pre_div / 16 > clock && pre_div < 256) 656d31fc00aSDong Aisheng pre_div *= 2; 657d31fc00aSDong Aisheng 658d31fc00aSDong Aisheng while (host->max_clk / pre_div / div > clock && div < 16) 659d31fc00aSDong Aisheng div++; 660d31fc00aSDong Aisheng 6616079e63cSYangbo Lu if (esdhc->quirk_limited_clk_division && 6626079e63cSYangbo Lu clock == MMC_HS200_MAX_DTR && 6636079e63cSYangbo Lu (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 || 6646079e63cSYangbo Lu host->flags & SDHCI_HS400_TUNING)) { 6656079e63cSYangbo Lu division = pre_div * div; 6666079e63cSYangbo Lu if (division <= 4) { 6676079e63cSYangbo Lu pre_div = 4; 6686079e63cSYangbo Lu div = 1; 6696079e63cSYangbo Lu } else if (division <= 8) { 6706079e63cSYangbo Lu pre_div = 4; 6716079e63cSYangbo Lu div = 2; 6726079e63cSYangbo Lu } else if (division <= 12) { 6736079e63cSYangbo Lu pre_div = 4; 6746079e63cSYangbo Lu div = 3; 6756079e63cSYangbo Lu } else { 676b11c36d5SColin Ian King pr_warn("%s: using unsupported clock division.\n", 6776079e63cSYangbo Lu mmc_hostname(host->mmc)); 6786079e63cSYangbo Lu } 6796079e63cSYangbo Lu } 6806079e63cSYangbo Lu 681d31fc00aSDong Aisheng dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", 682e76b8559SDong Aisheng clock, host->max_clk / pre_div / div); 683bd455029SJoakim Tjernlund host->mmc->actual_clock = host->max_clk / pre_div / div; 684b1f378abSYinbo Zhu esdhc->div_ratio = pre_div * div; 685d31fc00aSDong Aisheng pre_div >>= 1; 686d31fc00aSDong Aisheng div--; 687d31fc00aSDong Aisheng 688d31fc00aSDong Aisheng temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 689d31fc00aSDong Aisheng temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN 690d31fc00aSDong Aisheng | (div << ESDHC_DIVIDER_SHIFT) 691d31fc00aSDong Aisheng | (pre_div << ESDHC_PREDIV_SHIFT)); 692d31fc00aSDong Aisheng sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 693e87d2db2Syangbo lu 69454e08d9aSYangbo Lu if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && 69554e08d9aSYangbo Lu clock == MMC_HS200_MAX_DTR) { 69654e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 69754e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_MODE, ESDHC_TBCTL); 69854e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_SDCLKCTL); 69954e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_CMD_CLK_CTL, ESDHC_SDCLKCTL); 70054e08d9aSYangbo Lu esdhc_clock_enable(host, true); 70154e08d9aSYangbo Lu 70254e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_DLLCFG0); 70358d0bf84SYangbo Lu temp |= ESDHC_DLL_ENABLE; 70458d0bf84SYangbo Lu if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) 70558d0bf84SYangbo Lu temp |= ESDHC_DLL_FREQ_SEL; 70654e08d9aSYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 70754e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 70854e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL); 70954e08d9aSYangbo Lu 71054e08d9aSYangbo Lu esdhc_clock_enable(host, false); 7116e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 71254e08d9aSYangbo Lu } 71354e08d9aSYangbo Lu 714e87d2db2Syangbo lu /* Wait max 20 ms */ 715e145ac45Syangbo lu timeout = ktime_add_ms(ktime_get(), 20); 716ea6d0273SAdrian Hunter while (1) { 717ea6d0273SAdrian Hunter bool timedout = ktime_after(ktime_get(), timeout); 718ea6d0273SAdrian Hunter 719ea6d0273SAdrian Hunter if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) 720ea6d0273SAdrian Hunter break; 721ea6d0273SAdrian Hunter if (timedout) { 722e87d2db2Syangbo lu pr_err("%s: Internal clock never stabilised.\n", 723e87d2db2Syangbo lu mmc_hostname(host->mmc)); 724e87d2db2Syangbo lu return; 725e87d2db2Syangbo lu } 726e145ac45Syangbo lu udelay(10); 727f060bc9cSJerry Huang } 728f060bc9cSJerry Huang 72954e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 730e87d2db2Syangbo lu temp |= ESDHC_CLOCK_SDCLKEN; 731e87d2db2Syangbo lu sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 732e87d2db2Syangbo lu } 733e87d2db2Syangbo lu 7342317f56cSRussell King static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) 73566b50a00SOded Gabbay { 73666b50a00SOded Gabbay u32 ctrl; 73766b50a00SOded Gabbay 738f4932cfdSyangbo lu ctrl = sdhci_readl(host, ESDHC_PROCTL); 739f4932cfdSyangbo lu ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK); 74066b50a00SOded Gabbay switch (width) { 74166b50a00SOded Gabbay case MMC_BUS_WIDTH_8: 742f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_8BITBUS; 74366b50a00SOded Gabbay break; 74466b50a00SOded Gabbay 74566b50a00SOded Gabbay case MMC_BUS_WIDTH_4: 746f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_4BITBUS; 74766b50a00SOded Gabbay break; 74866b50a00SOded Gabbay 74966b50a00SOded Gabbay default: 75066b50a00SOded Gabbay break; 75166b50a00SOded Gabbay } 75266b50a00SOded Gabbay 753f4932cfdSyangbo lu sdhci_writel(host, ctrl, ESDHC_PROCTL); 75466b50a00SOded Gabbay } 75566b50a00SOded Gabbay 756304f0a98SAlessio Igor Bogani static void esdhc_reset(struct sdhci_host *host, u8 mask) 757304f0a98SAlessio Igor Bogani { 75848e304ccSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 75948e304ccSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 760f2bc6000Syinbo.zhu u32 val; 761f2bc6000Syinbo.zhu 762304f0a98SAlessio Igor Bogani sdhci_reset(host, mask); 763304f0a98SAlessio Igor Bogani 764304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 765304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 766f2bc6000Syinbo.zhu 767f2bc6000Syinbo.zhu if (mask & SDHCI_RESET_ALL) { 768f2bc6000Syinbo.zhu val = sdhci_readl(host, ESDHC_TBCTL); 769f2bc6000Syinbo.zhu val &= ~ESDHC_TB_EN; 770f2bc6000Syinbo.zhu sdhci_writel(host, val, ESDHC_TBCTL); 77148e304ccSYangbo Lu 77248e304ccSYangbo Lu if (esdhc->quirk_unreliable_pulse_detection) { 77348e304ccSYangbo Lu val = sdhci_readl(host, ESDHC_DLLCFG1); 77448e304ccSYangbo Lu val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL; 77548e304ccSYangbo Lu sdhci_writel(host, val, ESDHC_DLLCFG1); 77648e304ccSYangbo Lu } 777f2bc6000Syinbo.zhu } 778304f0a98SAlessio Igor Bogani } 779304f0a98SAlessio Igor Bogani 780ea35645aSyangbo lu /* The SCFG, Supplemental Configuration Unit, provides SoC specific 781ea35645aSyangbo lu * configuration and status registers for the device. There is a 782ea35645aSyangbo lu * SDHC IO VSEL control register on SCFG for some platforms. It's 783ea35645aSyangbo lu * used to support SDHC IO voltage switching. 784ea35645aSyangbo lu */ 785ea35645aSyangbo lu static const struct of_device_id scfg_device_ids[] = { 786ea35645aSyangbo lu { .compatible = "fsl,t1040-scfg", }, 787ea35645aSyangbo lu { .compatible = "fsl,ls1012a-scfg", }, 788ea35645aSyangbo lu { .compatible = "fsl,ls1046a-scfg", }, 789ea35645aSyangbo lu {} 790ea35645aSyangbo lu }; 791ea35645aSyangbo lu 792ea35645aSyangbo lu /* SDHC IO VSEL control register definition */ 793ea35645aSyangbo lu #define SCFG_SDHCIOVSELCR 0x408 794ea35645aSyangbo lu #define SDHCIOVSELCR_TGLEN 0x80000000 795ea35645aSyangbo lu #define SDHCIOVSELCR_VSELVAL 0x60000000 796ea35645aSyangbo lu #define SDHCIOVSELCR_SDHC_VS 0x00000001 797ea35645aSyangbo lu 798ea35645aSyangbo lu static int esdhc_signal_voltage_switch(struct mmc_host *mmc, 799ea35645aSyangbo lu struct mmc_ios *ios) 800ea35645aSyangbo lu { 801ea35645aSyangbo lu struct sdhci_host *host = mmc_priv(mmc); 802ea35645aSyangbo lu struct device_node *scfg_node; 803ea35645aSyangbo lu void __iomem *scfg_base = NULL; 804ea35645aSyangbo lu u32 sdhciovselcr; 805ea35645aSyangbo lu u32 val; 806ea35645aSyangbo lu 807ea35645aSyangbo lu /* 808ea35645aSyangbo lu * Signal Voltage Switching is only applicable for Host Controllers 809ea35645aSyangbo lu * v3.00 and above. 810ea35645aSyangbo lu */ 811ea35645aSyangbo lu if (host->version < SDHCI_SPEC_300) 812ea35645aSyangbo lu return 0; 813ea35645aSyangbo lu 814ea35645aSyangbo lu val = sdhci_readl(host, ESDHC_PROCTL); 815ea35645aSyangbo lu 816ea35645aSyangbo lu switch (ios->signal_voltage) { 817ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_330: 818ea35645aSyangbo lu val &= ~ESDHC_VOLT_SEL; 819ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 820ea35645aSyangbo lu return 0; 821ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_180: 822ea35645aSyangbo lu scfg_node = of_find_matching_node(NULL, scfg_device_ids); 823ea35645aSyangbo lu if (scfg_node) 824ea35645aSyangbo lu scfg_base = of_iomap(scfg_node, 0); 825ea35645aSyangbo lu if (scfg_base) { 826ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 827ea35645aSyangbo lu SDHCIOVSELCR_VSELVAL; 828ea35645aSyangbo lu iowrite32be(sdhciovselcr, 829ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 830ea35645aSyangbo lu 831ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 832ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 833ea35645aSyangbo lu mdelay(5); 834ea35645aSyangbo lu 835ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 836ea35645aSyangbo lu SDHCIOVSELCR_SDHC_VS; 837ea35645aSyangbo lu iowrite32be(sdhciovselcr, 838ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 839ea35645aSyangbo lu iounmap(scfg_base); 840ea35645aSyangbo lu } else { 841ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 842ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 843ea35645aSyangbo lu } 844ea35645aSyangbo lu return 0; 845ea35645aSyangbo lu default: 846ea35645aSyangbo lu return 0; 847ea35645aSyangbo lu } 848ea35645aSyangbo lu } 849ea35645aSyangbo lu 85022dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type1[] = { 85122dc132dSYangbo Lu { .family = "QorIQ T1023", .revision = "1.0", }, 852b1f378abSYinbo Zhu { .family = "QorIQ T1040", .revision = "1.0", }, 853b1f378abSYinbo Zhu { .family = "QorIQ T2080", .revision = "1.0", }, 854b1f378abSYinbo Zhu { .family = "QorIQ LS1021A", .revision = "1.0", }, 85522dc132dSYangbo Lu { }, 85622dc132dSYangbo Lu }; 85722dc132dSYangbo Lu 85822dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type2[] = { 859b1f378abSYinbo Zhu { .family = "QorIQ LS1012A", .revision = "1.0", }, 860b1f378abSYinbo Zhu { .family = "QorIQ LS1043A", .revision = "1.*", }, 861b1f378abSYinbo Zhu { .family = "QorIQ LS1046A", .revision = "1.0", }, 86222dc132dSYangbo Lu { .family = "QorIQ LS1080A", .revision = "1.0", }, 86322dc132dSYangbo Lu { .family = "QorIQ LS2080A", .revision = "1.0", }, 86422dc132dSYangbo Lu { .family = "QorIQ LA1575A", .revision = "1.0", }, 865b1f378abSYinbo Zhu { }, 866b1f378abSYinbo Zhu }; 867b1f378abSYinbo Zhu 86854e08d9aSYangbo Lu static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable) 869ba49cbd0Syangbo lu { 870ba49cbd0Syangbo lu u32 val; 871ba49cbd0Syangbo lu 872ba49cbd0Syangbo lu esdhc_clock_enable(host, false); 8736e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 874ba49cbd0Syangbo lu 875ba49cbd0Syangbo lu val = sdhci_readl(host, ESDHC_TBCTL); 87654e08d9aSYangbo Lu if (enable) 877ba49cbd0Syangbo lu val |= ESDHC_TB_EN; 87854e08d9aSYangbo Lu else 87954e08d9aSYangbo Lu val &= ~ESDHC_TB_EN; 880ba49cbd0Syangbo lu sdhci_writel(host, val, ESDHC_TBCTL); 881ba49cbd0Syangbo lu 88254e08d9aSYangbo Lu esdhc_clock_enable(host, true); 88354e08d9aSYangbo Lu } 88454e08d9aSYangbo Lu 88522dc132dSYangbo Lu static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start, 88622dc132dSYangbo Lu u8 *window_end) 88722dc132dSYangbo Lu { 88822dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 88922dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 89022dc132dSYangbo Lu u8 tbstat_15_8, tbstat_7_0; 89122dc132dSYangbo Lu u32 val; 89222dc132dSYangbo Lu 89322dc132dSYangbo Lu if (esdhc->quirk_tuning_erratum_type1) { 89422dc132dSYangbo Lu *window_start = 5 * esdhc->div_ratio; 89522dc132dSYangbo Lu *window_end = 3 * esdhc->div_ratio; 89622dc132dSYangbo Lu return; 89722dc132dSYangbo Lu } 89822dc132dSYangbo Lu 89922dc132dSYangbo Lu /* Write TBCTL[11:8]=4'h8 */ 90022dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 90122dc132dSYangbo Lu val &= ~(0xf << 8); 90222dc132dSYangbo Lu val |= 8 << 8; 90322dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 90422dc132dSYangbo Lu 90522dc132dSYangbo Lu mdelay(1); 90622dc132dSYangbo Lu 90722dc132dSYangbo Lu /* Read TBCTL[31:0] register and rewrite again */ 90822dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 90922dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 91022dc132dSYangbo Lu 91122dc132dSYangbo Lu mdelay(1); 91222dc132dSYangbo Lu 91322dc132dSYangbo Lu /* Read the TBSTAT[31:0] register twice */ 91422dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 91522dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 91622dc132dSYangbo Lu 91722dc132dSYangbo Lu /* Reset data lines by setting ESDHCCTL[RSTD] */ 91822dc132dSYangbo Lu sdhci_reset(host, SDHCI_RESET_DATA); 91922dc132dSYangbo Lu /* Write 32'hFFFF_FFFF to IRQSTAT register */ 92022dc132dSYangbo Lu sdhci_writel(host, 0xFFFFFFFF, SDHCI_INT_STATUS); 92122dc132dSYangbo Lu 92222dc132dSYangbo Lu /* If TBSTAT[15:8]-TBSTAT[7:0] > 4 * div_ratio 92322dc132dSYangbo Lu * or TBSTAT[7:0]-TBSTAT[15:8] > 4 * div_ratio, 92422dc132dSYangbo Lu * then program TBPTR[TB_WNDW_END_PTR] = 4 * div_ratio 92522dc132dSYangbo Lu * and program TBPTR[TB_WNDW_START_PTR] = 8 * div_ratio. 92622dc132dSYangbo Lu */ 92722dc132dSYangbo Lu tbstat_7_0 = val & 0xff; 92822dc132dSYangbo Lu tbstat_15_8 = (val >> 8) & 0xff; 92922dc132dSYangbo Lu 93022dc132dSYangbo Lu if (abs(tbstat_15_8 - tbstat_7_0) > (4 * esdhc->div_ratio)) { 93122dc132dSYangbo Lu *window_start = 8 * esdhc->div_ratio; 93222dc132dSYangbo Lu *window_end = 4 * esdhc->div_ratio; 93322dc132dSYangbo Lu } else { 93422dc132dSYangbo Lu *window_start = 5 * esdhc->div_ratio; 93522dc132dSYangbo Lu *window_end = 3 * esdhc->div_ratio; 93622dc132dSYangbo Lu } 93722dc132dSYangbo Lu } 93822dc132dSYangbo Lu 93922dc132dSYangbo Lu static int esdhc_execute_sw_tuning(struct mmc_host *mmc, u32 opcode, 94022dc132dSYangbo Lu u8 window_start, u8 window_end) 94122dc132dSYangbo Lu { 94222dc132dSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 94322dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 94422dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 94522dc132dSYangbo Lu u32 val; 94622dc132dSYangbo Lu int ret; 94722dc132dSYangbo Lu 94822dc132dSYangbo Lu /* Program TBPTR[TB_WNDW_END_PTR] and TBPTR[TB_WNDW_START_PTR] */ 94922dc132dSYangbo Lu val = ((u32)window_start << ESDHC_WNDW_STRT_PTR_SHIFT) & 95022dc132dSYangbo Lu ESDHC_WNDW_STRT_PTR_MASK; 95122dc132dSYangbo Lu val |= window_end & ESDHC_WNDW_END_PTR_MASK; 95222dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBPTR); 95322dc132dSYangbo Lu 95422dc132dSYangbo Lu /* Program the software tuning mode by setting TBCTL[TB_MODE]=2'h3 */ 95522dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 95622dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 95722dc132dSYangbo Lu val |= ESDHC_TB_MODE_SW; 95822dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 95922dc132dSYangbo Lu 96022dc132dSYangbo Lu esdhc->in_sw_tuning = true; 96122dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 96222dc132dSYangbo Lu esdhc->in_sw_tuning = false; 96322dc132dSYangbo Lu return ret; 96422dc132dSYangbo Lu } 96522dc132dSYangbo Lu 96654e08d9aSYangbo Lu static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) 96754e08d9aSYangbo Lu { 96854e08d9aSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 96954e08d9aSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 97054e08d9aSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 97122dc132dSYangbo Lu u8 window_start, window_end; 97222dc132dSYangbo Lu int ret, retries = 1; 97354e08d9aSYangbo Lu bool hs400_tuning; 97404509d77SYangbo Lu unsigned int clk; 97554e08d9aSYangbo Lu u32 val; 97654e08d9aSYangbo Lu 97704509d77SYangbo Lu /* For tuning mode, the sd clock divisor value 97804509d77SYangbo Lu * must be larger than 3 according to reference manual. 97904509d77SYangbo Lu */ 98004509d77SYangbo Lu clk = esdhc->peripheral_clock / 3; 98104509d77SYangbo Lu if (host->clock > clk) 98204509d77SYangbo Lu esdhc_of_set_clock(host, clk); 98304509d77SYangbo Lu 98454e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 98554e08d9aSYangbo Lu 98654e08d9aSYangbo Lu hs400_tuning = host->flags & SDHCI_HS400_TUNING; 98754e08d9aSYangbo Lu 98822dc132dSYangbo Lu do { 98922dc132dSYangbo Lu if (esdhc->quirk_limited_clk_division && 99022dc132dSYangbo Lu hs400_tuning) 99122dc132dSYangbo Lu esdhc_of_set_clock(host, host->clock); 99222dc132dSYangbo Lu 99322dc132dSYangbo Lu /* Do HW tuning */ 99422dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 99522dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 99622dc132dSYangbo Lu val |= ESDHC_TB_MODE_3; 99722dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 99822dc132dSYangbo Lu 99922dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 100022dc132dSYangbo Lu if (ret) 100122dc132dSYangbo Lu break; 100222dc132dSYangbo Lu 100322dc132dSYangbo Lu /* If HW tuning fails and triggers erratum, 100422dc132dSYangbo Lu * try workaround. 100522dc132dSYangbo Lu */ 100622dc132dSYangbo Lu ret = host->tuning_err; 100722dc132dSYangbo Lu if (ret == -EAGAIN && 100822dc132dSYangbo Lu (esdhc->quirk_tuning_erratum_type1 || 100922dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2)) { 101022dc132dSYangbo Lu /* Recover HS400 tuning flag */ 101122dc132dSYangbo Lu if (hs400_tuning) 101222dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 101322dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try SW tuning!\n", 101422dc132dSYangbo Lu mmc_hostname(mmc)); 101522dc132dSYangbo Lu /* Do SW tuning */ 101622dc132dSYangbo Lu esdhc_prepare_sw_tuning(host, &window_start, 101722dc132dSYangbo Lu &window_end); 101822dc132dSYangbo Lu ret = esdhc_execute_sw_tuning(mmc, opcode, 101922dc132dSYangbo Lu window_start, 102022dc132dSYangbo Lu window_end); 102122dc132dSYangbo Lu if (ret) 102222dc132dSYangbo Lu break; 102322dc132dSYangbo Lu 102422dc132dSYangbo Lu /* Retry both HW/SW tuning with reduced clock. */ 102522dc132dSYangbo Lu ret = host->tuning_err; 102622dc132dSYangbo Lu if (ret == -EAGAIN && retries) { 102722dc132dSYangbo Lu /* Recover HS400 tuning flag */ 102822dc132dSYangbo Lu if (hs400_tuning) 102922dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 103022dc132dSYangbo Lu 103122dc132dSYangbo Lu clk = host->max_clk / (esdhc->div_ratio + 1); 103222dc132dSYangbo Lu esdhc_of_set_clock(host, clk); 103322dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try tuning with reduced clock!\n", 103422dc132dSYangbo Lu mmc_hostname(mmc)); 103522dc132dSYangbo Lu } else { 103622dc132dSYangbo Lu break; 103722dc132dSYangbo Lu } 103822dc132dSYangbo Lu } else { 103922dc132dSYangbo Lu break; 104022dc132dSYangbo Lu } 104122dc132dSYangbo Lu } while (retries--); 104222dc132dSYangbo Lu 104322dc132dSYangbo Lu if (ret) { 104422dc132dSYangbo Lu esdhc_tuning_block_enable(host, false); 104522dc132dSYangbo Lu } else if (hs400_tuning) { 104654e08d9aSYangbo Lu val = sdhci_readl(host, ESDHC_SDTIMNGCTL); 104754e08d9aSYangbo Lu val |= ESDHC_FLW_CTL_BG; 104854e08d9aSYangbo Lu sdhci_writel(host, val, ESDHC_SDTIMNGCTL); 104954e08d9aSYangbo Lu } 105054e08d9aSYangbo Lu 105154e08d9aSYangbo Lu return ret; 105254e08d9aSYangbo Lu } 105354e08d9aSYangbo Lu 105454e08d9aSYangbo Lu static void esdhc_set_uhs_signaling(struct sdhci_host *host, 105554e08d9aSYangbo Lu unsigned int timing) 105654e08d9aSYangbo Lu { 105754e08d9aSYangbo Lu if (timing == MMC_TIMING_MMC_HS400) 105854e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 105954e08d9aSYangbo Lu else 106054e08d9aSYangbo Lu sdhci_set_uhs_signaling(host, timing); 1061ba49cbd0Syangbo lu } 1062ba49cbd0Syangbo lu 1063b214fe59SYinbo Zhu static u32 esdhc_irq(struct sdhci_host *host, u32 intmask) 1064b214fe59SYinbo Zhu { 1065b214fe59SYinbo Zhu u32 command; 1066b214fe59SYinbo Zhu 1067b214fe59SYinbo Zhu if (of_find_compatible_node(NULL, NULL, 1068b214fe59SYinbo Zhu "fsl,p2020-esdhc")) { 1069b214fe59SYinbo Zhu command = SDHCI_GET_CMD(sdhci_readw(host, 1070b214fe59SYinbo Zhu SDHCI_COMMAND)); 1071b214fe59SYinbo Zhu if (command == MMC_WRITE_MULTIPLE_BLOCK && 1072b214fe59SYinbo Zhu sdhci_readw(host, SDHCI_BLOCK_COUNT) && 1073b214fe59SYinbo Zhu intmask & SDHCI_INT_DATA_END) { 1074b214fe59SYinbo Zhu intmask &= ~SDHCI_INT_DATA_END; 1075b214fe59SYinbo Zhu sdhci_writel(host, SDHCI_INT_DATA_END, 1076b214fe59SYinbo Zhu SDHCI_INT_STATUS); 1077b214fe59SYinbo Zhu } 1078b214fe59SYinbo Zhu } 1079b214fe59SYinbo Zhu return intmask; 1080b214fe59SYinbo Zhu } 1081b214fe59SYinbo Zhu 10829e48b336SUlf Hansson #ifdef CONFIG_PM_SLEEP 1083723f7924SRussell King static u32 esdhc_proctl; 1084723f7924SRussell King static int esdhc_of_suspend(struct device *dev) 1085723f7924SRussell King { 1086723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1087723f7924SRussell King 1088f4932cfdSyangbo lu esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL); 1089723f7924SRussell King 1090d38dcad4SAdrian Hunter if (host->tuning_mode != SDHCI_TUNING_MODE_3) 1091d38dcad4SAdrian Hunter mmc_retune_needed(host->mmc); 1092d38dcad4SAdrian Hunter 1093723f7924SRussell King return sdhci_suspend_host(host); 1094723f7924SRussell King } 1095723f7924SRussell King 109606732b84SUlf Hansson static int esdhc_of_resume(struct device *dev) 1097723f7924SRussell King { 1098723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1099723f7924SRussell King int ret = sdhci_resume_host(host); 1100723f7924SRussell King 1101723f7924SRussell King if (ret == 0) { 1102723f7924SRussell King /* Isn't this already done by sdhci_resume_host() ? --rmk */ 1103723f7924SRussell King esdhc_of_enable_dma(host); 1104f4932cfdSyangbo lu sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); 1105723f7924SRussell King } 1106723f7924SRussell King return ret; 1107723f7924SRussell King } 1108723f7924SRussell King #endif 1109723f7924SRussell King 11109e48b336SUlf Hansson static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, 11119e48b336SUlf Hansson esdhc_of_suspend, 11129e48b336SUlf Hansson esdhc_of_resume); 11139e48b336SUlf Hansson 1114f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_be_ops = { 1115f4932cfdSyangbo lu .read_l = esdhc_be_readl, 1116f4932cfdSyangbo lu .read_w = esdhc_be_readw, 1117f4932cfdSyangbo lu .read_b = esdhc_be_readb, 1118f4932cfdSyangbo lu .write_l = esdhc_be_writel, 1119f4932cfdSyangbo lu .write_w = esdhc_be_writew, 1120f4932cfdSyangbo lu .write_b = esdhc_be_writeb, 1121f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1122f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1123f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1124f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1125f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1126f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1127f4932cfdSyangbo lu .reset = esdhc_reset, 112854e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1129b214fe59SYinbo Zhu .irq = esdhc_irq, 1130f4932cfdSyangbo lu }; 1131f4932cfdSyangbo lu 1132f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_le_ops = { 1133f4932cfdSyangbo lu .read_l = esdhc_le_readl, 1134f4932cfdSyangbo lu .read_w = esdhc_le_readw, 1135f4932cfdSyangbo lu .read_b = esdhc_le_readb, 1136f4932cfdSyangbo lu .write_l = esdhc_le_writel, 1137f4932cfdSyangbo lu .write_w = esdhc_le_writew, 1138f4932cfdSyangbo lu .write_b = esdhc_le_writeb, 1139f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1140f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1141f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1142f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1143f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1144f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1145f4932cfdSyangbo lu .reset = esdhc_reset, 114654e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1147b214fe59SYinbo Zhu .irq = esdhc_irq, 1148f4932cfdSyangbo lu }; 1149f4932cfdSyangbo lu 1150f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { 1151e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1152e9acc77dSyangbo lu #ifdef CONFIG_PPC 1153e9acc77dSyangbo lu SDHCI_QUIRK_BROKEN_CARD_DETECTION | 1154e9acc77dSyangbo lu #endif 1155e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1156e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1157f4932cfdSyangbo lu .ops = &sdhci_esdhc_be_ops, 11587657c3a7SAlbert Herranz }; 115938576af1SShawn Guo 1160f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = { 1161e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1162e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1163e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1164f4932cfdSyangbo lu .ops = &sdhci_esdhc_le_ops, 1165f4932cfdSyangbo lu }; 1166f4932cfdSyangbo lu 1167151ede40Syangbo lu static struct soc_device_attribute soc_incorrect_hostver[] = { 1168151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "1.0", }, 1169151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "2.0", }, 1170151ede40Syangbo lu { }, 1171151ede40Syangbo lu }; 1172151ede40Syangbo lu 11736079e63cSYangbo Lu static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = { 11746079e63cSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 11758e9a6919SYinbo Zhu { .family = "QorIQ LX2160A", .revision = "2.0", }, 11765f3ad196SYinbo Zhu { .family = "QorIQ LS1028A", .revision = "1.0", }, 11776079e63cSYangbo Lu { }, 11786079e63cSYangbo Lu }; 11796079e63cSYangbo Lu 118048e304ccSYangbo Lu static struct soc_device_attribute soc_unreliable_pulse_detection[] = { 118148e304ccSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 118248e304ccSYangbo Lu { }, 118348e304ccSYangbo Lu }; 118448e304ccSYangbo Lu 1185f4932cfdSyangbo lu static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) 1186f4932cfdSyangbo lu { 118767fdfbdfSyinbo.zhu const struct of_device_id *match; 1188f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host; 1189f4932cfdSyangbo lu struct sdhci_esdhc *esdhc; 119019c3a0efSyangbo lu struct device_node *np; 119119c3a0efSyangbo lu struct clk *clk; 119219c3a0efSyangbo lu u32 val; 1193f4932cfdSyangbo lu u16 host_ver; 1194f4932cfdSyangbo lu 1195f4932cfdSyangbo lu pltfm_host = sdhci_priv(host); 11968605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 1197f4932cfdSyangbo lu 1198f4932cfdSyangbo lu host_ver = sdhci_readw(host, SDHCI_HOST_VERSION); 1199f4932cfdSyangbo lu esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> 1200f4932cfdSyangbo lu SDHCI_VENDOR_VER_SHIFT; 1201f4932cfdSyangbo lu esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; 1202151ede40Syangbo lu if (soc_device_match(soc_incorrect_hostver)) 1203151ede40Syangbo lu esdhc->quirk_incorrect_hostver = true; 1204151ede40Syangbo lu else 1205151ede40Syangbo lu esdhc->quirk_incorrect_hostver = false; 120619c3a0efSyangbo lu 12076079e63cSYangbo Lu if (soc_device_match(soc_fixup_sdhc_clkdivs)) 12086079e63cSYangbo Lu esdhc->quirk_limited_clk_division = true; 12096079e63cSYangbo Lu else 12106079e63cSYangbo Lu esdhc->quirk_limited_clk_division = false; 12116079e63cSYangbo Lu 121248e304ccSYangbo Lu if (soc_device_match(soc_unreliable_pulse_detection)) 121348e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = true; 121448e304ccSYangbo Lu else 121548e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = false; 121648e304ccSYangbo Lu 121767fdfbdfSyinbo.zhu match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); 121867fdfbdfSyinbo.zhu if (match) 121967fdfbdfSyinbo.zhu esdhc->clk_fixup = match->data; 122019c3a0efSyangbo lu np = pdev->dev.of_node; 122119c3a0efSyangbo lu clk = of_clk_get(np, 0); 122219c3a0efSyangbo lu if (!IS_ERR(clk)) { 122319c3a0efSyangbo lu /* 122419c3a0efSyangbo lu * esdhc->peripheral_clock would be assigned with a value 122519c3a0efSyangbo lu * which is eSDHC base clock when use periperal clock. 1226791463baSYangbo Lu * For some platforms, the clock value got by common clk 1227791463baSYangbo Lu * API is peripheral clock while the eSDHC base clock is 1228791463baSYangbo Lu * 1/2 peripheral clock. 122919c3a0efSyangbo lu */ 1230791463baSYangbo Lu if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || 1231791463baSYangbo Lu of_device_is_compatible(np, "fsl,ls1028a-esdhc")) 123219c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk) / 2; 123319c3a0efSyangbo lu else 123419c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk); 123519c3a0efSyangbo lu 123619c3a0efSyangbo lu clk_put(clk); 123719c3a0efSyangbo lu } 123819c3a0efSyangbo lu 123919c3a0efSyangbo lu if (esdhc->peripheral_clock) { 124019c3a0efSyangbo lu esdhc_clock_enable(host, false); 124119c3a0efSyangbo lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 124219c3a0efSyangbo lu val |= ESDHC_PERIPHERAL_CLK_SEL; 124319c3a0efSyangbo lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 124419c3a0efSyangbo lu esdhc_clock_enable(host, true); 124519c3a0efSyangbo lu } 1246f4932cfdSyangbo lu } 1247f4932cfdSyangbo lu 124854e08d9aSYangbo Lu static int esdhc_hs400_prepare_ddr(struct mmc_host *mmc) 124954e08d9aSYangbo Lu { 125054e08d9aSYangbo Lu esdhc_tuning_block_enable(mmc_priv(mmc), false); 125154e08d9aSYangbo Lu return 0; 125254e08d9aSYangbo Lu } 125354e08d9aSYangbo Lu 1254c3be1efdSBill Pemberton static int sdhci_esdhc_probe(struct platform_device *pdev) 125538576af1SShawn Guo { 125666b50a00SOded Gabbay struct sdhci_host *host; 1257dcaff04dSOded Gabbay struct device_node *np; 12581ef5e49eSyangbo lu struct sdhci_pltfm_host *pltfm_host; 12591ef5e49eSyangbo lu struct sdhci_esdhc *esdhc; 126066b50a00SOded Gabbay int ret; 126166b50a00SOded Gabbay 1262f4932cfdSyangbo lu np = pdev->dev.of_node; 1263f4932cfdSyangbo lu 1264150d4240SJulia Lawall if (of_property_read_bool(np, "little-endian")) 12658605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, 12668605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1267f4932cfdSyangbo lu else 12688605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, 12698605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1270f4932cfdSyangbo lu 127166b50a00SOded Gabbay if (IS_ERR(host)) 127266b50a00SOded Gabbay return PTR_ERR(host); 127366b50a00SOded Gabbay 1274ea35645aSyangbo lu host->mmc_host_ops.start_signal_voltage_switch = 1275ea35645aSyangbo lu esdhc_signal_voltage_switch; 1276ba49cbd0Syangbo lu host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; 127754e08d9aSYangbo Lu host->mmc_host_ops.hs400_prepare_ddr = esdhc_hs400_prepare_ddr; 12786b236f37Syangbo lu host->tuning_delay = 1; 1279ea35645aSyangbo lu 1280f4932cfdSyangbo lu esdhc_init(pdev, host); 1281f4932cfdSyangbo lu 128266b50a00SOded Gabbay sdhci_get_of_property(pdev); 128366b50a00SOded Gabbay 12841ef5e49eSyangbo lu pltfm_host = sdhci_priv(host); 12858605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 128622dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type1)) 128722dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = true; 1288b1f378abSYinbo Zhu else 128922dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = false; 129022dc132dSYangbo Lu 129122dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type2)) 129222dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = true; 129322dc132dSYangbo Lu else 129422dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = false; 1295b1f378abSYinbo Zhu 12961ef5e49eSyangbo lu if (esdhc->vendor_ver == VENDOR_V_22) 12971ef5e49eSyangbo lu host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; 12981ef5e49eSyangbo lu 12991ef5e49eSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) 13001ef5e49eSyangbo lu host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; 13011ef5e49eSyangbo lu 130205cb6b2aSYinbo Zhu if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { 1303*fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; 1304*fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 130505cb6b2aSYinbo Zhu } 1306a46e4271SYinbo Zhu 130774fd5e30SYangbo Lu if (of_device_is_compatible(np, "fsl,p5040-esdhc") || 130874fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p5020-esdhc") || 130974fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p4080-esdhc") || 131074fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p1020-esdhc") || 1311e9acc77dSyangbo lu of_device_is_compatible(np, "fsl,t1040-esdhc")) 131274fd5e30SYangbo Lu host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; 131374fd5e30SYangbo Lu 1314a22950c8Syangbo lu if (of_device_is_compatible(np, "fsl,ls1021a-esdhc")) 1315a22950c8Syangbo lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 1316a22950c8Syangbo lu 13171f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = false; 1318dcaff04dSOded Gabbay if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 1319dcaff04dSOded Gabbay /* 1320dcaff04dSOded Gabbay * Freescale messed up with P2020 as it has a non-standard 1321dcaff04dSOded Gabbay * host control register 1322dcaff04dSOded Gabbay */ 1323dcaff04dSOded Gabbay host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; 13241f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = true; 1325dcaff04dSOded Gabbay } 1326dcaff04dSOded Gabbay 132766b50a00SOded Gabbay /* call to generic mmc_of_parse to support additional capabilities */ 1328f0991408SUlf Hansson ret = mmc_of_parse(host->mmc); 1329f0991408SUlf Hansson if (ret) 1330f0991408SUlf Hansson goto err; 1331f0991408SUlf Hansson 1332490104acSHaijun Zhang mmc_of_parse_voltage(np, &host->ocr_mask); 133366b50a00SOded Gabbay 133466b50a00SOded Gabbay ret = sdhci_add_host(host); 133566b50a00SOded Gabbay if (ret) 1336f0991408SUlf Hansson goto err; 133766b50a00SOded Gabbay 1338f0991408SUlf Hansson return 0; 1339f0991408SUlf Hansson err: 1340f0991408SUlf Hansson sdhci_pltfm_free(pdev); 134166b50a00SOded Gabbay return ret; 134238576af1SShawn Guo } 134338576af1SShawn Guo 134438576af1SShawn Guo static struct platform_driver sdhci_esdhc_driver = { 134538576af1SShawn Guo .driver = { 134638576af1SShawn Guo .name = "sdhci-esdhc", 134738576af1SShawn Guo .of_match_table = sdhci_esdhc_of_match, 13489e48b336SUlf Hansson .pm = &esdhc_of_dev_pm_ops, 134938576af1SShawn Guo }, 135038576af1SShawn Guo .probe = sdhci_esdhc_probe, 1351caebcae9SKevin Hao .remove = sdhci_pltfm_unregister, 135238576af1SShawn Guo }; 135338576af1SShawn Guo 1354d1f81a64SAxel Lin module_platform_driver(sdhci_esdhc_driver); 135538576af1SShawn Guo 135638576af1SShawn Guo MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); 135738576af1SShawn Guo MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " 135838576af1SShawn Guo "Anton Vorontsov <avorontsov@ru.mvista.com>"); 135938576af1SShawn Guo MODULE_LICENSE("GPL v2"); 1360