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; 83f667216cSYangbo Lu bool quirk_delay_before_data_reset; 8422dc132dSYangbo Lu bool in_sw_tuning; 8519c3a0efSyangbo lu unsigned int peripheral_clock; 8667fdfbdfSyinbo.zhu const struct esdhc_clk_fixup *clk_fixup; 87b1f378abSYinbo Zhu u32 div_ratio; 88f4932cfdSyangbo lu }; 89f4932cfdSyangbo lu 90f4932cfdSyangbo lu /** 91f4932cfdSyangbo lu * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register 92f4932cfdSyangbo lu * to make it compatible with SD spec. 93f4932cfdSyangbo lu * 94f4932cfdSyangbo lu * @host: pointer to sdhci_host 95f4932cfdSyangbo lu * @spec_reg: SD spec register address 96f4932cfdSyangbo lu * @value: 32bit eSDHC register value on spec_reg address 97f4932cfdSyangbo lu * 98f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 99f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 100f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 101f4932cfdSyangbo lu * and SD spec. 102f4932cfdSyangbo lu * 103f4932cfdSyangbo lu * Return a fixed up register value 104f4932cfdSyangbo lu */ 105f4932cfdSyangbo lu static u32 esdhc_readl_fixup(struct sdhci_host *host, 106f4932cfdSyangbo lu int spec_reg, u32 value) 107137ccd46SJerry Huang { 108f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1098605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 110137ccd46SJerry Huang u32 ret; 111137ccd46SJerry Huang 112137ccd46SJerry Huang /* 113137ccd46SJerry Huang * The bit of ADMA flag in eSDHC is not compatible with standard 114137ccd46SJerry Huang * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is 115137ccd46SJerry Huang * supported by eSDHC. 116137ccd46SJerry Huang * And for many FSL eSDHC controller, the reset value of field 117f4932cfdSyangbo lu * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA, 118137ccd46SJerry Huang * only these vendor version is greater than 2.2/0x12 support ADMA. 119137ccd46SJerry Huang */ 120f4932cfdSyangbo lu if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) { 121f4932cfdSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) { 122f4932cfdSyangbo lu ret = value | SDHCI_CAN_DO_ADMA2; 123f4932cfdSyangbo lu return ret; 124137ccd46SJerry Huang } 125f4932cfdSyangbo lu } 126b0921d5cSMichael Walle /* 127b0921d5cSMichael Walle * The DAT[3:0] line signal levels and the CMD line signal level are 128b0921d5cSMichael Walle * not compatible with standard SDHC register. The line signal levels 129b0921d5cSMichael Walle * DAT[7:0] are at bits 31:24 and the command line signal level is at 130b0921d5cSMichael Walle * bit 23. All other bits are the same as in the standard SDHC 131b0921d5cSMichael Walle * register. 132b0921d5cSMichael Walle */ 133b0921d5cSMichael Walle if (spec_reg == SDHCI_PRESENT_STATE) { 134b0921d5cSMichael Walle ret = value & 0x000fffff; 135b0921d5cSMichael Walle ret |= (value >> 4) & SDHCI_DATA_LVL_MASK; 136b0921d5cSMichael Walle ret |= (value << 1) & SDHCI_CMD_LVL; 137b0921d5cSMichael Walle return ret; 138b0921d5cSMichael Walle } 139b0921d5cSMichael Walle 1402f3110ccSyangbo lu /* 1412f3110ccSyangbo lu * DTS properties of mmc host are used to enable each speed mode 1422f3110ccSyangbo lu * according to soc and board capability. So clean up 1432f3110ccSyangbo lu * SDR50/SDR104/DDR50 support bits here. 1442f3110ccSyangbo lu */ 1452f3110ccSyangbo lu if (spec_reg == SDHCI_CAPABILITIES_1) { 1462f3110ccSyangbo lu ret = value & ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | 1472f3110ccSyangbo lu SDHCI_SUPPORT_DDR50); 1482f3110ccSyangbo lu return ret; 1492f3110ccSyangbo lu } 1502f3110ccSyangbo lu 1511f1929f3SYangbo Lu /* 1521f1929f3SYangbo Lu * Some controllers have unreliable Data Line Active 1531f1929f3SYangbo Lu * bit for commands with busy signal. This affects 1541f1929f3SYangbo Lu * Command Inhibit (data) bit. Just ignore it since 1551f1929f3SYangbo Lu * MMC core driver has already polled card status 1561f1929f3SYangbo Lu * with CMD13 after any command with busy siganl. 1571f1929f3SYangbo Lu */ 1581f1929f3SYangbo Lu if ((spec_reg == SDHCI_PRESENT_STATE) && 1591f1929f3SYangbo Lu (esdhc->quirk_ignore_data_inhibit == true)) { 1601f1929f3SYangbo Lu ret = value & ~SDHCI_DATA_INHIBIT; 1611f1929f3SYangbo Lu return ret; 1621f1929f3SYangbo Lu } 1631f1929f3SYangbo Lu 164f4932cfdSyangbo lu ret = value; 165137ccd46SJerry Huang return ret; 166137ccd46SJerry Huang } 167137ccd46SJerry Huang 168f4932cfdSyangbo lu static u16 esdhc_readw_fixup(struct sdhci_host *host, 169f4932cfdSyangbo lu int spec_reg, u32 value) 1707657c3a7SAlbert Herranz { 171151ede40Syangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 172151ede40Syangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1737657c3a7SAlbert Herranz u16 ret; 174f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 1757657c3a7SAlbert Herranz 176f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_VERSION) 177f4932cfdSyangbo lu ret = value & 0xffff; 1787657c3a7SAlbert Herranz else 179f4932cfdSyangbo lu ret = (value >> shift) & 0xffff; 180151ede40Syangbo lu /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect 181151ede40Syangbo lu * vendor version and spec version information. 182151ede40Syangbo lu */ 183151ede40Syangbo lu if ((spec_reg == SDHCI_HOST_VERSION) && 184151ede40Syangbo lu (esdhc->quirk_incorrect_hostver)) 185151ede40Syangbo lu ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200; 186e51cbc9eSXu lei return ret; 187e51cbc9eSXu lei } 188e51cbc9eSXu lei 189f4932cfdSyangbo lu static u8 esdhc_readb_fixup(struct sdhci_host *host, 190f4932cfdSyangbo lu int spec_reg, u32 value) 191e51cbc9eSXu lei { 192f4932cfdSyangbo lu u8 ret; 193f4932cfdSyangbo lu u8 dma_bits; 194f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 195f4932cfdSyangbo lu 196f4932cfdSyangbo lu ret = (value >> shift) & 0xff; 197ba8c4dc9SRoy Zang 198ba8c4dc9SRoy Zang /* 199ba8c4dc9SRoy Zang * "DMA select" locates at offset 0x28 in SD specification, but on 200ba8c4dc9SRoy Zang * P5020 or P3041, it locates at 0x29. 201ba8c4dc9SRoy Zang */ 202f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 203ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 204f4932cfdSyangbo lu dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK; 205ba8c4dc9SRoy Zang /* fixup the result */ 206ba8c4dc9SRoy Zang ret &= ~SDHCI_CTRL_DMA_MASK; 207ba8c4dc9SRoy Zang ret |= dma_bits; 208ba8c4dc9SRoy Zang } 209f4932cfdSyangbo lu return ret; 210f4932cfdSyangbo lu } 211f4932cfdSyangbo lu 212f4932cfdSyangbo lu /** 213f4932cfdSyangbo lu * esdhc_write*_fixup - Fixup the SD spec register value so that it could be 214f4932cfdSyangbo lu * written into eSDHC register. 215f4932cfdSyangbo lu * 216f4932cfdSyangbo lu * @host: pointer to sdhci_host 217f4932cfdSyangbo lu * @spec_reg: SD spec register address 218f4932cfdSyangbo lu * @value: 8/16/32bit SD spec register value that would be written 219f4932cfdSyangbo lu * @old_value: 32bit eSDHC register value on spec_reg address 220f4932cfdSyangbo lu * 221f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 222f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 223f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 224f4932cfdSyangbo lu * and SD spec. 225f4932cfdSyangbo lu * 226f4932cfdSyangbo lu * Return a fixed up register value 227f4932cfdSyangbo lu */ 228f4932cfdSyangbo lu static u32 esdhc_writel_fixup(struct sdhci_host *host, 229f4932cfdSyangbo lu int spec_reg, u32 value, u32 old_value) 230f4932cfdSyangbo lu { 231f4932cfdSyangbo lu u32 ret; 232f4932cfdSyangbo lu 233f4932cfdSyangbo lu /* 234f4932cfdSyangbo lu * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] 235f4932cfdSyangbo lu * when SYSCTL[RSTD] is set for some special operations. 236f4932cfdSyangbo lu * No any impact on other operation. 237f4932cfdSyangbo lu */ 238f4932cfdSyangbo lu if (spec_reg == SDHCI_INT_ENABLE) 239f4932cfdSyangbo lu ret = value | SDHCI_INT_BLK_GAP; 240f4932cfdSyangbo lu else 241f4932cfdSyangbo lu ret = value; 242ba8c4dc9SRoy Zang 2437657c3a7SAlbert Herranz return ret; 2447657c3a7SAlbert Herranz } 2457657c3a7SAlbert Herranz 246f4932cfdSyangbo lu static u32 esdhc_writew_fixup(struct sdhci_host *host, 247f4932cfdSyangbo lu int spec_reg, u16 value, u32 old_value) 248a4071fbbSHaijun Zhang { 249f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 250f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 251f4932cfdSyangbo lu u32 ret; 252f4932cfdSyangbo lu 253f4932cfdSyangbo lu switch (spec_reg) { 254f4932cfdSyangbo lu case SDHCI_TRANSFER_MODE: 255a4071fbbSHaijun Zhang /* 256f4932cfdSyangbo lu * Postpone this write, we must do it together with a 257f4932cfdSyangbo lu * command write that is down below. Return old value. 258a4071fbbSHaijun Zhang */ 259f4932cfdSyangbo lu pltfm_host->xfer_mode_shadow = value; 260f4932cfdSyangbo lu return old_value; 261f4932cfdSyangbo lu case SDHCI_COMMAND: 262f4932cfdSyangbo lu ret = (value << 16) | pltfm_host->xfer_mode_shadow; 263f4932cfdSyangbo lu return ret; 264a4071fbbSHaijun Zhang } 265a4071fbbSHaijun Zhang 266f4932cfdSyangbo lu ret = old_value & (~(0xffff << shift)); 267f4932cfdSyangbo lu ret |= (value << shift); 268f4932cfdSyangbo lu 269f4932cfdSyangbo lu if (spec_reg == SDHCI_BLOCK_SIZE) { 2707657c3a7SAlbert Herranz /* 2717657c3a7SAlbert Herranz * Two last DMA bits are reserved, and first one is used for 2727657c3a7SAlbert Herranz * non-standard blksz of 4096 bytes that we don't support 2737657c3a7SAlbert Herranz * yet. So clear the DMA boundary bits. 2747657c3a7SAlbert Herranz */ 275f4932cfdSyangbo lu ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0)); 2767657c3a7SAlbert Herranz } 277f4932cfdSyangbo lu return ret; 2787657c3a7SAlbert Herranz } 2797657c3a7SAlbert Herranz 280f4932cfdSyangbo lu static u32 esdhc_writeb_fixup(struct sdhci_host *host, 281f4932cfdSyangbo lu int spec_reg, u8 value, u32 old_value) 2827657c3a7SAlbert Herranz { 283f4932cfdSyangbo lu u32 ret; 284f4932cfdSyangbo lu u32 dma_bits; 285f4932cfdSyangbo lu u8 tmp; 286f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 287f4932cfdSyangbo lu 288ba8c4dc9SRoy Zang /* 2899e4703dfSyangbo lu * eSDHC doesn't have a standard power control register, so we do 2909e4703dfSyangbo lu * nothing here to avoid incorrect operation. 2919e4703dfSyangbo lu */ 2929e4703dfSyangbo lu if (spec_reg == SDHCI_POWER_CONTROL) 2939e4703dfSyangbo lu return old_value; 2949e4703dfSyangbo lu /* 295ba8c4dc9SRoy Zang * "DMA select" location is offset 0x28 in SD specification, but on 296ba8c4dc9SRoy Zang * P5020 or P3041, it's located at 0x29. 297ba8c4dc9SRoy Zang */ 298f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 299dcaff04dSOded Gabbay /* 300dcaff04dSOded Gabbay * If host control register is not standard, exit 301dcaff04dSOded Gabbay * this function 302dcaff04dSOded Gabbay */ 303dcaff04dSOded Gabbay if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) 304f4932cfdSyangbo lu return old_value; 305dcaff04dSOded Gabbay 306ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 307f4932cfdSyangbo lu dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5; 308f4932cfdSyangbo lu ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits; 309f4932cfdSyangbo lu tmp = (value & (~SDHCI_CTRL_DMA_MASK)) | 310f4932cfdSyangbo lu (old_value & SDHCI_CTRL_DMA_MASK); 311f4932cfdSyangbo lu ret = (ret & (~0xff)) | tmp; 312f4932cfdSyangbo lu 313f4932cfdSyangbo lu /* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */ 314f4932cfdSyangbo lu ret &= ~ESDHC_HOST_CONTROL_RES; 315f4932cfdSyangbo lu return ret; 316ba8c4dc9SRoy Zang } 317ba8c4dc9SRoy Zang 318f4932cfdSyangbo lu ret = (old_value & (~(0xff << shift))) | (value << shift); 319f4932cfdSyangbo lu return ret; 320f4932cfdSyangbo lu } 321f4932cfdSyangbo lu 322f4932cfdSyangbo lu static u32 esdhc_be_readl(struct sdhci_host *host, int reg) 323f4932cfdSyangbo lu { 324f4932cfdSyangbo lu u32 ret; 325f4932cfdSyangbo lu u32 value; 326f4932cfdSyangbo lu 3272f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3282f3110ccSyangbo lu value = ioread32be(host->ioaddr + ESDHC_CAPABILITIES_1); 3292f3110ccSyangbo lu else 330f4932cfdSyangbo lu value = ioread32be(host->ioaddr + reg); 3312f3110ccSyangbo lu 332f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 333f4932cfdSyangbo lu 334f4932cfdSyangbo lu return ret; 335f4932cfdSyangbo lu } 336f4932cfdSyangbo lu 337f4932cfdSyangbo lu static u32 esdhc_le_readl(struct sdhci_host *host, int reg) 338f4932cfdSyangbo lu { 339f4932cfdSyangbo lu u32 ret; 340f4932cfdSyangbo lu u32 value; 341f4932cfdSyangbo lu 3422f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3432f3110ccSyangbo lu value = ioread32(host->ioaddr + ESDHC_CAPABILITIES_1); 3442f3110ccSyangbo lu else 345f4932cfdSyangbo lu value = ioread32(host->ioaddr + reg); 3462f3110ccSyangbo lu 347f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 348f4932cfdSyangbo lu 349f4932cfdSyangbo lu return ret; 350f4932cfdSyangbo lu } 351f4932cfdSyangbo lu 352f4932cfdSyangbo lu static u16 esdhc_be_readw(struct sdhci_host *host, int reg) 353f4932cfdSyangbo lu { 354f4932cfdSyangbo lu u16 ret; 355f4932cfdSyangbo lu u32 value; 356f4932cfdSyangbo lu int base = reg & ~0x3; 357f4932cfdSyangbo lu 358f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 359f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 360f4932cfdSyangbo lu return ret; 361f4932cfdSyangbo lu } 362f4932cfdSyangbo lu 363f4932cfdSyangbo lu static u16 esdhc_le_readw(struct sdhci_host *host, int reg) 364f4932cfdSyangbo lu { 365f4932cfdSyangbo lu u16 ret; 366f4932cfdSyangbo lu u32 value; 367f4932cfdSyangbo lu int base = reg & ~0x3; 368f4932cfdSyangbo lu 369f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 370f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 371f4932cfdSyangbo lu return ret; 372f4932cfdSyangbo lu } 373f4932cfdSyangbo lu 374f4932cfdSyangbo lu static u8 esdhc_be_readb(struct sdhci_host *host, int reg) 375f4932cfdSyangbo lu { 376f4932cfdSyangbo lu u8 ret; 377f4932cfdSyangbo lu u32 value; 378f4932cfdSyangbo lu int base = reg & ~0x3; 379f4932cfdSyangbo lu 380f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 381f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 382f4932cfdSyangbo lu return ret; 383f4932cfdSyangbo lu } 384f4932cfdSyangbo lu 385f4932cfdSyangbo lu static u8 esdhc_le_readb(struct sdhci_host *host, int reg) 386f4932cfdSyangbo lu { 387f4932cfdSyangbo lu u8 ret; 388f4932cfdSyangbo lu u32 value; 389f4932cfdSyangbo lu int base = reg & ~0x3; 390f4932cfdSyangbo lu 391f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 392f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 393f4932cfdSyangbo lu return ret; 394f4932cfdSyangbo lu } 395f4932cfdSyangbo lu 396f4932cfdSyangbo lu static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg) 397f4932cfdSyangbo lu { 398f4932cfdSyangbo lu u32 value; 399f4932cfdSyangbo lu 400f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 401f4932cfdSyangbo lu iowrite32be(value, host->ioaddr + reg); 402f4932cfdSyangbo lu } 403f4932cfdSyangbo lu 404f4932cfdSyangbo lu static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg) 405f4932cfdSyangbo lu { 406f4932cfdSyangbo lu u32 value; 407f4932cfdSyangbo lu 408f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 409f4932cfdSyangbo lu iowrite32(value, host->ioaddr + reg); 410f4932cfdSyangbo lu } 411f4932cfdSyangbo lu 412f4932cfdSyangbo lu static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg) 413f4932cfdSyangbo lu { 41422dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 41522dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 416f4932cfdSyangbo lu int base = reg & ~0x3; 417f4932cfdSyangbo lu u32 value; 418f4932cfdSyangbo lu u32 ret; 419f4932cfdSyangbo lu 420f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 421f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 422f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 423f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 42422dc132dSYangbo Lu 42522dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 42622dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 42722dc132dSYangbo Lu */ 42822dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 42922dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 43022dc132dSYangbo Lu esdhc->in_sw_tuning) { 43122dc132dSYangbo Lu udelay(1); 43222dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 43322dc132dSYangbo Lu iowrite32be(ret, host->ioaddr + base); 43422dc132dSYangbo Lu } 43522dc132dSYangbo Lu } 436f4932cfdSyangbo lu } 437f4932cfdSyangbo lu 438f4932cfdSyangbo lu static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg) 439f4932cfdSyangbo lu { 44022dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 44122dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 442f4932cfdSyangbo lu int base = reg & ~0x3; 443f4932cfdSyangbo lu u32 value; 444f4932cfdSyangbo lu u32 ret; 445f4932cfdSyangbo lu 446f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 447f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 448f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 449f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 45022dc132dSYangbo Lu 45122dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 45222dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 45322dc132dSYangbo Lu */ 45422dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 45522dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 45622dc132dSYangbo Lu esdhc->in_sw_tuning) { 45722dc132dSYangbo Lu udelay(1); 45822dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 45922dc132dSYangbo Lu iowrite32(ret, host->ioaddr + base); 46022dc132dSYangbo Lu } 46122dc132dSYangbo Lu } 462f4932cfdSyangbo lu } 463f4932cfdSyangbo lu 464f4932cfdSyangbo lu static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg) 465f4932cfdSyangbo lu { 466f4932cfdSyangbo lu int base = reg & ~0x3; 467f4932cfdSyangbo lu u32 value; 468f4932cfdSyangbo lu u32 ret; 469f4932cfdSyangbo lu 470f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 471f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 472f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 473f4932cfdSyangbo lu } 474f4932cfdSyangbo lu 475f4932cfdSyangbo lu static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg) 476f4932cfdSyangbo lu { 477f4932cfdSyangbo lu int base = reg & ~0x3; 478f4932cfdSyangbo lu u32 value; 479f4932cfdSyangbo lu u32 ret; 480f4932cfdSyangbo lu 481f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 482f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 483f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 4847657c3a7SAlbert Herranz } 4857657c3a7SAlbert Herranz 486a4071fbbSHaijun Zhang /* 487a4071fbbSHaijun Zhang * For Abort or Suspend after Stop at Block Gap, ignore the ADMA 488a4071fbbSHaijun Zhang * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) 489a4071fbbSHaijun Zhang * and Block Gap Event(IRQSTAT[BGE]) are also set. 490a4071fbbSHaijun Zhang * For Continue, apply soft reset for data(SYSCTL[RSTD]); 491a4071fbbSHaijun Zhang * and re-issue the entire read transaction from beginning. 492a4071fbbSHaijun Zhang */ 493f4932cfdSyangbo lu static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) 494a4071fbbSHaijun Zhang { 495f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 4968605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 497a4071fbbSHaijun Zhang bool applicable; 498a4071fbbSHaijun Zhang dma_addr_t dmastart; 499a4071fbbSHaijun Zhang dma_addr_t dmanow; 500a4071fbbSHaijun Zhang 501a4071fbbSHaijun Zhang applicable = (intmask & SDHCI_INT_DATA_END) && 502a4071fbbSHaijun Zhang (intmask & SDHCI_INT_BLK_GAP) && 503f4932cfdSyangbo lu (esdhc->vendor_ver == VENDOR_V_23); 504a4071fbbSHaijun Zhang if (!applicable) 505a4071fbbSHaijun Zhang return; 506a4071fbbSHaijun Zhang 507a4071fbbSHaijun Zhang host->data->error = 0; 508a4071fbbSHaijun Zhang dmastart = sg_dma_address(host->data->sg); 509a4071fbbSHaijun Zhang dmanow = dmastart + host->data->bytes_xfered; 510a4071fbbSHaijun Zhang /* 511a4071fbbSHaijun Zhang * Force update to the next DMA block boundary. 512a4071fbbSHaijun Zhang */ 513a4071fbbSHaijun Zhang dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 514a4071fbbSHaijun Zhang SDHCI_DEFAULT_BOUNDARY_SIZE; 515a4071fbbSHaijun Zhang host->data->bytes_xfered = dmanow - dmastart; 516a4071fbbSHaijun Zhang sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); 517a4071fbbSHaijun Zhang } 518a4071fbbSHaijun Zhang 51980872e21SWolfram Sang static int esdhc_of_enable_dma(struct sdhci_host *host) 5207657c3a7SAlbert Herranz { 521f4932cfdSyangbo lu u32 value; 5225552d7adSLaurentiu Tudor struct device *dev = mmc_dev(host->mmc); 5235552d7adSLaurentiu Tudor 5245552d7adSLaurentiu Tudor if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || 5255552d7adSLaurentiu Tudor of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) 5265552d7adSLaurentiu Tudor dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); 527f4932cfdSyangbo lu 528f4932cfdSyangbo lu value = sdhci_readl(host, ESDHC_DMA_SYSCTL); 529121bd08bSRussell King 530121bd08bSRussell King if (of_dma_is_coherent(dev->of_node)) 531f4932cfdSyangbo lu value |= ESDHC_DMA_SNOOP; 532121bd08bSRussell King else 533121bd08bSRussell King value &= ~ESDHC_DMA_SNOOP; 534121bd08bSRussell King 535f4932cfdSyangbo lu sdhci_writel(host, value, ESDHC_DMA_SYSCTL); 5367657c3a7SAlbert Herranz return 0; 5377657c3a7SAlbert Herranz } 5387657c3a7SAlbert Herranz 53980872e21SWolfram Sang static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host) 5407657c3a7SAlbert Herranz { 541e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 54219c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 5437657c3a7SAlbert Herranz 54419c3a0efSyangbo lu if (esdhc->peripheral_clock) 54519c3a0efSyangbo lu return esdhc->peripheral_clock; 54619c3a0efSyangbo lu else 547e307148fSShawn Guo return pltfm_host->clock; 5487657c3a7SAlbert Herranz } 5497657c3a7SAlbert Herranz 55080872e21SWolfram Sang static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) 5517657c3a7SAlbert Herranz { 552e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 55319c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 55419c3a0efSyangbo lu unsigned int clock; 5557657c3a7SAlbert Herranz 55619c3a0efSyangbo lu if (esdhc->peripheral_clock) 55719c3a0efSyangbo lu clock = esdhc->peripheral_clock; 55819c3a0efSyangbo lu else 55919c3a0efSyangbo lu clock = pltfm_host->clock; 56019c3a0efSyangbo lu return clock / 256 / 16; 5617657c3a7SAlbert Herranz } 5627657c3a7SAlbert Herranz 563dd3f6983Syangbo lu static void esdhc_clock_enable(struct sdhci_host *host, bool enable) 564dd3f6983Syangbo lu { 565dd3f6983Syangbo lu u32 val; 566dd3f6983Syangbo lu ktime_t timeout; 567dd3f6983Syangbo lu 568dd3f6983Syangbo lu val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 569dd3f6983Syangbo lu 570dd3f6983Syangbo lu if (enable) 571dd3f6983Syangbo lu val |= ESDHC_CLOCK_SDCLKEN; 572dd3f6983Syangbo lu else 573dd3f6983Syangbo lu val &= ~ESDHC_CLOCK_SDCLKEN; 574dd3f6983Syangbo lu 575dd3f6983Syangbo lu sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL); 576dd3f6983Syangbo lu 577dd3f6983Syangbo lu /* Wait max 20 ms */ 578dd3f6983Syangbo lu timeout = ktime_add_ms(ktime_get(), 20); 579dd3f6983Syangbo lu val = ESDHC_CLOCK_STABLE; 580ea6d0273SAdrian Hunter while (1) { 581ea6d0273SAdrian Hunter bool timedout = ktime_after(ktime_get(), timeout); 582ea6d0273SAdrian Hunter 583ea6d0273SAdrian Hunter if (sdhci_readl(host, ESDHC_PRSSTAT) & val) 584ea6d0273SAdrian Hunter break; 585ea6d0273SAdrian Hunter if (timedout) { 586dd3f6983Syangbo lu pr_err("%s: Internal clock never stabilised.\n", 587dd3f6983Syangbo lu mmc_hostname(host->mmc)); 588dd3f6983Syangbo lu break; 589dd3f6983Syangbo lu } 590dd3f6983Syangbo lu udelay(10); 591dd3f6983Syangbo lu } 592dd3f6983Syangbo lu } 593dd3f6983Syangbo lu 5946e32f65cSYangbo Lu static void esdhc_flush_async_fifo(struct sdhci_host *host) 5956e32f65cSYangbo Lu { 5966e32f65cSYangbo Lu ktime_t timeout; 5976e32f65cSYangbo Lu u32 val; 5986e32f65cSYangbo Lu 5996e32f65cSYangbo Lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 6006e32f65cSYangbo Lu val |= ESDHC_FLUSH_ASYNC_FIFO; 6016e32f65cSYangbo Lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 6026e32f65cSYangbo Lu 6036e32f65cSYangbo Lu /* Wait max 20 ms */ 6046e32f65cSYangbo Lu timeout = ktime_add_ms(ktime_get(), 20); 6056e32f65cSYangbo Lu while (1) { 6066e32f65cSYangbo Lu bool timedout = ktime_after(ktime_get(), timeout); 6076e32f65cSYangbo Lu 6086e32f65cSYangbo Lu if (!(sdhci_readl(host, ESDHC_DMA_SYSCTL) & 6096e32f65cSYangbo Lu ESDHC_FLUSH_ASYNC_FIFO)) 6106e32f65cSYangbo Lu break; 6116e32f65cSYangbo Lu if (timedout) { 6126e32f65cSYangbo Lu pr_err("%s: flushing asynchronous FIFO timeout.\n", 6136e32f65cSYangbo Lu mmc_hostname(host->mmc)); 6146e32f65cSYangbo Lu break; 6156e32f65cSYangbo Lu } 6166e32f65cSYangbo Lu usleep_range(10, 20); 6176e32f65cSYangbo Lu } 6186e32f65cSYangbo Lu } 6196e32f65cSYangbo Lu 620f060bc9cSJerry Huang static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) 621f060bc9cSJerry Huang { 622f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 6238605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 624bd455029SJoakim Tjernlund int pre_div = 1; 625d31fc00aSDong Aisheng int div = 1; 6266079e63cSYangbo Lu int division; 627e145ac45Syangbo lu ktime_t timeout; 62867fdfbdfSyinbo.zhu long fixup = 0; 629d31fc00aSDong Aisheng u32 temp; 630d31fc00aSDong Aisheng 6311650d0c7SRussell King host->mmc->actual_clock = 0; 6321650d0c7SRussell King 633dd3f6983Syangbo lu if (clock == 0) { 634dd3f6983Syangbo lu esdhc_clock_enable(host, false); 635373073efSRussell King return; 636dd3f6983Syangbo lu } 637d31fc00aSDong Aisheng 63877bd2f6fSYangbo Lu /* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */ 639f4932cfdSyangbo lu if (esdhc->vendor_ver < VENDOR_V_23) 64077bd2f6fSYangbo Lu pre_div = 2; 64177bd2f6fSYangbo Lu 64267fdfbdfSyinbo.zhu if (host->mmc->card && mmc_card_sd(host->mmc->card) && 64367fdfbdfSyinbo.zhu esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) 64467fdfbdfSyinbo.zhu fixup = esdhc->clk_fixup->sd_dflt_max_clk; 64567fdfbdfSyinbo.zhu else if (esdhc->clk_fixup) 64667fdfbdfSyinbo.zhu fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; 647a627f025Syangbo lu 64867fdfbdfSyinbo.zhu if (fixup && clock > fixup) 64967fdfbdfSyinbo.zhu clock = fixup; 650f060bc9cSJerry Huang 651d31fc00aSDong Aisheng temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 652e87d2db2Syangbo lu temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | 653e87d2db2Syangbo lu ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); 654d31fc00aSDong Aisheng sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 655d31fc00aSDong Aisheng 656d31fc00aSDong Aisheng while (host->max_clk / pre_div / 16 > clock && pre_div < 256) 657d31fc00aSDong Aisheng pre_div *= 2; 658d31fc00aSDong Aisheng 659d31fc00aSDong Aisheng while (host->max_clk / pre_div / div > clock && div < 16) 660d31fc00aSDong Aisheng div++; 661d31fc00aSDong Aisheng 6626079e63cSYangbo Lu if (esdhc->quirk_limited_clk_division && 6636079e63cSYangbo Lu clock == MMC_HS200_MAX_DTR && 6646079e63cSYangbo Lu (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 || 6656079e63cSYangbo Lu host->flags & SDHCI_HS400_TUNING)) { 6666079e63cSYangbo Lu division = pre_div * div; 6676079e63cSYangbo Lu if (division <= 4) { 6686079e63cSYangbo Lu pre_div = 4; 6696079e63cSYangbo Lu div = 1; 6706079e63cSYangbo Lu } else if (division <= 8) { 6716079e63cSYangbo Lu pre_div = 4; 6726079e63cSYangbo Lu div = 2; 6736079e63cSYangbo Lu } else if (division <= 12) { 6746079e63cSYangbo Lu pre_div = 4; 6756079e63cSYangbo Lu div = 3; 6766079e63cSYangbo Lu } else { 677b11c36d5SColin Ian King pr_warn("%s: using unsupported clock division.\n", 6786079e63cSYangbo Lu mmc_hostname(host->mmc)); 6796079e63cSYangbo Lu } 6806079e63cSYangbo Lu } 6816079e63cSYangbo Lu 682d31fc00aSDong Aisheng dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", 683e76b8559SDong Aisheng clock, host->max_clk / pre_div / div); 684bd455029SJoakim Tjernlund host->mmc->actual_clock = host->max_clk / pre_div / div; 685b1f378abSYinbo Zhu esdhc->div_ratio = pre_div * div; 686d31fc00aSDong Aisheng pre_div >>= 1; 687d31fc00aSDong Aisheng div--; 688d31fc00aSDong Aisheng 689d31fc00aSDong Aisheng temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 690d31fc00aSDong Aisheng temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN 691d31fc00aSDong Aisheng | (div << ESDHC_DIVIDER_SHIFT) 692d31fc00aSDong Aisheng | (pre_div << ESDHC_PREDIV_SHIFT)); 693d31fc00aSDong Aisheng sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 694e87d2db2Syangbo lu 69554e08d9aSYangbo Lu if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && 69654e08d9aSYangbo Lu clock == MMC_HS200_MAX_DTR) { 69754e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 69854e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_MODE, ESDHC_TBCTL); 69954e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_SDCLKCTL); 70054e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_CMD_CLK_CTL, ESDHC_SDCLKCTL); 70154e08d9aSYangbo Lu esdhc_clock_enable(host, true); 70254e08d9aSYangbo Lu 70354e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_DLLCFG0); 70458d0bf84SYangbo Lu temp |= ESDHC_DLL_ENABLE; 70558d0bf84SYangbo Lu if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) 70658d0bf84SYangbo Lu temp |= ESDHC_DLL_FREQ_SEL; 70754e08d9aSYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 70854e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 70954e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL); 71054e08d9aSYangbo Lu 71154e08d9aSYangbo Lu esdhc_clock_enable(host, false); 7126e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 71354e08d9aSYangbo Lu } 71454e08d9aSYangbo Lu 715e87d2db2Syangbo lu /* Wait max 20 ms */ 716e145ac45Syangbo lu timeout = ktime_add_ms(ktime_get(), 20); 717ea6d0273SAdrian Hunter while (1) { 718ea6d0273SAdrian Hunter bool timedout = ktime_after(ktime_get(), timeout); 719ea6d0273SAdrian Hunter 720ea6d0273SAdrian Hunter if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) 721ea6d0273SAdrian Hunter break; 722ea6d0273SAdrian Hunter if (timedout) { 723e87d2db2Syangbo lu pr_err("%s: Internal clock never stabilised.\n", 724e87d2db2Syangbo lu mmc_hostname(host->mmc)); 725e87d2db2Syangbo lu return; 726e87d2db2Syangbo lu } 727e145ac45Syangbo lu udelay(10); 728f060bc9cSJerry Huang } 729f060bc9cSJerry Huang 73054e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 731e87d2db2Syangbo lu temp |= ESDHC_CLOCK_SDCLKEN; 732e87d2db2Syangbo lu sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 733e87d2db2Syangbo lu } 734e87d2db2Syangbo lu 7352317f56cSRussell King static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) 73666b50a00SOded Gabbay { 73766b50a00SOded Gabbay u32 ctrl; 73866b50a00SOded Gabbay 739f4932cfdSyangbo lu ctrl = sdhci_readl(host, ESDHC_PROCTL); 740f4932cfdSyangbo lu ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK); 74166b50a00SOded Gabbay switch (width) { 74266b50a00SOded Gabbay case MMC_BUS_WIDTH_8: 743f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_8BITBUS; 74466b50a00SOded Gabbay break; 74566b50a00SOded Gabbay 74666b50a00SOded Gabbay case MMC_BUS_WIDTH_4: 747f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_4BITBUS; 74866b50a00SOded Gabbay break; 74966b50a00SOded Gabbay 75066b50a00SOded Gabbay default: 75166b50a00SOded Gabbay break; 75266b50a00SOded Gabbay } 75366b50a00SOded Gabbay 754f4932cfdSyangbo lu sdhci_writel(host, ctrl, ESDHC_PROCTL); 75566b50a00SOded Gabbay } 75666b50a00SOded Gabbay 757304f0a98SAlessio Igor Bogani static void esdhc_reset(struct sdhci_host *host, u8 mask) 758304f0a98SAlessio Igor Bogani { 75948e304ccSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 76048e304ccSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 761f2bc6000Syinbo.zhu u32 val; 762f2bc6000Syinbo.zhu 763f667216cSYangbo Lu if (esdhc->quirk_delay_before_data_reset && 764f667216cSYangbo Lu (mask & SDHCI_RESET_DATA) && 765f667216cSYangbo Lu (host->flags & SDHCI_REQ_USE_DMA)) 766f667216cSYangbo Lu mdelay(5); 767f667216cSYangbo Lu 768304f0a98SAlessio Igor Bogani sdhci_reset(host, mask); 769304f0a98SAlessio Igor Bogani 770304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 771304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 772f2bc6000Syinbo.zhu 773f2bc6000Syinbo.zhu if (mask & SDHCI_RESET_ALL) { 774f2bc6000Syinbo.zhu val = sdhci_readl(host, ESDHC_TBCTL); 775f2bc6000Syinbo.zhu val &= ~ESDHC_TB_EN; 776f2bc6000Syinbo.zhu sdhci_writel(host, val, ESDHC_TBCTL); 77748e304ccSYangbo Lu 77848e304ccSYangbo Lu if (esdhc->quirk_unreliable_pulse_detection) { 77948e304ccSYangbo Lu val = sdhci_readl(host, ESDHC_DLLCFG1); 78048e304ccSYangbo Lu val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL; 78148e304ccSYangbo Lu sdhci_writel(host, val, ESDHC_DLLCFG1); 78248e304ccSYangbo Lu } 783f2bc6000Syinbo.zhu } 784304f0a98SAlessio Igor Bogani } 785304f0a98SAlessio Igor Bogani 786ea35645aSyangbo lu /* The SCFG, Supplemental Configuration Unit, provides SoC specific 787ea35645aSyangbo lu * configuration and status registers for the device. There is a 788ea35645aSyangbo lu * SDHC IO VSEL control register on SCFG for some platforms. It's 789ea35645aSyangbo lu * used to support SDHC IO voltage switching. 790ea35645aSyangbo lu */ 791ea35645aSyangbo lu static const struct of_device_id scfg_device_ids[] = { 792ea35645aSyangbo lu { .compatible = "fsl,t1040-scfg", }, 793ea35645aSyangbo lu { .compatible = "fsl,ls1012a-scfg", }, 794ea35645aSyangbo lu { .compatible = "fsl,ls1046a-scfg", }, 795ea35645aSyangbo lu {} 796ea35645aSyangbo lu }; 797ea35645aSyangbo lu 798ea35645aSyangbo lu /* SDHC IO VSEL control register definition */ 799ea35645aSyangbo lu #define SCFG_SDHCIOVSELCR 0x408 800ea35645aSyangbo lu #define SDHCIOVSELCR_TGLEN 0x80000000 801ea35645aSyangbo lu #define SDHCIOVSELCR_VSELVAL 0x60000000 802ea35645aSyangbo lu #define SDHCIOVSELCR_SDHC_VS 0x00000001 803ea35645aSyangbo lu 804ea35645aSyangbo lu static int esdhc_signal_voltage_switch(struct mmc_host *mmc, 805ea35645aSyangbo lu struct mmc_ios *ios) 806ea35645aSyangbo lu { 807ea35645aSyangbo lu struct sdhci_host *host = mmc_priv(mmc); 808ea35645aSyangbo lu struct device_node *scfg_node; 809ea35645aSyangbo lu void __iomem *scfg_base = NULL; 810ea35645aSyangbo lu u32 sdhciovselcr; 811ea35645aSyangbo lu u32 val; 812ea35645aSyangbo lu 813ea35645aSyangbo lu /* 814ea35645aSyangbo lu * Signal Voltage Switching is only applicable for Host Controllers 815ea35645aSyangbo lu * v3.00 and above. 816ea35645aSyangbo lu */ 817ea35645aSyangbo lu if (host->version < SDHCI_SPEC_300) 818ea35645aSyangbo lu return 0; 819ea35645aSyangbo lu 820ea35645aSyangbo lu val = sdhci_readl(host, ESDHC_PROCTL); 821ea35645aSyangbo lu 822ea35645aSyangbo lu switch (ios->signal_voltage) { 823ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_330: 824ea35645aSyangbo lu val &= ~ESDHC_VOLT_SEL; 825ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 826ea35645aSyangbo lu return 0; 827ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_180: 828ea35645aSyangbo lu scfg_node = of_find_matching_node(NULL, scfg_device_ids); 829ea35645aSyangbo lu if (scfg_node) 830ea35645aSyangbo lu scfg_base = of_iomap(scfg_node, 0); 831ea35645aSyangbo lu if (scfg_base) { 832ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 833ea35645aSyangbo lu SDHCIOVSELCR_VSELVAL; 834ea35645aSyangbo lu iowrite32be(sdhciovselcr, 835ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 836ea35645aSyangbo lu 837ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 838ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 839ea35645aSyangbo lu mdelay(5); 840ea35645aSyangbo lu 841ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 842ea35645aSyangbo lu SDHCIOVSELCR_SDHC_VS; 843ea35645aSyangbo lu iowrite32be(sdhciovselcr, 844ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 845ea35645aSyangbo lu iounmap(scfg_base); 846ea35645aSyangbo lu } else { 847ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 848ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 849ea35645aSyangbo lu } 850ea35645aSyangbo lu return 0; 851ea35645aSyangbo lu default: 852ea35645aSyangbo lu return 0; 853ea35645aSyangbo lu } 854ea35645aSyangbo lu } 855ea35645aSyangbo lu 85622dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type1[] = { 857*5b742232SYangbo Lu { .family = "QorIQ T1023", }, 858*5b742232SYangbo Lu { .family = "QorIQ T1040", }, 859*5b742232SYangbo Lu { .family = "QorIQ T2080", }, 860*5b742232SYangbo Lu { .family = "QorIQ LS1021A", }, 86122dc132dSYangbo Lu { }, 86222dc132dSYangbo Lu }; 86322dc132dSYangbo Lu 86422dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type2[] = { 865*5b742232SYangbo Lu { .family = "QorIQ LS1012A", }, 866*5b742232SYangbo Lu { .family = "QorIQ LS1043A", }, 867*5b742232SYangbo Lu { .family = "QorIQ LS1046A", }, 868*5b742232SYangbo Lu { .family = "QorIQ LS1080A", }, 869*5b742232SYangbo Lu { .family = "QorIQ LS2080A", }, 870*5b742232SYangbo Lu { .family = "QorIQ LA1575A", }, 871b1f378abSYinbo Zhu { }, 872b1f378abSYinbo Zhu }; 873b1f378abSYinbo Zhu 87454e08d9aSYangbo Lu static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable) 875ba49cbd0Syangbo lu { 876ba49cbd0Syangbo lu u32 val; 877ba49cbd0Syangbo lu 878ba49cbd0Syangbo lu esdhc_clock_enable(host, false); 8796e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 880ba49cbd0Syangbo lu 881ba49cbd0Syangbo lu val = sdhci_readl(host, ESDHC_TBCTL); 88254e08d9aSYangbo Lu if (enable) 883ba49cbd0Syangbo lu val |= ESDHC_TB_EN; 88454e08d9aSYangbo Lu else 88554e08d9aSYangbo Lu val &= ~ESDHC_TB_EN; 886ba49cbd0Syangbo lu sdhci_writel(host, val, ESDHC_TBCTL); 887ba49cbd0Syangbo lu 88854e08d9aSYangbo Lu esdhc_clock_enable(host, true); 88954e08d9aSYangbo Lu } 89054e08d9aSYangbo Lu 891f3c20825SYangbo Lu static void esdhc_tuning_window_ptr(struct sdhci_host *host, u8 *window_start, 89222dc132dSYangbo Lu u8 *window_end) 89322dc132dSYangbo Lu { 89422dc132dSYangbo Lu u32 val; 89522dc132dSYangbo Lu 89622dc132dSYangbo Lu /* Write TBCTL[11:8]=4'h8 */ 89722dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 89822dc132dSYangbo Lu val &= ~(0xf << 8); 89922dc132dSYangbo Lu val |= 8 << 8; 90022dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 90122dc132dSYangbo Lu 90222dc132dSYangbo Lu mdelay(1); 90322dc132dSYangbo Lu 90422dc132dSYangbo Lu /* Read TBCTL[31:0] register and rewrite again */ 90522dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 90622dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 90722dc132dSYangbo Lu 90822dc132dSYangbo Lu mdelay(1); 90922dc132dSYangbo Lu 91022dc132dSYangbo Lu /* Read the TBSTAT[31:0] register twice */ 91122dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 91222dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 91322dc132dSYangbo Lu 914f3c20825SYangbo Lu *window_end = val & 0xff; 915f3c20825SYangbo Lu *window_start = (val >> 8) & 0xff; 916f3c20825SYangbo Lu } 917f3c20825SYangbo Lu 918f3c20825SYangbo Lu static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start, 919f3c20825SYangbo Lu u8 *window_end) 920f3c20825SYangbo Lu { 921f3c20825SYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 922f3c20825SYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 923f3c20825SYangbo Lu u8 start_ptr, end_ptr; 924f3c20825SYangbo Lu 925f3c20825SYangbo Lu if (esdhc->quirk_tuning_erratum_type1) { 926f3c20825SYangbo Lu *window_start = 5 * esdhc->div_ratio; 927f3c20825SYangbo Lu *window_end = 3 * esdhc->div_ratio; 928f3c20825SYangbo Lu return; 929f3c20825SYangbo Lu } 930f3c20825SYangbo Lu 931f3c20825SYangbo Lu esdhc_tuning_window_ptr(host, &start_ptr, &end_ptr); 932f3c20825SYangbo Lu 93322dc132dSYangbo Lu /* Reset data lines by setting ESDHCCTL[RSTD] */ 93422dc132dSYangbo Lu sdhci_reset(host, SDHCI_RESET_DATA); 93522dc132dSYangbo Lu /* Write 32'hFFFF_FFFF to IRQSTAT register */ 93622dc132dSYangbo Lu sdhci_writel(host, 0xFFFFFFFF, SDHCI_INT_STATUS); 93722dc132dSYangbo Lu 938*5b742232SYangbo Lu /* If TBSTAT[15:8]-TBSTAT[7:0] > (4 * div_ratio) + 2 939*5b742232SYangbo Lu * or TBSTAT[7:0]-TBSTAT[15:8] > (4 * div_ratio) + 2, 94022dc132dSYangbo Lu * then program TBPTR[TB_WNDW_END_PTR] = 4 * div_ratio 94122dc132dSYangbo Lu * and program TBPTR[TB_WNDW_START_PTR] = 8 * div_ratio. 94222dc132dSYangbo Lu */ 94322dc132dSYangbo Lu 944*5b742232SYangbo Lu if (abs(start_ptr - end_ptr) > (4 * esdhc->div_ratio + 2)) { 94522dc132dSYangbo Lu *window_start = 8 * esdhc->div_ratio; 94622dc132dSYangbo Lu *window_end = 4 * esdhc->div_ratio; 94722dc132dSYangbo Lu } else { 94822dc132dSYangbo Lu *window_start = 5 * esdhc->div_ratio; 94922dc132dSYangbo Lu *window_end = 3 * esdhc->div_ratio; 95022dc132dSYangbo Lu } 95122dc132dSYangbo Lu } 95222dc132dSYangbo Lu 95322dc132dSYangbo Lu static int esdhc_execute_sw_tuning(struct mmc_host *mmc, u32 opcode, 95422dc132dSYangbo Lu u8 window_start, u8 window_end) 95522dc132dSYangbo Lu { 95622dc132dSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 95722dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 95822dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 95922dc132dSYangbo Lu u32 val; 96022dc132dSYangbo Lu int ret; 96122dc132dSYangbo Lu 96222dc132dSYangbo Lu /* Program TBPTR[TB_WNDW_END_PTR] and TBPTR[TB_WNDW_START_PTR] */ 96322dc132dSYangbo Lu val = ((u32)window_start << ESDHC_WNDW_STRT_PTR_SHIFT) & 96422dc132dSYangbo Lu ESDHC_WNDW_STRT_PTR_MASK; 96522dc132dSYangbo Lu val |= window_end & ESDHC_WNDW_END_PTR_MASK; 96622dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBPTR); 96722dc132dSYangbo Lu 96822dc132dSYangbo Lu /* Program the software tuning mode by setting TBCTL[TB_MODE]=2'h3 */ 96922dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 97022dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 97122dc132dSYangbo Lu val |= ESDHC_TB_MODE_SW; 97222dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 97322dc132dSYangbo Lu 97422dc132dSYangbo Lu esdhc->in_sw_tuning = true; 97522dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 97622dc132dSYangbo Lu esdhc->in_sw_tuning = false; 97722dc132dSYangbo Lu return ret; 97822dc132dSYangbo Lu } 97922dc132dSYangbo Lu 98054e08d9aSYangbo Lu static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) 98154e08d9aSYangbo Lu { 98254e08d9aSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 98354e08d9aSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 98454e08d9aSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 98522dc132dSYangbo Lu u8 window_start, window_end; 98622dc132dSYangbo Lu int ret, retries = 1; 98754e08d9aSYangbo Lu bool hs400_tuning; 98804509d77SYangbo Lu unsigned int clk; 98954e08d9aSYangbo Lu u32 val; 99054e08d9aSYangbo Lu 99104509d77SYangbo Lu /* For tuning mode, the sd clock divisor value 99204509d77SYangbo Lu * must be larger than 3 according to reference manual. 99304509d77SYangbo Lu */ 99404509d77SYangbo Lu clk = esdhc->peripheral_clock / 3; 99504509d77SYangbo Lu if (host->clock > clk) 99604509d77SYangbo Lu esdhc_of_set_clock(host, clk); 99704509d77SYangbo Lu 99854e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 99954e08d9aSYangbo Lu 100054e08d9aSYangbo Lu hs400_tuning = host->flags & SDHCI_HS400_TUNING; 100154e08d9aSYangbo Lu 100222dc132dSYangbo Lu do { 100322dc132dSYangbo Lu if (esdhc->quirk_limited_clk_division && 100422dc132dSYangbo Lu hs400_tuning) 100522dc132dSYangbo Lu esdhc_of_set_clock(host, host->clock); 100622dc132dSYangbo Lu 100722dc132dSYangbo Lu /* Do HW tuning */ 100822dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 100922dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 101022dc132dSYangbo Lu val |= ESDHC_TB_MODE_3; 101122dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 101222dc132dSYangbo Lu 101322dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 101422dc132dSYangbo Lu if (ret) 101522dc132dSYangbo Lu break; 101622dc132dSYangbo Lu 1017*5b742232SYangbo Lu /* For type2 affected platforms of the tuning erratum, 1018*5b742232SYangbo Lu * tuning may succeed although eSDHC might not have 1019*5b742232SYangbo Lu * tuned properly. Need to check tuning window. 1020*5b742232SYangbo Lu */ 1021*5b742232SYangbo Lu if (esdhc->quirk_tuning_erratum_type2 && 1022*5b742232SYangbo Lu !host->tuning_err) { 1023*5b742232SYangbo Lu esdhc_tuning_window_ptr(host, &window_start, 1024*5b742232SYangbo Lu &window_end); 1025*5b742232SYangbo Lu if (abs(window_start - window_end) > 1026*5b742232SYangbo Lu (4 * esdhc->div_ratio + 2)) 1027*5b742232SYangbo Lu host->tuning_err = -EAGAIN; 1028*5b742232SYangbo Lu } 1029*5b742232SYangbo Lu 103022dc132dSYangbo Lu /* If HW tuning fails and triggers erratum, 103122dc132dSYangbo Lu * try workaround. 103222dc132dSYangbo Lu */ 103322dc132dSYangbo Lu ret = host->tuning_err; 103422dc132dSYangbo Lu if (ret == -EAGAIN && 103522dc132dSYangbo Lu (esdhc->quirk_tuning_erratum_type1 || 103622dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2)) { 103722dc132dSYangbo Lu /* Recover HS400 tuning flag */ 103822dc132dSYangbo Lu if (hs400_tuning) 103922dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 104022dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try SW tuning!\n", 104122dc132dSYangbo Lu mmc_hostname(mmc)); 104222dc132dSYangbo Lu /* Do SW tuning */ 104322dc132dSYangbo Lu esdhc_prepare_sw_tuning(host, &window_start, 104422dc132dSYangbo Lu &window_end); 104522dc132dSYangbo Lu ret = esdhc_execute_sw_tuning(mmc, opcode, 104622dc132dSYangbo Lu window_start, 104722dc132dSYangbo Lu window_end); 104822dc132dSYangbo Lu if (ret) 104922dc132dSYangbo Lu break; 105022dc132dSYangbo Lu 105122dc132dSYangbo Lu /* Retry both HW/SW tuning with reduced clock. */ 105222dc132dSYangbo Lu ret = host->tuning_err; 105322dc132dSYangbo Lu if (ret == -EAGAIN && retries) { 105422dc132dSYangbo Lu /* Recover HS400 tuning flag */ 105522dc132dSYangbo Lu if (hs400_tuning) 105622dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 105722dc132dSYangbo Lu 105822dc132dSYangbo Lu clk = host->max_clk / (esdhc->div_ratio + 1); 105922dc132dSYangbo Lu esdhc_of_set_clock(host, clk); 106022dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try tuning with reduced clock!\n", 106122dc132dSYangbo Lu mmc_hostname(mmc)); 106222dc132dSYangbo Lu } else { 106322dc132dSYangbo Lu break; 106422dc132dSYangbo Lu } 106522dc132dSYangbo Lu } else { 106622dc132dSYangbo Lu break; 106722dc132dSYangbo Lu } 106822dc132dSYangbo Lu } while (retries--); 106922dc132dSYangbo Lu 107022dc132dSYangbo Lu if (ret) { 107122dc132dSYangbo Lu esdhc_tuning_block_enable(host, false); 107222dc132dSYangbo Lu } else if (hs400_tuning) { 107354e08d9aSYangbo Lu val = sdhci_readl(host, ESDHC_SDTIMNGCTL); 107454e08d9aSYangbo Lu val |= ESDHC_FLW_CTL_BG; 107554e08d9aSYangbo Lu sdhci_writel(host, val, ESDHC_SDTIMNGCTL); 107654e08d9aSYangbo Lu } 107754e08d9aSYangbo Lu 107854e08d9aSYangbo Lu return ret; 107954e08d9aSYangbo Lu } 108054e08d9aSYangbo Lu 108154e08d9aSYangbo Lu static void esdhc_set_uhs_signaling(struct sdhci_host *host, 108254e08d9aSYangbo Lu unsigned int timing) 108354e08d9aSYangbo Lu { 108454e08d9aSYangbo Lu if (timing == MMC_TIMING_MMC_HS400) 108554e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 108654e08d9aSYangbo Lu else 108754e08d9aSYangbo Lu sdhci_set_uhs_signaling(host, timing); 1088ba49cbd0Syangbo lu } 1089ba49cbd0Syangbo lu 1090b214fe59SYinbo Zhu static u32 esdhc_irq(struct sdhci_host *host, u32 intmask) 1091b214fe59SYinbo Zhu { 1092b214fe59SYinbo Zhu u32 command; 1093b214fe59SYinbo Zhu 1094b214fe59SYinbo Zhu if (of_find_compatible_node(NULL, NULL, 1095b214fe59SYinbo Zhu "fsl,p2020-esdhc")) { 1096b214fe59SYinbo Zhu command = SDHCI_GET_CMD(sdhci_readw(host, 1097b214fe59SYinbo Zhu SDHCI_COMMAND)); 1098b214fe59SYinbo Zhu if (command == MMC_WRITE_MULTIPLE_BLOCK && 1099b214fe59SYinbo Zhu sdhci_readw(host, SDHCI_BLOCK_COUNT) && 1100b214fe59SYinbo Zhu intmask & SDHCI_INT_DATA_END) { 1101b214fe59SYinbo Zhu intmask &= ~SDHCI_INT_DATA_END; 1102b214fe59SYinbo Zhu sdhci_writel(host, SDHCI_INT_DATA_END, 1103b214fe59SYinbo Zhu SDHCI_INT_STATUS); 1104b214fe59SYinbo Zhu } 1105b214fe59SYinbo Zhu } 1106b214fe59SYinbo Zhu return intmask; 1107b214fe59SYinbo Zhu } 1108b214fe59SYinbo Zhu 11099e48b336SUlf Hansson #ifdef CONFIG_PM_SLEEP 1110723f7924SRussell King static u32 esdhc_proctl; 1111723f7924SRussell King static int esdhc_of_suspend(struct device *dev) 1112723f7924SRussell King { 1113723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1114723f7924SRussell King 1115f4932cfdSyangbo lu esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL); 1116723f7924SRussell King 1117d38dcad4SAdrian Hunter if (host->tuning_mode != SDHCI_TUNING_MODE_3) 1118d38dcad4SAdrian Hunter mmc_retune_needed(host->mmc); 1119d38dcad4SAdrian Hunter 1120723f7924SRussell King return sdhci_suspend_host(host); 1121723f7924SRussell King } 1122723f7924SRussell King 112306732b84SUlf Hansson static int esdhc_of_resume(struct device *dev) 1124723f7924SRussell King { 1125723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1126723f7924SRussell King int ret = sdhci_resume_host(host); 1127723f7924SRussell King 1128723f7924SRussell King if (ret == 0) { 1129723f7924SRussell King /* Isn't this already done by sdhci_resume_host() ? --rmk */ 1130723f7924SRussell King esdhc_of_enable_dma(host); 1131f4932cfdSyangbo lu sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); 1132723f7924SRussell King } 1133723f7924SRussell King return ret; 1134723f7924SRussell King } 1135723f7924SRussell King #endif 1136723f7924SRussell King 11379e48b336SUlf Hansson static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, 11389e48b336SUlf Hansson esdhc_of_suspend, 11399e48b336SUlf Hansson esdhc_of_resume); 11409e48b336SUlf Hansson 1141f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_be_ops = { 1142f4932cfdSyangbo lu .read_l = esdhc_be_readl, 1143f4932cfdSyangbo lu .read_w = esdhc_be_readw, 1144f4932cfdSyangbo lu .read_b = esdhc_be_readb, 1145f4932cfdSyangbo lu .write_l = esdhc_be_writel, 1146f4932cfdSyangbo lu .write_w = esdhc_be_writew, 1147f4932cfdSyangbo lu .write_b = esdhc_be_writeb, 1148f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1149f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1150f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1151f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1152f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1153f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1154f4932cfdSyangbo lu .reset = esdhc_reset, 115554e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1156b214fe59SYinbo Zhu .irq = esdhc_irq, 1157f4932cfdSyangbo lu }; 1158f4932cfdSyangbo lu 1159f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_le_ops = { 1160f4932cfdSyangbo lu .read_l = esdhc_le_readl, 1161f4932cfdSyangbo lu .read_w = esdhc_le_readw, 1162f4932cfdSyangbo lu .read_b = esdhc_le_readb, 1163f4932cfdSyangbo lu .write_l = esdhc_le_writel, 1164f4932cfdSyangbo lu .write_w = esdhc_le_writew, 1165f4932cfdSyangbo lu .write_b = esdhc_le_writeb, 1166f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1167f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1168f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1169f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1170f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1171f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1172f4932cfdSyangbo lu .reset = esdhc_reset, 117354e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1174b214fe59SYinbo Zhu .irq = esdhc_irq, 1175f4932cfdSyangbo lu }; 1176f4932cfdSyangbo lu 1177f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { 1178e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1179e9acc77dSyangbo lu #ifdef CONFIG_PPC 1180e9acc77dSyangbo lu SDHCI_QUIRK_BROKEN_CARD_DETECTION | 1181e9acc77dSyangbo lu #endif 1182e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1183e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1184f4932cfdSyangbo lu .ops = &sdhci_esdhc_be_ops, 11857657c3a7SAlbert Herranz }; 118638576af1SShawn Guo 1187f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = { 1188e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1189e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1190e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1191f4932cfdSyangbo lu .ops = &sdhci_esdhc_le_ops, 1192f4932cfdSyangbo lu }; 1193f4932cfdSyangbo lu 1194151ede40Syangbo lu static struct soc_device_attribute soc_incorrect_hostver[] = { 1195151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "1.0", }, 1196151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "2.0", }, 1197151ede40Syangbo lu { }, 1198151ede40Syangbo lu }; 1199151ede40Syangbo lu 12006079e63cSYangbo Lu static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = { 12016079e63cSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 12028e9a6919SYinbo Zhu { .family = "QorIQ LX2160A", .revision = "2.0", }, 12035f3ad196SYinbo Zhu { .family = "QorIQ LS1028A", .revision = "1.0", }, 12046079e63cSYangbo Lu { }, 12056079e63cSYangbo Lu }; 12066079e63cSYangbo Lu 120748e304ccSYangbo Lu static struct soc_device_attribute soc_unreliable_pulse_detection[] = { 120848e304ccSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 120948e304ccSYangbo Lu { }, 121048e304ccSYangbo Lu }; 121148e304ccSYangbo Lu 1212f4932cfdSyangbo lu static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) 1213f4932cfdSyangbo lu { 121467fdfbdfSyinbo.zhu const struct of_device_id *match; 1215f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host; 1216f4932cfdSyangbo lu struct sdhci_esdhc *esdhc; 121719c3a0efSyangbo lu struct device_node *np; 121819c3a0efSyangbo lu struct clk *clk; 121919c3a0efSyangbo lu u32 val; 1220f4932cfdSyangbo lu u16 host_ver; 1221f4932cfdSyangbo lu 1222f4932cfdSyangbo lu pltfm_host = sdhci_priv(host); 12238605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 1224f4932cfdSyangbo lu 1225f4932cfdSyangbo lu host_ver = sdhci_readw(host, SDHCI_HOST_VERSION); 1226f4932cfdSyangbo lu esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> 1227f4932cfdSyangbo lu SDHCI_VENDOR_VER_SHIFT; 1228f4932cfdSyangbo lu esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; 1229151ede40Syangbo lu if (soc_device_match(soc_incorrect_hostver)) 1230151ede40Syangbo lu esdhc->quirk_incorrect_hostver = true; 1231151ede40Syangbo lu else 1232151ede40Syangbo lu esdhc->quirk_incorrect_hostver = false; 123319c3a0efSyangbo lu 12346079e63cSYangbo Lu if (soc_device_match(soc_fixup_sdhc_clkdivs)) 12356079e63cSYangbo Lu esdhc->quirk_limited_clk_division = true; 12366079e63cSYangbo Lu else 12376079e63cSYangbo Lu esdhc->quirk_limited_clk_division = false; 12386079e63cSYangbo Lu 123948e304ccSYangbo Lu if (soc_device_match(soc_unreliable_pulse_detection)) 124048e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = true; 124148e304ccSYangbo Lu else 124248e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = false; 124348e304ccSYangbo Lu 124467fdfbdfSyinbo.zhu match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); 124567fdfbdfSyinbo.zhu if (match) 124667fdfbdfSyinbo.zhu esdhc->clk_fixup = match->data; 124719c3a0efSyangbo lu np = pdev->dev.of_node; 1248f667216cSYangbo Lu 1249f667216cSYangbo Lu if (of_device_is_compatible(np, "fsl,p2020-esdhc")) 1250f667216cSYangbo Lu esdhc->quirk_delay_before_data_reset = true; 1251f667216cSYangbo Lu 125219c3a0efSyangbo lu clk = of_clk_get(np, 0); 125319c3a0efSyangbo lu if (!IS_ERR(clk)) { 125419c3a0efSyangbo lu /* 125519c3a0efSyangbo lu * esdhc->peripheral_clock would be assigned with a value 125619c3a0efSyangbo lu * which is eSDHC base clock when use periperal clock. 1257791463baSYangbo Lu * For some platforms, the clock value got by common clk 1258791463baSYangbo Lu * API is peripheral clock while the eSDHC base clock is 1259791463baSYangbo Lu * 1/2 peripheral clock. 126019c3a0efSyangbo lu */ 1261791463baSYangbo Lu if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || 126266a83febSYangbo Lu of_device_is_compatible(np, "fsl,ls1028a-esdhc") || 126366a83febSYangbo Lu of_device_is_compatible(np, "fsl,ls1088a-esdhc")) 126419c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk) / 2; 126519c3a0efSyangbo lu else 126619c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk); 126719c3a0efSyangbo lu 126819c3a0efSyangbo lu clk_put(clk); 126919c3a0efSyangbo lu } 127019c3a0efSyangbo lu 127119c3a0efSyangbo lu if (esdhc->peripheral_clock) { 127219c3a0efSyangbo lu esdhc_clock_enable(host, false); 127319c3a0efSyangbo lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 127419c3a0efSyangbo lu val |= ESDHC_PERIPHERAL_CLK_SEL; 127519c3a0efSyangbo lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 127619c3a0efSyangbo lu esdhc_clock_enable(host, true); 127719c3a0efSyangbo lu } 1278f4932cfdSyangbo lu } 1279f4932cfdSyangbo lu 128054e08d9aSYangbo Lu static int esdhc_hs400_prepare_ddr(struct mmc_host *mmc) 128154e08d9aSYangbo Lu { 128254e08d9aSYangbo Lu esdhc_tuning_block_enable(mmc_priv(mmc), false); 128354e08d9aSYangbo Lu return 0; 128454e08d9aSYangbo Lu } 128554e08d9aSYangbo Lu 1286c3be1efdSBill Pemberton static int sdhci_esdhc_probe(struct platform_device *pdev) 128738576af1SShawn Guo { 128866b50a00SOded Gabbay struct sdhci_host *host; 1289dcaff04dSOded Gabbay struct device_node *np; 12901ef5e49eSyangbo lu struct sdhci_pltfm_host *pltfm_host; 12911ef5e49eSyangbo lu struct sdhci_esdhc *esdhc; 129266b50a00SOded Gabbay int ret; 129366b50a00SOded Gabbay 1294f4932cfdSyangbo lu np = pdev->dev.of_node; 1295f4932cfdSyangbo lu 1296150d4240SJulia Lawall if (of_property_read_bool(np, "little-endian")) 12978605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, 12988605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1299f4932cfdSyangbo lu else 13008605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, 13018605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1302f4932cfdSyangbo lu 130366b50a00SOded Gabbay if (IS_ERR(host)) 130466b50a00SOded Gabbay return PTR_ERR(host); 130566b50a00SOded Gabbay 1306ea35645aSyangbo lu host->mmc_host_ops.start_signal_voltage_switch = 1307ea35645aSyangbo lu esdhc_signal_voltage_switch; 1308ba49cbd0Syangbo lu host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; 130954e08d9aSYangbo Lu host->mmc_host_ops.hs400_prepare_ddr = esdhc_hs400_prepare_ddr; 13106b236f37Syangbo lu host->tuning_delay = 1; 1311ea35645aSyangbo lu 1312f4932cfdSyangbo lu esdhc_init(pdev, host); 1313f4932cfdSyangbo lu 131466b50a00SOded Gabbay sdhci_get_of_property(pdev); 131566b50a00SOded Gabbay 13161ef5e49eSyangbo lu pltfm_host = sdhci_priv(host); 13178605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 131822dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type1)) 131922dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = true; 1320b1f378abSYinbo Zhu else 132122dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = false; 132222dc132dSYangbo Lu 132322dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type2)) 132422dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = true; 132522dc132dSYangbo Lu else 132622dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = false; 1327b1f378abSYinbo Zhu 13281ef5e49eSyangbo lu if (esdhc->vendor_ver == VENDOR_V_22) 13291ef5e49eSyangbo lu host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; 13301ef5e49eSyangbo lu 13311ef5e49eSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) 13321ef5e49eSyangbo lu host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; 13331ef5e49eSyangbo lu 133405cb6b2aSYinbo Zhu if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { 1335fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; 1336fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 133705cb6b2aSYinbo Zhu } 1338a46e4271SYinbo Zhu 133974fd5e30SYangbo Lu if (of_device_is_compatible(np, "fsl,p5040-esdhc") || 134074fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p5020-esdhc") || 134174fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p4080-esdhc") || 134274fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p1020-esdhc") || 1343e9acc77dSyangbo lu of_device_is_compatible(np, "fsl,t1040-esdhc")) 134474fd5e30SYangbo Lu host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; 134574fd5e30SYangbo Lu 1346a22950c8Syangbo lu if (of_device_is_compatible(np, "fsl,ls1021a-esdhc")) 1347a22950c8Syangbo lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 1348a22950c8Syangbo lu 13491f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = false; 1350dcaff04dSOded Gabbay if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 1351dcaff04dSOded Gabbay /* 1352dcaff04dSOded Gabbay * Freescale messed up with P2020 as it has a non-standard 1353dcaff04dSOded Gabbay * host control register 1354dcaff04dSOded Gabbay */ 1355dcaff04dSOded Gabbay host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; 13561f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = true; 1357dcaff04dSOded Gabbay } 1358dcaff04dSOded Gabbay 135966b50a00SOded Gabbay /* call to generic mmc_of_parse to support additional capabilities */ 1360f0991408SUlf Hansson ret = mmc_of_parse(host->mmc); 1361f0991408SUlf Hansson if (ret) 1362f0991408SUlf Hansson goto err; 1363f0991408SUlf Hansson 1364490104acSHaijun Zhang mmc_of_parse_voltage(np, &host->ocr_mask); 136566b50a00SOded Gabbay 136666b50a00SOded Gabbay ret = sdhci_add_host(host); 136766b50a00SOded Gabbay if (ret) 1368f0991408SUlf Hansson goto err; 136966b50a00SOded Gabbay 1370f0991408SUlf Hansson return 0; 1371f0991408SUlf Hansson err: 1372f0991408SUlf Hansson sdhci_pltfm_free(pdev); 137366b50a00SOded Gabbay return ret; 137438576af1SShawn Guo } 137538576af1SShawn Guo 137638576af1SShawn Guo static struct platform_driver sdhci_esdhc_driver = { 137738576af1SShawn Guo .driver = { 137838576af1SShawn Guo .name = "sdhci-esdhc", 137938576af1SShawn Guo .of_match_table = sdhci_esdhc_of_match, 13809e48b336SUlf Hansson .pm = &esdhc_of_dev_pm_ops, 138138576af1SShawn Guo }, 138238576af1SShawn Guo .probe = sdhci_esdhc_probe, 1383caebcae9SKevin Hao .remove = sdhci_pltfm_unregister, 138438576af1SShawn Guo }; 138538576af1SShawn Guo 1386d1f81a64SAxel Lin module_platform_driver(sdhci_esdhc_driver); 138738576af1SShawn Guo 138838576af1SShawn Guo MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); 138938576af1SShawn Guo MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " 139038576af1SShawn Guo "Anton Vorontsov <avorontsov@ru.mvista.com>"); 139138576af1SShawn Guo MODULE_LICENSE("GPL v2"); 1392