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; 84*060522d8SChris Packham bool quirk_trans_complete_erratum; 8522dc132dSYangbo Lu bool in_sw_tuning; 8619c3a0efSyangbo lu unsigned int peripheral_clock; 8767fdfbdfSyinbo.zhu const struct esdhc_clk_fixup *clk_fixup; 88b1f378abSYinbo Zhu u32 div_ratio; 89f4932cfdSyangbo lu }; 90f4932cfdSyangbo lu 91f4932cfdSyangbo lu /** 92f4932cfdSyangbo lu * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register 93f4932cfdSyangbo lu * to make it compatible with SD spec. 94f4932cfdSyangbo lu * 95f4932cfdSyangbo lu * @host: pointer to sdhci_host 96f4932cfdSyangbo lu * @spec_reg: SD spec register address 97f4932cfdSyangbo lu * @value: 32bit eSDHC register value on spec_reg address 98f4932cfdSyangbo lu * 99f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 100f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 101f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 102f4932cfdSyangbo lu * and SD spec. 103f4932cfdSyangbo lu * 104f4932cfdSyangbo lu * Return a fixed up register value 105f4932cfdSyangbo lu */ 106f4932cfdSyangbo lu static u32 esdhc_readl_fixup(struct sdhci_host *host, 107f4932cfdSyangbo lu int spec_reg, u32 value) 108137ccd46SJerry Huang { 109f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1108605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 111137ccd46SJerry Huang u32 ret; 112137ccd46SJerry Huang 113137ccd46SJerry Huang /* 114137ccd46SJerry Huang * The bit of ADMA flag in eSDHC is not compatible with standard 115137ccd46SJerry Huang * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is 116137ccd46SJerry Huang * supported by eSDHC. 117137ccd46SJerry Huang * And for many FSL eSDHC controller, the reset value of field 118f4932cfdSyangbo lu * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA, 119137ccd46SJerry Huang * only these vendor version is greater than 2.2/0x12 support ADMA. 120137ccd46SJerry Huang */ 121f4932cfdSyangbo lu if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) { 122f4932cfdSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) { 123f4932cfdSyangbo lu ret = value | SDHCI_CAN_DO_ADMA2; 124f4932cfdSyangbo lu return ret; 125137ccd46SJerry Huang } 126f4932cfdSyangbo lu } 127b0921d5cSMichael Walle /* 128b0921d5cSMichael Walle * The DAT[3:0] line signal levels and the CMD line signal level are 129b0921d5cSMichael Walle * not compatible with standard SDHC register. The line signal levels 130b0921d5cSMichael Walle * DAT[7:0] are at bits 31:24 and the command line signal level is at 131b0921d5cSMichael Walle * bit 23. All other bits are the same as in the standard SDHC 132b0921d5cSMichael Walle * register. 133b0921d5cSMichael Walle */ 134b0921d5cSMichael Walle if (spec_reg == SDHCI_PRESENT_STATE) { 135b0921d5cSMichael Walle ret = value & 0x000fffff; 136b0921d5cSMichael Walle ret |= (value >> 4) & SDHCI_DATA_LVL_MASK; 137b0921d5cSMichael Walle ret |= (value << 1) & SDHCI_CMD_LVL; 138b0921d5cSMichael Walle return ret; 139b0921d5cSMichael Walle } 140b0921d5cSMichael Walle 1412f3110ccSyangbo lu /* 1422f3110ccSyangbo lu * DTS properties of mmc host are used to enable each speed mode 1432f3110ccSyangbo lu * according to soc and board capability. So clean up 1442f3110ccSyangbo lu * SDR50/SDR104/DDR50 support bits here. 1452f3110ccSyangbo lu */ 1462f3110ccSyangbo lu if (spec_reg == SDHCI_CAPABILITIES_1) { 1472f3110ccSyangbo lu ret = value & ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | 1482f3110ccSyangbo lu SDHCI_SUPPORT_DDR50); 1492f3110ccSyangbo lu return ret; 1502f3110ccSyangbo lu } 1512f3110ccSyangbo lu 1521f1929f3SYangbo Lu /* 1531f1929f3SYangbo Lu * Some controllers have unreliable Data Line Active 1541f1929f3SYangbo Lu * bit for commands with busy signal. This affects 1551f1929f3SYangbo Lu * Command Inhibit (data) bit. Just ignore it since 1561f1929f3SYangbo Lu * MMC core driver has already polled card status 1571f1929f3SYangbo Lu * with CMD13 after any command with busy siganl. 1581f1929f3SYangbo Lu */ 1591f1929f3SYangbo Lu if ((spec_reg == SDHCI_PRESENT_STATE) && 1601f1929f3SYangbo Lu (esdhc->quirk_ignore_data_inhibit == true)) { 1611f1929f3SYangbo Lu ret = value & ~SDHCI_DATA_INHIBIT; 1621f1929f3SYangbo Lu return ret; 1631f1929f3SYangbo Lu } 1641f1929f3SYangbo Lu 165f4932cfdSyangbo lu ret = value; 166137ccd46SJerry Huang return ret; 167137ccd46SJerry Huang } 168137ccd46SJerry Huang 169f4932cfdSyangbo lu static u16 esdhc_readw_fixup(struct sdhci_host *host, 170f4932cfdSyangbo lu int spec_reg, u32 value) 1717657c3a7SAlbert Herranz { 172151ede40Syangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 173151ede40Syangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1747657c3a7SAlbert Herranz u16 ret; 175f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 1767657c3a7SAlbert Herranz 177429d939cSYangbo Lu if (spec_reg == SDHCI_TRANSFER_MODE) 178429d939cSYangbo Lu return pltfm_host->xfer_mode_shadow; 179429d939cSYangbo Lu 180f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_VERSION) 181f4932cfdSyangbo lu ret = value & 0xffff; 1827657c3a7SAlbert Herranz else 183f4932cfdSyangbo lu ret = (value >> shift) & 0xffff; 184151ede40Syangbo lu /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect 185151ede40Syangbo lu * vendor version and spec version information. 186151ede40Syangbo lu */ 187151ede40Syangbo lu if ((spec_reg == SDHCI_HOST_VERSION) && 188151ede40Syangbo lu (esdhc->quirk_incorrect_hostver)) 189151ede40Syangbo lu ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200; 190e51cbc9eSXu lei return ret; 191e51cbc9eSXu lei } 192e51cbc9eSXu lei 193f4932cfdSyangbo lu static u8 esdhc_readb_fixup(struct sdhci_host *host, 194f4932cfdSyangbo lu int spec_reg, u32 value) 195e51cbc9eSXu lei { 196f4932cfdSyangbo lu u8 ret; 197f4932cfdSyangbo lu u8 dma_bits; 198f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 199f4932cfdSyangbo lu 200f4932cfdSyangbo lu ret = (value >> shift) & 0xff; 201ba8c4dc9SRoy Zang 202ba8c4dc9SRoy Zang /* 203ba8c4dc9SRoy Zang * "DMA select" locates at offset 0x28 in SD specification, but on 204ba8c4dc9SRoy Zang * P5020 or P3041, it locates at 0x29. 205ba8c4dc9SRoy Zang */ 206f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 207ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 208f4932cfdSyangbo lu dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK; 209ba8c4dc9SRoy Zang /* fixup the result */ 210ba8c4dc9SRoy Zang ret &= ~SDHCI_CTRL_DMA_MASK; 211ba8c4dc9SRoy Zang ret |= dma_bits; 212ba8c4dc9SRoy Zang } 213f4932cfdSyangbo lu return ret; 214f4932cfdSyangbo lu } 215f4932cfdSyangbo lu 216f4932cfdSyangbo lu /** 217f4932cfdSyangbo lu * esdhc_write*_fixup - Fixup the SD spec register value so that it could be 218f4932cfdSyangbo lu * written into eSDHC register. 219f4932cfdSyangbo lu * 220f4932cfdSyangbo lu * @host: pointer to sdhci_host 221f4932cfdSyangbo lu * @spec_reg: SD spec register address 222f4932cfdSyangbo lu * @value: 8/16/32bit SD spec register value that would be written 223f4932cfdSyangbo lu * @old_value: 32bit eSDHC register value on spec_reg address 224f4932cfdSyangbo lu * 225f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 226f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 227f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 228f4932cfdSyangbo lu * and SD spec. 229f4932cfdSyangbo lu * 230f4932cfdSyangbo lu * Return a fixed up register value 231f4932cfdSyangbo lu */ 232f4932cfdSyangbo lu static u32 esdhc_writel_fixup(struct sdhci_host *host, 233f4932cfdSyangbo lu int spec_reg, u32 value, u32 old_value) 234f4932cfdSyangbo lu { 235f4932cfdSyangbo lu u32 ret; 236f4932cfdSyangbo lu 237f4932cfdSyangbo lu /* 238f4932cfdSyangbo lu * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] 239f4932cfdSyangbo lu * when SYSCTL[RSTD] is set for some special operations. 240f4932cfdSyangbo lu * No any impact on other operation. 241f4932cfdSyangbo lu */ 242f4932cfdSyangbo lu if (spec_reg == SDHCI_INT_ENABLE) 243f4932cfdSyangbo lu ret = value | SDHCI_INT_BLK_GAP; 244f4932cfdSyangbo lu else 245f4932cfdSyangbo lu ret = value; 246ba8c4dc9SRoy Zang 2477657c3a7SAlbert Herranz return ret; 2487657c3a7SAlbert Herranz } 2497657c3a7SAlbert Herranz 250f4932cfdSyangbo lu static u32 esdhc_writew_fixup(struct sdhci_host *host, 251f4932cfdSyangbo lu int spec_reg, u16 value, u32 old_value) 252a4071fbbSHaijun Zhang { 253f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 254f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 255f4932cfdSyangbo lu u32 ret; 256f4932cfdSyangbo lu 257f4932cfdSyangbo lu switch (spec_reg) { 258f4932cfdSyangbo lu case SDHCI_TRANSFER_MODE: 259a4071fbbSHaijun Zhang /* 260f4932cfdSyangbo lu * Postpone this write, we must do it together with a 261f4932cfdSyangbo lu * command write that is down below. Return old value. 262a4071fbbSHaijun Zhang */ 263f4932cfdSyangbo lu pltfm_host->xfer_mode_shadow = value; 264f4932cfdSyangbo lu return old_value; 265f4932cfdSyangbo lu case SDHCI_COMMAND: 266f4932cfdSyangbo lu ret = (value << 16) | pltfm_host->xfer_mode_shadow; 267f4932cfdSyangbo lu return ret; 268a4071fbbSHaijun Zhang } 269a4071fbbSHaijun Zhang 270f4932cfdSyangbo lu ret = old_value & (~(0xffff << shift)); 271f4932cfdSyangbo lu ret |= (value << shift); 272f4932cfdSyangbo lu 273f4932cfdSyangbo lu if (spec_reg == SDHCI_BLOCK_SIZE) { 2747657c3a7SAlbert Herranz /* 2757657c3a7SAlbert Herranz * Two last DMA bits are reserved, and first one is used for 2767657c3a7SAlbert Herranz * non-standard blksz of 4096 bytes that we don't support 2777657c3a7SAlbert Herranz * yet. So clear the DMA boundary bits. 2787657c3a7SAlbert Herranz */ 279f4932cfdSyangbo lu ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0)); 2807657c3a7SAlbert Herranz } 281f4932cfdSyangbo lu return ret; 2827657c3a7SAlbert Herranz } 2837657c3a7SAlbert Herranz 284f4932cfdSyangbo lu static u32 esdhc_writeb_fixup(struct sdhci_host *host, 285f4932cfdSyangbo lu int spec_reg, u8 value, u32 old_value) 2867657c3a7SAlbert Herranz { 287f4932cfdSyangbo lu u32 ret; 288f4932cfdSyangbo lu u32 dma_bits; 289f4932cfdSyangbo lu u8 tmp; 290f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 291f4932cfdSyangbo lu 292ba8c4dc9SRoy Zang /* 2939e4703dfSyangbo lu * eSDHC doesn't have a standard power control register, so we do 2949e4703dfSyangbo lu * nothing here to avoid incorrect operation. 2959e4703dfSyangbo lu */ 2969e4703dfSyangbo lu if (spec_reg == SDHCI_POWER_CONTROL) 2979e4703dfSyangbo lu return old_value; 2989e4703dfSyangbo lu /* 299ba8c4dc9SRoy Zang * "DMA select" location is offset 0x28 in SD specification, but on 300ba8c4dc9SRoy Zang * P5020 or P3041, it's located at 0x29. 301ba8c4dc9SRoy Zang */ 302f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 303dcaff04dSOded Gabbay /* 304dcaff04dSOded Gabbay * If host control register is not standard, exit 305dcaff04dSOded Gabbay * this function 306dcaff04dSOded Gabbay */ 307dcaff04dSOded Gabbay if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) 308f4932cfdSyangbo lu return old_value; 309dcaff04dSOded Gabbay 310ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 311f4932cfdSyangbo lu dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5; 312f4932cfdSyangbo lu ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits; 313f4932cfdSyangbo lu tmp = (value & (~SDHCI_CTRL_DMA_MASK)) | 314f4932cfdSyangbo lu (old_value & SDHCI_CTRL_DMA_MASK); 315f4932cfdSyangbo lu ret = (ret & (~0xff)) | tmp; 316f4932cfdSyangbo lu 317f4932cfdSyangbo lu /* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */ 318f4932cfdSyangbo lu ret &= ~ESDHC_HOST_CONTROL_RES; 319f4932cfdSyangbo lu return ret; 320ba8c4dc9SRoy Zang } 321ba8c4dc9SRoy Zang 322f4932cfdSyangbo lu ret = (old_value & (~(0xff << shift))) | (value << shift); 323f4932cfdSyangbo lu return ret; 324f4932cfdSyangbo lu } 325f4932cfdSyangbo lu 326f4932cfdSyangbo lu static u32 esdhc_be_readl(struct sdhci_host *host, int reg) 327f4932cfdSyangbo lu { 328f4932cfdSyangbo lu u32 ret; 329f4932cfdSyangbo lu u32 value; 330f4932cfdSyangbo lu 3312f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3322f3110ccSyangbo lu value = ioread32be(host->ioaddr + ESDHC_CAPABILITIES_1); 3332f3110ccSyangbo lu else 334f4932cfdSyangbo lu value = ioread32be(host->ioaddr + reg); 3352f3110ccSyangbo lu 336f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 337f4932cfdSyangbo lu 338f4932cfdSyangbo lu return ret; 339f4932cfdSyangbo lu } 340f4932cfdSyangbo lu 341f4932cfdSyangbo lu static u32 esdhc_le_readl(struct sdhci_host *host, int reg) 342f4932cfdSyangbo lu { 343f4932cfdSyangbo lu u32 ret; 344f4932cfdSyangbo lu u32 value; 345f4932cfdSyangbo lu 3462f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3472f3110ccSyangbo lu value = ioread32(host->ioaddr + ESDHC_CAPABILITIES_1); 3482f3110ccSyangbo lu else 349f4932cfdSyangbo lu value = ioread32(host->ioaddr + reg); 3502f3110ccSyangbo lu 351f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 352f4932cfdSyangbo lu 353f4932cfdSyangbo lu return ret; 354f4932cfdSyangbo lu } 355f4932cfdSyangbo lu 356f4932cfdSyangbo lu static u16 esdhc_be_readw(struct sdhci_host *host, int reg) 357f4932cfdSyangbo lu { 358f4932cfdSyangbo lu u16 ret; 359f4932cfdSyangbo lu u32 value; 360f4932cfdSyangbo lu int base = reg & ~0x3; 361f4932cfdSyangbo lu 362f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 363f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 364f4932cfdSyangbo lu return ret; 365f4932cfdSyangbo lu } 366f4932cfdSyangbo lu 367f4932cfdSyangbo lu static u16 esdhc_le_readw(struct sdhci_host *host, int reg) 368f4932cfdSyangbo lu { 369f4932cfdSyangbo lu u16 ret; 370f4932cfdSyangbo lu u32 value; 371f4932cfdSyangbo lu int base = reg & ~0x3; 372f4932cfdSyangbo lu 373f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 374f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 375f4932cfdSyangbo lu return ret; 376f4932cfdSyangbo lu } 377f4932cfdSyangbo lu 378f4932cfdSyangbo lu static u8 esdhc_be_readb(struct sdhci_host *host, int reg) 379f4932cfdSyangbo lu { 380f4932cfdSyangbo lu u8 ret; 381f4932cfdSyangbo lu u32 value; 382f4932cfdSyangbo lu int base = reg & ~0x3; 383f4932cfdSyangbo lu 384f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 385f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 386f4932cfdSyangbo lu return ret; 387f4932cfdSyangbo lu } 388f4932cfdSyangbo lu 389f4932cfdSyangbo lu static u8 esdhc_le_readb(struct sdhci_host *host, int reg) 390f4932cfdSyangbo lu { 391f4932cfdSyangbo lu u8 ret; 392f4932cfdSyangbo lu u32 value; 393f4932cfdSyangbo lu int base = reg & ~0x3; 394f4932cfdSyangbo lu 395f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 396f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 397f4932cfdSyangbo lu return ret; 398f4932cfdSyangbo lu } 399f4932cfdSyangbo lu 400f4932cfdSyangbo lu static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg) 401f4932cfdSyangbo lu { 402f4932cfdSyangbo lu u32 value; 403f4932cfdSyangbo lu 404f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 405f4932cfdSyangbo lu iowrite32be(value, host->ioaddr + reg); 406f4932cfdSyangbo lu } 407f4932cfdSyangbo lu 408f4932cfdSyangbo lu static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg) 409f4932cfdSyangbo lu { 410f4932cfdSyangbo lu u32 value; 411f4932cfdSyangbo lu 412f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 413f4932cfdSyangbo lu iowrite32(value, host->ioaddr + reg); 414f4932cfdSyangbo lu } 415f4932cfdSyangbo lu 416f4932cfdSyangbo lu static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg) 417f4932cfdSyangbo lu { 41822dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 41922dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 420f4932cfdSyangbo lu int base = reg & ~0x3; 421f4932cfdSyangbo lu u32 value; 422f4932cfdSyangbo lu u32 ret; 423f4932cfdSyangbo lu 424f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 425f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 426f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 427f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 42822dc132dSYangbo Lu 42922dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 43022dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 43122dc132dSYangbo Lu */ 43222dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 43322dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 43422dc132dSYangbo Lu esdhc->in_sw_tuning) { 43522dc132dSYangbo Lu udelay(1); 43622dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 43722dc132dSYangbo Lu iowrite32be(ret, host->ioaddr + base); 43822dc132dSYangbo Lu } 43922dc132dSYangbo Lu } 440f4932cfdSyangbo lu } 441f4932cfdSyangbo lu 442f4932cfdSyangbo lu static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg) 443f4932cfdSyangbo lu { 44422dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 44522dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 446f4932cfdSyangbo lu int base = reg & ~0x3; 447f4932cfdSyangbo lu u32 value; 448f4932cfdSyangbo lu u32 ret; 449f4932cfdSyangbo lu 450f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 451f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 452f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 453f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 45422dc132dSYangbo Lu 45522dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 45622dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 45722dc132dSYangbo Lu */ 45822dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 45922dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 46022dc132dSYangbo Lu esdhc->in_sw_tuning) { 46122dc132dSYangbo Lu udelay(1); 46222dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 46322dc132dSYangbo Lu iowrite32(ret, host->ioaddr + base); 46422dc132dSYangbo Lu } 46522dc132dSYangbo Lu } 466f4932cfdSyangbo lu } 467f4932cfdSyangbo lu 468f4932cfdSyangbo lu static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg) 469f4932cfdSyangbo lu { 470f4932cfdSyangbo lu int base = reg & ~0x3; 471f4932cfdSyangbo lu u32 value; 472f4932cfdSyangbo lu u32 ret; 473f4932cfdSyangbo lu 474f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 475f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 476f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 477f4932cfdSyangbo lu } 478f4932cfdSyangbo lu 479f4932cfdSyangbo lu static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg) 480f4932cfdSyangbo lu { 481f4932cfdSyangbo lu int base = reg & ~0x3; 482f4932cfdSyangbo lu u32 value; 483f4932cfdSyangbo lu u32 ret; 484f4932cfdSyangbo lu 485f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 486f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 487f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 4887657c3a7SAlbert Herranz } 4897657c3a7SAlbert Herranz 490a4071fbbSHaijun Zhang /* 491a4071fbbSHaijun Zhang * For Abort or Suspend after Stop at Block Gap, ignore the ADMA 492a4071fbbSHaijun Zhang * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) 493a4071fbbSHaijun Zhang * and Block Gap Event(IRQSTAT[BGE]) are also set. 494a4071fbbSHaijun Zhang * For Continue, apply soft reset for data(SYSCTL[RSTD]); 495a4071fbbSHaijun Zhang * and re-issue the entire read transaction from beginning. 496a4071fbbSHaijun Zhang */ 497f4932cfdSyangbo lu static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) 498a4071fbbSHaijun Zhang { 499f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 5008605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 501a4071fbbSHaijun Zhang bool applicable; 502a4071fbbSHaijun Zhang dma_addr_t dmastart; 503a4071fbbSHaijun Zhang dma_addr_t dmanow; 504a4071fbbSHaijun Zhang 505a4071fbbSHaijun Zhang applicable = (intmask & SDHCI_INT_DATA_END) && 506a4071fbbSHaijun Zhang (intmask & SDHCI_INT_BLK_GAP) && 507f4932cfdSyangbo lu (esdhc->vendor_ver == VENDOR_V_23); 508a4071fbbSHaijun Zhang if (!applicable) 509a4071fbbSHaijun Zhang return; 510a4071fbbSHaijun Zhang 511a4071fbbSHaijun Zhang host->data->error = 0; 512a4071fbbSHaijun Zhang dmastart = sg_dma_address(host->data->sg); 513a4071fbbSHaijun Zhang dmanow = dmastart + host->data->bytes_xfered; 514a4071fbbSHaijun Zhang /* 515a4071fbbSHaijun Zhang * Force update to the next DMA block boundary. 516a4071fbbSHaijun Zhang */ 517a4071fbbSHaijun Zhang dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 518a4071fbbSHaijun Zhang SDHCI_DEFAULT_BOUNDARY_SIZE; 519a4071fbbSHaijun Zhang host->data->bytes_xfered = dmanow - dmastart; 520a4071fbbSHaijun Zhang sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); 521a4071fbbSHaijun Zhang } 522a4071fbbSHaijun Zhang 52380872e21SWolfram Sang static int esdhc_of_enable_dma(struct sdhci_host *host) 5247657c3a7SAlbert Herranz { 525f4932cfdSyangbo lu u32 value; 5265552d7adSLaurentiu Tudor struct device *dev = mmc_dev(host->mmc); 5275552d7adSLaurentiu Tudor 5285552d7adSLaurentiu Tudor if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || 5295552d7adSLaurentiu Tudor of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) 5305552d7adSLaurentiu Tudor dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); 531f4932cfdSyangbo lu 532f4932cfdSyangbo lu value = sdhci_readl(host, ESDHC_DMA_SYSCTL); 533121bd08bSRussell King 534121bd08bSRussell King if (of_dma_is_coherent(dev->of_node)) 535f4932cfdSyangbo lu value |= ESDHC_DMA_SNOOP; 536121bd08bSRussell King else 537121bd08bSRussell King value &= ~ESDHC_DMA_SNOOP; 538121bd08bSRussell King 539f4932cfdSyangbo lu sdhci_writel(host, value, ESDHC_DMA_SYSCTL); 5407657c3a7SAlbert Herranz return 0; 5417657c3a7SAlbert Herranz } 5427657c3a7SAlbert Herranz 54380872e21SWolfram Sang static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host) 5447657c3a7SAlbert Herranz { 545e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 54619c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 5477657c3a7SAlbert Herranz 54819c3a0efSyangbo lu if (esdhc->peripheral_clock) 54919c3a0efSyangbo lu return esdhc->peripheral_clock; 55019c3a0efSyangbo lu else 551e307148fSShawn Guo return pltfm_host->clock; 5527657c3a7SAlbert Herranz } 5537657c3a7SAlbert Herranz 55480872e21SWolfram Sang static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) 5557657c3a7SAlbert Herranz { 556e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 55719c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 55819c3a0efSyangbo lu unsigned int clock; 5597657c3a7SAlbert Herranz 56019c3a0efSyangbo lu if (esdhc->peripheral_clock) 56119c3a0efSyangbo lu clock = esdhc->peripheral_clock; 56219c3a0efSyangbo lu else 56319c3a0efSyangbo lu clock = pltfm_host->clock; 56419c3a0efSyangbo lu return clock / 256 / 16; 5657657c3a7SAlbert Herranz } 5667657c3a7SAlbert Herranz 567dd3f6983Syangbo lu static void esdhc_clock_enable(struct sdhci_host *host, bool enable) 568dd3f6983Syangbo lu { 5691b21a701SYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 5701b21a701SYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 571dd3f6983Syangbo lu ktime_t timeout; 5721b21a701SYangbo Lu u32 val, clk_en; 5731b21a701SYangbo Lu 5741b21a701SYangbo Lu clk_en = ESDHC_CLOCK_SDCLKEN; 5751b21a701SYangbo Lu 5761b21a701SYangbo Lu /* 5771b21a701SYangbo Lu * IPGEN/HCKEN/PEREN bits exist on eSDHC whose vendor version 5781b21a701SYangbo Lu * is 2.2 or lower. 5791b21a701SYangbo Lu */ 5801b21a701SYangbo Lu if (esdhc->vendor_ver <= VENDOR_V_22) 5811b21a701SYangbo Lu clk_en |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | 5821b21a701SYangbo Lu ESDHC_CLOCK_PEREN); 583dd3f6983Syangbo lu 584dd3f6983Syangbo lu val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 585dd3f6983Syangbo lu 586dd3f6983Syangbo lu if (enable) 5871b21a701SYangbo Lu val |= clk_en; 588dd3f6983Syangbo lu else 5891b21a701SYangbo Lu val &= ~clk_en; 590dd3f6983Syangbo lu 591dd3f6983Syangbo lu sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL); 592dd3f6983Syangbo lu 5931b21a701SYangbo Lu /* 5941b21a701SYangbo Lu * Wait max 20 ms. If vendor version is 2.2 or lower, do not 5951b21a701SYangbo Lu * wait clock stable bit which does not exist. 5961b21a701SYangbo Lu */ 597dd3f6983Syangbo lu timeout = ktime_add_ms(ktime_get(), 20); 5981b21a701SYangbo Lu while (esdhc->vendor_ver > VENDOR_V_22) { 599ea6d0273SAdrian Hunter bool timedout = ktime_after(ktime_get(), timeout); 600ea6d0273SAdrian Hunter 6011b21a701SYangbo Lu if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) 602ea6d0273SAdrian Hunter break; 603ea6d0273SAdrian Hunter if (timedout) { 604dd3f6983Syangbo lu pr_err("%s: Internal clock never stabilised.\n", 605dd3f6983Syangbo lu mmc_hostname(host->mmc)); 606dd3f6983Syangbo lu break; 607dd3f6983Syangbo lu } 6081b21a701SYangbo Lu usleep_range(10, 20); 609dd3f6983Syangbo lu } 610dd3f6983Syangbo lu } 611dd3f6983Syangbo lu 6126e32f65cSYangbo Lu static void esdhc_flush_async_fifo(struct sdhci_host *host) 6136e32f65cSYangbo Lu { 6146e32f65cSYangbo Lu ktime_t timeout; 6156e32f65cSYangbo Lu u32 val; 6166e32f65cSYangbo Lu 6176e32f65cSYangbo Lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 6186e32f65cSYangbo Lu val |= ESDHC_FLUSH_ASYNC_FIFO; 6196e32f65cSYangbo Lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 6206e32f65cSYangbo Lu 6216e32f65cSYangbo Lu /* Wait max 20 ms */ 6226e32f65cSYangbo Lu timeout = ktime_add_ms(ktime_get(), 20); 6236e32f65cSYangbo Lu while (1) { 6246e32f65cSYangbo Lu bool timedout = ktime_after(ktime_get(), timeout); 6256e32f65cSYangbo Lu 6266e32f65cSYangbo Lu if (!(sdhci_readl(host, ESDHC_DMA_SYSCTL) & 6276e32f65cSYangbo Lu ESDHC_FLUSH_ASYNC_FIFO)) 6286e32f65cSYangbo Lu break; 6296e32f65cSYangbo Lu if (timedout) { 6306e32f65cSYangbo Lu pr_err("%s: flushing asynchronous FIFO timeout.\n", 6316e32f65cSYangbo Lu mmc_hostname(host->mmc)); 6326e32f65cSYangbo Lu break; 6336e32f65cSYangbo Lu } 6346e32f65cSYangbo Lu usleep_range(10, 20); 6356e32f65cSYangbo Lu } 6366e32f65cSYangbo Lu } 6376e32f65cSYangbo Lu 638f060bc9cSJerry Huang static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) 639f060bc9cSJerry Huang { 640f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 6418605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 6421b21a701SYangbo Lu unsigned int pre_div = 1, div = 1; 6431b21a701SYangbo Lu unsigned int clock_fixup = 0; 644e145ac45Syangbo lu ktime_t timeout; 645d31fc00aSDong Aisheng u32 temp; 646d31fc00aSDong Aisheng 647dd3f6983Syangbo lu if (clock == 0) { 6481b21a701SYangbo Lu host->mmc->actual_clock = 0; 649dd3f6983Syangbo lu esdhc_clock_enable(host, false); 650373073efSRussell King return; 651dd3f6983Syangbo lu } 652d31fc00aSDong Aisheng 6531b21a701SYangbo Lu /* Start pre_div at 2 for vendor version < 2.3. */ 654f4932cfdSyangbo lu if (esdhc->vendor_ver < VENDOR_V_23) 65577bd2f6fSYangbo Lu pre_div = 2; 65677bd2f6fSYangbo Lu 6571b21a701SYangbo Lu /* Fix clock value. */ 65867fdfbdfSyinbo.zhu if (host->mmc->card && mmc_card_sd(host->mmc->card) && 65967fdfbdfSyinbo.zhu esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) 6601b21a701SYangbo Lu clock_fixup = esdhc->clk_fixup->sd_dflt_max_clk; 66167fdfbdfSyinbo.zhu else if (esdhc->clk_fixup) 6621b21a701SYangbo Lu clock_fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; 663a627f025Syangbo lu 6641b21a701SYangbo Lu if (clock_fixup == 0 || clock < clock_fixup) 6651b21a701SYangbo Lu clock_fixup = clock; 666f060bc9cSJerry Huang 6671b21a701SYangbo Lu /* Calculate pre_div and div. */ 6681b21a701SYangbo Lu while (host->max_clk / pre_div / 16 > clock_fixup && pre_div < 256) 669d31fc00aSDong Aisheng pre_div *= 2; 670d31fc00aSDong Aisheng 6711b21a701SYangbo Lu while (host->max_clk / pre_div / div > clock_fixup && div < 16) 672d31fc00aSDong Aisheng div++; 673d31fc00aSDong Aisheng 6741b21a701SYangbo Lu esdhc->div_ratio = pre_div * div; 6751b21a701SYangbo Lu 6761b21a701SYangbo Lu /* Limit clock division for HS400 200MHz clock for quirk. */ 6776079e63cSYangbo Lu if (esdhc->quirk_limited_clk_division && 6786079e63cSYangbo Lu clock == MMC_HS200_MAX_DTR && 6796079e63cSYangbo Lu (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 || 6806079e63cSYangbo Lu host->flags & SDHCI_HS400_TUNING)) { 6811b21a701SYangbo Lu if (esdhc->div_ratio <= 4) { 6826079e63cSYangbo Lu pre_div = 4; 6836079e63cSYangbo Lu div = 1; 6841b21a701SYangbo Lu } else if (esdhc->div_ratio <= 8) { 6856079e63cSYangbo Lu pre_div = 4; 6866079e63cSYangbo Lu div = 2; 6871b21a701SYangbo Lu } else if (esdhc->div_ratio <= 12) { 6886079e63cSYangbo Lu pre_div = 4; 6896079e63cSYangbo Lu div = 3; 6906079e63cSYangbo Lu } else { 691b11c36d5SColin Ian King pr_warn("%s: using unsupported clock division.\n", 6926079e63cSYangbo Lu mmc_hostname(host->mmc)); 6936079e63cSYangbo Lu } 6941b21a701SYangbo Lu esdhc->div_ratio = pre_div * div; 6956079e63cSYangbo Lu } 6966079e63cSYangbo Lu 6971b21a701SYangbo Lu host->mmc->actual_clock = host->max_clk / esdhc->div_ratio; 6981b21a701SYangbo Lu 699d31fc00aSDong Aisheng dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", 7001b21a701SYangbo Lu clock, host->mmc->actual_clock); 7011b21a701SYangbo Lu 7021b21a701SYangbo Lu /* Set clock division into register. */ 703d31fc00aSDong Aisheng pre_div >>= 1; 704d31fc00aSDong Aisheng div--; 705d31fc00aSDong Aisheng 7061b21a701SYangbo Lu esdhc_clock_enable(host, false); 7071b21a701SYangbo Lu 708d31fc00aSDong Aisheng temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 7091b21a701SYangbo Lu temp &= ~ESDHC_CLOCK_MASK; 7101b21a701SYangbo Lu temp |= ((div << ESDHC_DIVIDER_SHIFT) | 7111b21a701SYangbo Lu (pre_div << ESDHC_PREDIV_SHIFT)); 712d31fc00aSDong Aisheng sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 713e87d2db2Syangbo lu 7141b21a701SYangbo Lu /* 7151b21a701SYangbo Lu * Wait max 20 ms. If vendor version is 2.2 or lower, do not 7161b21a701SYangbo Lu * wait clock stable bit which does not exist. 7171b21a701SYangbo Lu */ 7181b21a701SYangbo Lu timeout = ktime_add_ms(ktime_get(), 20); 7191b21a701SYangbo Lu while (esdhc->vendor_ver > VENDOR_V_22) { 7201b21a701SYangbo Lu bool timedout = ktime_after(ktime_get(), timeout); 7211b21a701SYangbo Lu 7221b21a701SYangbo Lu if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) 7231b21a701SYangbo Lu break; 7241b21a701SYangbo Lu if (timedout) { 7251b21a701SYangbo Lu pr_err("%s: Internal clock never stabilised.\n", 7261b21a701SYangbo Lu mmc_hostname(host->mmc)); 7271b21a701SYangbo Lu break; 7281b21a701SYangbo Lu } 7291b21a701SYangbo Lu usleep_range(10, 20); 7301b21a701SYangbo Lu } 7311b21a701SYangbo Lu 7321b21a701SYangbo Lu /* Additional setting for HS400. */ 73354e08d9aSYangbo Lu if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && 73454e08d9aSYangbo Lu clock == MMC_HS200_MAX_DTR) { 73554e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 73654e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_MODE, ESDHC_TBCTL); 73754e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_SDCLKCTL); 73854e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_CMD_CLK_CTL, ESDHC_SDCLKCTL); 73954e08d9aSYangbo Lu esdhc_clock_enable(host, true); 74054e08d9aSYangbo Lu 74154e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_DLLCFG0); 74258d0bf84SYangbo Lu temp |= ESDHC_DLL_ENABLE; 74358d0bf84SYangbo Lu if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) 74458d0bf84SYangbo Lu temp |= ESDHC_DLL_FREQ_SEL; 74554e08d9aSYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 74654e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 74754e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL); 74854e08d9aSYangbo Lu 74954e08d9aSYangbo Lu esdhc_clock_enable(host, false); 7506e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 75154e08d9aSYangbo Lu } 75280c74823SYangbo Lu esdhc_clock_enable(host, true); 753e87d2db2Syangbo lu } 754e87d2db2Syangbo lu 7552317f56cSRussell King static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) 75666b50a00SOded Gabbay { 75766b50a00SOded Gabbay u32 ctrl; 75866b50a00SOded Gabbay 759f4932cfdSyangbo lu ctrl = sdhci_readl(host, ESDHC_PROCTL); 760f4932cfdSyangbo lu ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK); 76166b50a00SOded Gabbay switch (width) { 76266b50a00SOded Gabbay case MMC_BUS_WIDTH_8: 763f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_8BITBUS; 76466b50a00SOded Gabbay break; 76566b50a00SOded Gabbay 76666b50a00SOded Gabbay case MMC_BUS_WIDTH_4: 767f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_4BITBUS; 76866b50a00SOded Gabbay break; 76966b50a00SOded Gabbay 77066b50a00SOded Gabbay default: 77166b50a00SOded Gabbay break; 77266b50a00SOded Gabbay } 77366b50a00SOded Gabbay 774f4932cfdSyangbo lu sdhci_writel(host, ctrl, ESDHC_PROCTL); 77566b50a00SOded Gabbay } 77666b50a00SOded Gabbay 777304f0a98SAlessio Igor Bogani static void esdhc_reset(struct sdhci_host *host, u8 mask) 778304f0a98SAlessio Igor Bogani { 77948e304ccSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 78048e304ccSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 7812aa3d826SYangbo Lu u32 val, bus_width = 0; 782f2bc6000Syinbo.zhu 7832aa3d826SYangbo Lu /* 7842aa3d826SYangbo Lu * Add delay to make sure all the DMA transfers are finished 7852aa3d826SYangbo Lu * for quirk. 7862aa3d826SYangbo Lu */ 787f667216cSYangbo Lu if (esdhc->quirk_delay_before_data_reset && 788f667216cSYangbo Lu (mask & SDHCI_RESET_DATA) && 789f667216cSYangbo Lu (host->flags & SDHCI_REQ_USE_DMA)) 790f667216cSYangbo Lu mdelay(5); 791f667216cSYangbo Lu 7922aa3d826SYangbo Lu /* 7932aa3d826SYangbo Lu * Save bus-width for eSDHC whose vendor version is 2.2 7942aa3d826SYangbo Lu * or lower for data reset. 7952aa3d826SYangbo Lu */ 7962aa3d826SYangbo Lu if ((mask & SDHCI_RESET_DATA) && 7972aa3d826SYangbo Lu (esdhc->vendor_ver <= VENDOR_V_22)) { 7982aa3d826SYangbo Lu val = sdhci_readl(host, ESDHC_PROCTL); 7992aa3d826SYangbo Lu bus_width = val & ESDHC_CTRL_BUSWIDTH_MASK; 8002aa3d826SYangbo Lu } 8012aa3d826SYangbo Lu 802304f0a98SAlessio Igor Bogani sdhci_reset(host, mask); 803304f0a98SAlessio Igor Bogani 8042aa3d826SYangbo Lu /* 8052aa3d826SYangbo Lu * Restore bus-width setting and interrupt registers for eSDHC 8062aa3d826SYangbo Lu * whose vendor version is 2.2 or lower for data reset. 8072aa3d826SYangbo Lu */ 8082aa3d826SYangbo Lu if ((mask & SDHCI_RESET_DATA) && 8092aa3d826SYangbo Lu (esdhc->vendor_ver <= VENDOR_V_22)) { 8102aa3d826SYangbo Lu val = sdhci_readl(host, ESDHC_PROCTL); 8112aa3d826SYangbo Lu val &= ~ESDHC_CTRL_BUSWIDTH_MASK; 8122aa3d826SYangbo Lu val |= bus_width; 8132aa3d826SYangbo Lu sdhci_writel(host, val, ESDHC_PROCTL); 8142aa3d826SYangbo Lu 815304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 816304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 8172aa3d826SYangbo Lu } 818f2bc6000Syinbo.zhu 8192aa3d826SYangbo Lu /* 8202aa3d826SYangbo Lu * Some bits have to be cleaned manually for eSDHC whose spec 8212aa3d826SYangbo Lu * version is higher than 3.0 for all reset. 8222aa3d826SYangbo Lu */ 8232aa3d826SYangbo Lu if ((mask & SDHCI_RESET_ALL) && 8242aa3d826SYangbo Lu (esdhc->spec_ver >= SDHCI_SPEC_300)) { 825f2bc6000Syinbo.zhu val = sdhci_readl(host, ESDHC_TBCTL); 826f2bc6000Syinbo.zhu val &= ~ESDHC_TB_EN; 827f2bc6000Syinbo.zhu sdhci_writel(host, val, ESDHC_TBCTL); 82848e304ccSYangbo Lu 8292aa3d826SYangbo Lu /* 8302aa3d826SYangbo Lu * Initialize eSDHC_DLLCFG1[DLL_PD_PULSE_STRETCH_SEL] to 8312aa3d826SYangbo Lu * 0 for quirk. 8322aa3d826SYangbo Lu */ 83348e304ccSYangbo Lu if (esdhc->quirk_unreliable_pulse_detection) { 83448e304ccSYangbo Lu val = sdhci_readl(host, ESDHC_DLLCFG1); 83548e304ccSYangbo Lu val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL; 83648e304ccSYangbo Lu sdhci_writel(host, val, ESDHC_DLLCFG1); 83748e304ccSYangbo Lu } 838f2bc6000Syinbo.zhu } 839304f0a98SAlessio Igor Bogani } 840304f0a98SAlessio Igor Bogani 841ea35645aSyangbo lu /* The SCFG, Supplemental Configuration Unit, provides SoC specific 842ea35645aSyangbo lu * configuration and status registers for the device. There is a 843ea35645aSyangbo lu * SDHC IO VSEL control register on SCFG for some platforms. It's 844ea35645aSyangbo lu * used to support SDHC IO voltage switching. 845ea35645aSyangbo lu */ 846ea35645aSyangbo lu static const struct of_device_id scfg_device_ids[] = { 847ea35645aSyangbo lu { .compatible = "fsl,t1040-scfg", }, 848ea35645aSyangbo lu { .compatible = "fsl,ls1012a-scfg", }, 849ea35645aSyangbo lu { .compatible = "fsl,ls1046a-scfg", }, 850ea35645aSyangbo lu {} 851ea35645aSyangbo lu }; 852ea35645aSyangbo lu 853ea35645aSyangbo lu /* SDHC IO VSEL control register definition */ 854ea35645aSyangbo lu #define SCFG_SDHCIOVSELCR 0x408 855ea35645aSyangbo lu #define SDHCIOVSELCR_TGLEN 0x80000000 856ea35645aSyangbo lu #define SDHCIOVSELCR_VSELVAL 0x60000000 857ea35645aSyangbo lu #define SDHCIOVSELCR_SDHC_VS 0x00000001 858ea35645aSyangbo lu 859ea35645aSyangbo lu static int esdhc_signal_voltage_switch(struct mmc_host *mmc, 860ea35645aSyangbo lu struct mmc_ios *ios) 861ea35645aSyangbo lu { 862ea35645aSyangbo lu struct sdhci_host *host = mmc_priv(mmc); 863ea35645aSyangbo lu struct device_node *scfg_node; 864ea35645aSyangbo lu void __iomem *scfg_base = NULL; 865ea35645aSyangbo lu u32 sdhciovselcr; 866ea35645aSyangbo lu u32 val; 867ea35645aSyangbo lu 868ea35645aSyangbo lu /* 869ea35645aSyangbo lu * Signal Voltage Switching is only applicable for Host Controllers 870ea35645aSyangbo lu * v3.00 and above. 871ea35645aSyangbo lu */ 872ea35645aSyangbo lu if (host->version < SDHCI_SPEC_300) 873ea35645aSyangbo lu return 0; 874ea35645aSyangbo lu 875ea35645aSyangbo lu val = sdhci_readl(host, ESDHC_PROCTL); 876ea35645aSyangbo lu 877ea35645aSyangbo lu switch (ios->signal_voltage) { 878ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_330: 879ea35645aSyangbo lu val &= ~ESDHC_VOLT_SEL; 880ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 881ea35645aSyangbo lu return 0; 882ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_180: 883ea35645aSyangbo lu scfg_node = of_find_matching_node(NULL, scfg_device_ids); 884ea35645aSyangbo lu if (scfg_node) 885ea35645aSyangbo lu scfg_base = of_iomap(scfg_node, 0); 886ea35645aSyangbo lu if (scfg_base) { 887ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 888ea35645aSyangbo lu SDHCIOVSELCR_VSELVAL; 889ea35645aSyangbo lu iowrite32be(sdhciovselcr, 890ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 891ea35645aSyangbo lu 892ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 893ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 894ea35645aSyangbo lu mdelay(5); 895ea35645aSyangbo lu 896ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 897ea35645aSyangbo lu SDHCIOVSELCR_SDHC_VS; 898ea35645aSyangbo lu iowrite32be(sdhciovselcr, 899ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 900ea35645aSyangbo lu iounmap(scfg_base); 901ea35645aSyangbo lu } else { 902ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 903ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 904ea35645aSyangbo lu } 905ea35645aSyangbo lu return 0; 906ea35645aSyangbo lu default: 907ea35645aSyangbo lu return 0; 908ea35645aSyangbo lu } 909ea35645aSyangbo lu } 910ea35645aSyangbo lu 91122dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type1[] = { 9125b742232SYangbo Lu { .family = "QorIQ T1023", }, 9135b742232SYangbo Lu { .family = "QorIQ T1040", }, 9145b742232SYangbo Lu { .family = "QorIQ T2080", }, 9155b742232SYangbo Lu { .family = "QorIQ LS1021A", }, 91622dc132dSYangbo Lu { }, 91722dc132dSYangbo Lu }; 91822dc132dSYangbo Lu 91922dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type2[] = { 9205b742232SYangbo Lu { .family = "QorIQ LS1012A", }, 9215b742232SYangbo Lu { .family = "QorIQ LS1043A", }, 9225b742232SYangbo Lu { .family = "QorIQ LS1046A", }, 9235b742232SYangbo Lu { .family = "QorIQ LS1080A", }, 9245b742232SYangbo Lu { .family = "QorIQ LS2080A", }, 9255b742232SYangbo Lu { .family = "QorIQ LA1575A", }, 926b1f378abSYinbo Zhu { }, 927b1f378abSYinbo Zhu }; 928b1f378abSYinbo Zhu 92954e08d9aSYangbo Lu static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable) 930ba49cbd0Syangbo lu { 931ba49cbd0Syangbo lu u32 val; 932ba49cbd0Syangbo lu 933ba49cbd0Syangbo lu esdhc_clock_enable(host, false); 9346e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 935ba49cbd0Syangbo lu 936ba49cbd0Syangbo lu val = sdhci_readl(host, ESDHC_TBCTL); 93754e08d9aSYangbo Lu if (enable) 938ba49cbd0Syangbo lu val |= ESDHC_TB_EN; 93954e08d9aSYangbo Lu else 94054e08d9aSYangbo Lu val &= ~ESDHC_TB_EN; 941ba49cbd0Syangbo lu sdhci_writel(host, val, ESDHC_TBCTL); 942ba49cbd0Syangbo lu 94354e08d9aSYangbo Lu esdhc_clock_enable(host, true); 94454e08d9aSYangbo Lu } 94554e08d9aSYangbo Lu 946f3c20825SYangbo Lu static void esdhc_tuning_window_ptr(struct sdhci_host *host, u8 *window_start, 94722dc132dSYangbo Lu u8 *window_end) 94822dc132dSYangbo Lu { 94922dc132dSYangbo Lu u32 val; 95022dc132dSYangbo Lu 95122dc132dSYangbo Lu /* Write TBCTL[11:8]=4'h8 */ 95222dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 95322dc132dSYangbo Lu val &= ~(0xf << 8); 95422dc132dSYangbo Lu val |= 8 << 8; 95522dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 95622dc132dSYangbo Lu 95722dc132dSYangbo Lu mdelay(1); 95822dc132dSYangbo Lu 95922dc132dSYangbo Lu /* Read TBCTL[31:0] register and rewrite again */ 96022dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 96122dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 96222dc132dSYangbo Lu 96322dc132dSYangbo Lu mdelay(1); 96422dc132dSYangbo Lu 96522dc132dSYangbo Lu /* Read the TBSTAT[31:0] register twice */ 96622dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 96722dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 96822dc132dSYangbo Lu 969f3c20825SYangbo Lu *window_end = val & 0xff; 970f3c20825SYangbo Lu *window_start = (val >> 8) & 0xff; 971f3c20825SYangbo Lu } 972f3c20825SYangbo Lu 973f3c20825SYangbo Lu static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start, 974f3c20825SYangbo Lu u8 *window_end) 975f3c20825SYangbo Lu { 976f3c20825SYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 977f3c20825SYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 978f3c20825SYangbo Lu u8 start_ptr, end_ptr; 979f3c20825SYangbo Lu 980f3c20825SYangbo Lu if (esdhc->quirk_tuning_erratum_type1) { 981f3c20825SYangbo Lu *window_start = 5 * esdhc->div_ratio; 982f3c20825SYangbo Lu *window_end = 3 * esdhc->div_ratio; 983f3c20825SYangbo Lu return; 984f3c20825SYangbo Lu } 985f3c20825SYangbo Lu 986f3c20825SYangbo Lu esdhc_tuning_window_ptr(host, &start_ptr, &end_ptr); 987f3c20825SYangbo Lu 98822dc132dSYangbo Lu /* Reset data lines by setting ESDHCCTL[RSTD] */ 98922dc132dSYangbo Lu sdhci_reset(host, SDHCI_RESET_DATA); 99022dc132dSYangbo Lu /* Write 32'hFFFF_FFFF to IRQSTAT register */ 99122dc132dSYangbo Lu sdhci_writel(host, 0xFFFFFFFF, SDHCI_INT_STATUS); 99222dc132dSYangbo Lu 9935b742232SYangbo Lu /* If TBSTAT[15:8]-TBSTAT[7:0] > (4 * div_ratio) + 2 9945b742232SYangbo Lu * or TBSTAT[7:0]-TBSTAT[15:8] > (4 * div_ratio) + 2, 99522dc132dSYangbo Lu * then program TBPTR[TB_WNDW_END_PTR] = 4 * div_ratio 99622dc132dSYangbo Lu * and program TBPTR[TB_WNDW_START_PTR] = 8 * div_ratio. 99722dc132dSYangbo Lu */ 99822dc132dSYangbo Lu 9995b742232SYangbo Lu if (abs(start_ptr - end_ptr) > (4 * esdhc->div_ratio + 2)) { 100022dc132dSYangbo Lu *window_start = 8 * esdhc->div_ratio; 100122dc132dSYangbo Lu *window_end = 4 * esdhc->div_ratio; 100222dc132dSYangbo Lu } else { 100322dc132dSYangbo Lu *window_start = 5 * esdhc->div_ratio; 100422dc132dSYangbo Lu *window_end = 3 * esdhc->div_ratio; 100522dc132dSYangbo Lu } 100622dc132dSYangbo Lu } 100722dc132dSYangbo Lu 100822dc132dSYangbo Lu static int esdhc_execute_sw_tuning(struct mmc_host *mmc, u32 opcode, 100922dc132dSYangbo Lu u8 window_start, u8 window_end) 101022dc132dSYangbo Lu { 101122dc132dSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 101222dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 101322dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 101422dc132dSYangbo Lu u32 val; 101522dc132dSYangbo Lu int ret; 101622dc132dSYangbo Lu 101722dc132dSYangbo Lu /* Program TBPTR[TB_WNDW_END_PTR] and TBPTR[TB_WNDW_START_PTR] */ 101822dc132dSYangbo Lu val = ((u32)window_start << ESDHC_WNDW_STRT_PTR_SHIFT) & 101922dc132dSYangbo Lu ESDHC_WNDW_STRT_PTR_MASK; 102022dc132dSYangbo Lu val |= window_end & ESDHC_WNDW_END_PTR_MASK; 102122dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBPTR); 102222dc132dSYangbo Lu 102322dc132dSYangbo Lu /* Program the software tuning mode by setting TBCTL[TB_MODE]=2'h3 */ 102422dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 102522dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 102622dc132dSYangbo Lu val |= ESDHC_TB_MODE_SW; 102722dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 102822dc132dSYangbo Lu 102922dc132dSYangbo Lu esdhc->in_sw_tuning = true; 103022dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 103122dc132dSYangbo Lu esdhc->in_sw_tuning = false; 103222dc132dSYangbo Lu return ret; 103322dc132dSYangbo Lu } 103422dc132dSYangbo Lu 103554e08d9aSYangbo Lu static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) 103654e08d9aSYangbo Lu { 103754e08d9aSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 103854e08d9aSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 103954e08d9aSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 104022dc132dSYangbo Lu u8 window_start, window_end; 104122dc132dSYangbo Lu int ret, retries = 1; 104254e08d9aSYangbo Lu bool hs400_tuning; 104304509d77SYangbo Lu unsigned int clk; 104454e08d9aSYangbo Lu u32 val; 104554e08d9aSYangbo Lu 104604509d77SYangbo Lu /* For tuning mode, the sd clock divisor value 104704509d77SYangbo Lu * must be larger than 3 according to reference manual. 104804509d77SYangbo Lu */ 104904509d77SYangbo Lu clk = esdhc->peripheral_clock / 3; 105004509d77SYangbo Lu if (host->clock > clk) 105104509d77SYangbo Lu esdhc_of_set_clock(host, clk); 105204509d77SYangbo Lu 105354e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 105454e08d9aSYangbo Lu 105554e08d9aSYangbo Lu hs400_tuning = host->flags & SDHCI_HS400_TUNING; 105654e08d9aSYangbo Lu 105722dc132dSYangbo Lu do { 105822dc132dSYangbo Lu if (esdhc->quirk_limited_clk_division && 105922dc132dSYangbo Lu hs400_tuning) 106022dc132dSYangbo Lu esdhc_of_set_clock(host, host->clock); 106122dc132dSYangbo Lu 106222dc132dSYangbo Lu /* Do HW tuning */ 106322dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 106422dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 106522dc132dSYangbo Lu val |= ESDHC_TB_MODE_3; 106622dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 106722dc132dSYangbo Lu 106822dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 106922dc132dSYangbo Lu if (ret) 107022dc132dSYangbo Lu break; 107122dc132dSYangbo Lu 10725b742232SYangbo Lu /* For type2 affected platforms of the tuning erratum, 10735b742232SYangbo Lu * tuning may succeed although eSDHC might not have 10745b742232SYangbo Lu * tuned properly. Need to check tuning window. 10755b742232SYangbo Lu */ 10765b742232SYangbo Lu if (esdhc->quirk_tuning_erratum_type2 && 10775b742232SYangbo Lu !host->tuning_err) { 10785b742232SYangbo Lu esdhc_tuning_window_ptr(host, &window_start, 10795b742232SYangbo Lu &window_end); 10805b742232SYangbo Lu if (abs(window_start - window_end) > 10815b742232SYangbo Lu (4 * esdhc->div_ratio + 2)) 10825b742232SYangbo Lu host->tuning_err = -EAGAIN; 10835b742232SYangbo Lu } 10845b742232SYangbo Lu 108522dc132dSYangbo Lu /* If HW tuning fails and triggers erratum, 108622dc132dSYangbo Lu * try workaround. 108722dc132dSYangbo Lu */ 108822dc132dSYangbo Lu ret = host->tuning_err; 108922dc132dSYangbo Lu if (ret == -EAGAIN && 109022dc132dSYangbo Lu (esdhc->quirk_tuning_erratum_type1 || 109122dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2)) { 109222dc132dSYangbo Lu /* Recover HS400 tuning flag */ 109322dc132dSYangbo Lu if (hs400_tuning) 109422dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 109522dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try SW tuning!\n", 109622dc132dSYangbo Lu mmc_hostname(mmc)); 109722dc132dSYangbo Lu /* Do SW tuning */ 109822dc132dSYangbo Lu esdhc_prepare_sw_tuning(host, &window_start, 109922dc132dSYangbo Lu &window_end); 110022dc132dSYangbo Lu ret = esdhc_execute_sw_tuning(mmc, opcode, 110122dc132dSYangbo Lu window_start, 110222dc132dSYangbo Lu window_end); 110322dc132dSYangbo Lu if (ret) 110422dc132dSYangbo Lu break; 110522dc132dSYangbo Lu 110622dc132dSYangbo Lu /* Retry both HW/SW tuning with reduced clock. */ 110722dc132dSYangbo Lu ret = host->tuning_err; 110822dc132dSYangbo Lu if (ret == -EAGAIN && retries) { 110922dc132dSYangbo Lu /* Recover HS400 tuning flag */ 111022dc132dSYangbo Lu if (hs400_tuning) 111122dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 111222dc132dSYangbo Lu 111322dc132dSYangbo Lu clk = host->max_clk / (esdhc->div_ratio + 1); 111422dc132dSYangbo Lu esdhc_of_set_clock(host, clk); 111522dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try tuning with reduced clock!\n", 111622dc132dSYangbo Lu mmc_hostname(mmc)); 111722dc132dSYangbo Lu } else { 111822dc132dSYangbo Lu break; 111922dc132dSYangbo Lu } 112022dc132dSYangbo Lu } else { 112122dc132dSYangbo Lu break; 112222dc132dSYangbo Lu } 112322dc132dSYangbo Lu } while (retries--); 112422dc132dSYangbo Lu 112522dc132dSYangbo Lu if (ret) { 112622dc132dSYangbo Lu esdhc_tuning_block_enable(host, false); 112722dc132dSYangbo Lu } else if (hs400_tuning) { 112854e08d9aSYangbo Lu val = sdhci_readl(host, ESDHC_SDTIMNGCTL); 112954e08d9aSYangbo Lu val |= ESDHC_FLW_CTL_BG; 113054e08d9aSYangbo Lu sdhci_writel(host, val, ESDHC_SDTIMNGCTL); 113154e08d9aSYangbo Lu } 113254e08d9aSYangbo Lu 113354e08d9aSYangbo Lu return ret; 113454e08d9aSYangbo Lu } 113554e08d9aSYangbo Lu 113654e08d9aSYangbo Lu static void esdhc_set_uhs_signaling(struct sdhci_host *host, 113754e08d9aSYangbo Lu unsigned int timing) 113854e08d9aSYangbo Lu { 113947e9e107SYangbo Lu u32 val; 114047e9e107SYangbo Lu 114147e9e107SYangbo Lu /* 114247e9e107SYangbo Lu * There are specific registers setting for HS400 mode. 114347e9e107SYangbo Lu * Clean all of them if controller is in HS400 mode to 114447e9e107SYangbo Lu * exit HS400 mode before re-setting any speed mode. 114547e9e107SYangbo Lu */ 114647e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 114747e9e107SYangbo Lu if (val & ESDHC_HS400_MODE) { 114847e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_SDTIMNGCTL); 114947e9e107SYangbo Lu val &= ~ESDHC_FLW_CTL_BG; 115047e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_SDTIMNGCTL); 115147e9e107SYangbo Lu 115247e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_SDCLKCTL); 115347e9e107SYangbo Lu val &= ~ESDHC_CMD_CLK_CTL; 115447e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_SDCLKCTL); 115547e9e107SYangbo Lu 115647e9e107SYangbo Lu esdhc_clock_enable(host, false); 115747e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 115847e9e107SYangbo Lu val &= ~ESDHC_HS400_MODE; 115947e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 116047e9e107SYangbo Lu esdhc_clock_enable(host, true); 116147e9e107SYangbo Lu 116247e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_DLLCFG0); 116347e9e107SYangbo Lu val &= ~(ESDHC_DLL_ENABLE | ESDHC_DLL_FREQ_SEL); 116447e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_DLLCFG0); 116547e9e107SYangbo Lu 116647e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 116747e9e107SYangbo Lu val &= ~ESDHC_HS400_WNDW_ADJUST; 116847e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 116947e9e107SYangbo Lu 117047e9e107SYangbo Lu esdhc_tuning_block_enable(host, false); 117147e9e107SYangbo Lu } 117247e9e107SYangbo Lu 117354e08d9aSYangbo Lu if (timing == MMC_TIMING_MMC_HS400) 117454e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 117554e08d9aSYangbo Lu else 117654e08d9aSYangbo Lu sdhci_set_uhs_signaling(host, timing); 1177ba49cbd0Syangbo lu } 1178ba49cbd0Syangbo lu 1179b214fe59SYinbo Zhu static u32 esdhc_irq(struct sdhci_host *host, u32 intmask) 1180b214fe59SYinbo Zhu { 1181*060522d8SChris Packham struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1182*060522d8SChris Packham struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1183b214fe59SYinbo Zhu u32 command; 1184b214fe59SYinbo Zhu 1185*060522d8SChris Packham if (esdhc->quirk_trans_complete_erratum) { 1186b214fe59SYinbo Zhu command = SDHCI_GET_CMD(sdhci_readw(host, 1187b214fe59SYinbo Zhu SDHCI_COMMAND)); 1188b214fe59SYinbo Zhu if (command == MMC_WRITE_MULTIPLE_BLOCK && 1189b214fe59SYinbo Zhu sdhci_readw(host, SDHCI_BLOCK_COUNT) && 1190b214fe59SYinbo Zhu intmask & SDHCI_INT_DATA_END) { 1191b214fe59SYinbo Zhu intmask &= ~SDHCI_INT_DATA_END; 1192b214fe59SYinbo Zhu sdhci_writel(host, SDHCI_INT_DATA_END, 1193b214fe59SYinbo Zhu SDHCI_INT_STATUS); 1194b214fe59SYinbo Zhu } 1195b214fe59SYinbo Zhu } 1196b214fe59SYinbo Zhu return intmask; 1197b214fe59SYinbo Zhu } 1198b214fe59SYinbo Zhu 11999e48b336SUlf Hansson #ifdef CONFIG_PM_SLEEP 1200723f7924SRussell King static u32 esdhc_proctl; 1201723f7924SRussell King static int esdhc_of_suspend(struct device *dev) 1202723f7924SRussell King { 1203723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1204723f7924SRussell King 1205f4932cfdSyangbo lu esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL); 1206723f7924SRussell King 1207d38dcad4SAdrian Hunter if (host->tuning_mode != SDHCI_TUNING_MODE_3) 1208d38dcad4SAdrian Hunter mmc_retune_needed(host->mmc); 1209d38dcad4SAdrian Hunter 1210723f7924SRussell King return sdhci_suspend_host(host); 1211723f7924SRussell King } 1212723f7924SRussell King 121306732b84SUlf Hansson static int esdhc_of_resume(struct device *dev) 1214723f7924SRussell King { 1215723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1216723f7924SRussell King int ret = sdhci_resume_host(host); 1217723f7924SRussell King 1218723f7924SRussell King if (ret == 0) { 1219723f7924SRussell King /* Isn't this already done by sdhci_resume_host() ? --rmk */ 1220723f7924SRussell King esdhc_of_enable_dma(host); 1221f4932cfdSyangbo lu sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); 1222723f7924SRussell King } 1223723f7924SRussell King return ret; 1224723f7924SRussell King } 1225723f7924SRussell King #endif 1226723f7924SRussell King 12279e48b336SUlf Hansson static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, 12289e48b336SUlf Hansson esdhc_of_suspend, 12299e48b336SUlf Hansson esdhc_of_resume); 12309e48b336SUlf Hansson 1231f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_be_ops = { 1232f4932cfdSyangbo lu .read_l = esdhc_be_readl, 1233f4932cfdSyangbo lu .read_w = esdhc_be_readw, 1234f4932cfdSyangbo lu .read_b = esdhc_be_readb, 1235f4932cfdSyangbo lu .write_l = esdhc_be_writel, 1236f4932cfdSyangbo lu .write_w = esdhc_be_writew, 1237f4932cfdSyangbo lu .write_b = esdhc_be_writeb, 1238f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1239f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1240f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1241f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1242f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1243f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1244f4932cfdSyangbo lu .reset = esdhc_reset, 124554e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1246b214fe59SYinbo Zhu .irq = esdhc_irq, 1247f4932cfdSyangbo lu }; 1248f4932cfdSyangbo lu 1249f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_le_ops = { 1250f4932cfdSyangbo lu .read_l = esdhc_le_readl, 1251f4932cfdSyangbo lu .read_w = esdhc_le_readw, 1252f4932cfdSyangbo lu .read_b = esdhc_le_readb, 1253f4932cfdSyangbo lu .write_l = esdhc_le_writel, 1254f4932cfdSyangbo lu .write_w = esdhc_le_writew, 1255f4932cfdSyangbo lu .write_b = esdhc_le_writeb, 1256f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1257f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1258f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1259f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1260f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1261f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1262f4932cfdSyangbo lu .reset = esdhc_reset, 126354e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1264b214fe59SYinbo Zhu .irq = esdhc_irq, 1265f4932cfdSyangbo lu }; 1266f4932cfdSyangbo lu 1267f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { 1268e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1269e9acc77dSyangbo lu #ifdef CONFIG_PPC 1270e9acc77dSyangbo lu SDHCI_QUIRK_BROKEN_CARD_DETECTION | 1271e9acc77dSyangbo lu #endif 1272e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1273e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1274f4932cfdSyangbo lu .ops = &sdhci_esdhc_be_ops, 12757657c3a7SAlbert Herranz }; 127638576af1SShawn Guo 1277f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = { 1278e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1279e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1280e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1281f4932cfdSyangbo lu .ops = &sdhci_esdhc_le_ops, 1282f4932cfdSyangbo lu }; 1283f4932cfdSyangbo lu 1284151ede40Syangbo lu static struct soc_device_attribute soc_incorrect_hostver[] = { 1285151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "1.0", }, 1286151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "2.0", }, 1287151ede40Syangbo lu { }, 1288151ede40Syangbo lu }; 1289151ede40Syangbo lu 12906079e63cSYangbo Lu static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = { 12916079e63cSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 12928e9a6919SYinbo Zhu { .family = "QorIQ LX2160A", .revision = "2.0", }, 12935f3ad196SYinbo Zhu { .family = "QorIQ LS1028A", .revision = "1.0", }, 12946079e63cSYangbo Lu { }, 12956079e63cSYangbo Lu }; 12966079e63cSYangbo Lu 129748e304ccSYangbo Lu static struct soc_device_attribute soc_unreliable_pulse_detection[] = { 129848e304ccSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 129948e304ccSYangbo Lu { }, 130048e304ccSYangbo Lu }; 130148e304ccSYangbo Lu 1302f4932cfdSyangbo lu static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) 1303f4932cfdSyangbo lu { 130467fdfbdfSyinbo.zhu const struct of_device_id *match; 1305f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host; 1306f4932cfdSyangbo lu struct sdhci_esdhc *esdhc; 130719c3a0efSyangbo lu struct device_node *np; 130819c3a0efSyangbo lu struct clk *clk; 130919c3a0efSyangbo lu u32 val; 1310f4932cfdSyangbo lu u16 host_ver; 1311f4932cfdSyangbo lu 1312f4932cfdSyangbo lu pltfm_host = sdhci_priv(host); 13138605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 1314f4932cfdSyangbo lu 1315f4932cfdSyangbo lu host_ver = sdhci_readw(host, SDHCI_HOST_VERSION); 1316f4932cfdSyangbo lu esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> 1317f4932cfdSyangbo lu SDHCI_VENDOR_VER_SHIFT; 1318f4932cfdSyangbo lu esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; 1319151ede40Syangbo lu if (soc_device_match(soc_incorrect_hostver)) 1320151ede40Syangbo lu esdhc->quirk_incorrect_hostver = true; 1321151ede40Syangbo lu else 1322151ede40Syangbo lu esdhc->quirk_incorrect_hostver = false; 132319c3a0efSyangbo lu 13246079e63cSYangbo Lu if (soc_device_match(soc_fixup_sdhc_clkdivs)) 13256079e63cSYangbo Lu esdhc->quirk_limited_clk_division = true; 13266079e63cSYangbo Lu else 13276079e63cSYangbo Lu esdhc->quirk_limited_clk_division = false; 13286079e63cSYangbo Lu 132948e304ccSYangbo Lu if (soc_device_match(soc_unreliable_pulse_detection)) 133048e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = true; 133148e304ccSYangbo Lu else 133248e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = false; 133348e304ccSYangbo Lu 133467fdfbdfSyinbo.zhu match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); 133567fdfbdfSyinbo.zhu if (match) 133667fdfbdfSyinbo.zhu esdhc->clk_fixup = match->data; 133719c3a0efSyangbo lu np = pdev->dev.of_node; 1338f667216cSYangbo Lu 1339*060522d8SChris Packham if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 1340f667216cSYangbo Lu esdhc->quirk_delay_before_data_reset = true; 1341*060522d8SChris Packham esdhc->quirk_trans_complete_erratum = true; 1342*060522d8SChris Packham } 1343f667216cSYangbo Lu 134419c3a0efSyangbo lu clk = of_clk_get(np, 0); 134519c3a0efSyangbo lu if (!IS_ERR(clk)) { 134619c3a0efSyangbo lu /* 134719c3a0efSyangbo lu * esdhc->peripheral_clock would be assigned with a value 134819c3a0efSyangbo lu * which is eSDHC base clock when use periperal clock. 1349791463baSYangbo Lu * For some platforms, the clock value got by common clk 1350791463baSYangbo Lu * API is peripheral clock while the eSDHC base clock is 1351791463baSYangbo Lu * 1/2 peripheral clock. 135219c3a0efSyangbo lu */ 1353791463baSYangbo Lu if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || 135466a83febSYangbo Lu of_device_is_compatible(np, "fsl,ls1028a-esdhc") || 135566a83febSYangbo Lu of_device_is_compatible(np, "fsl,ls1088a-esdhc")) 135619c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk) / 2; 135719c3a0efSyangbo lu else 135819c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk); 135919c3a0efSyangbo lu 136019c3a0efSyangbo lu clk_put(clk); 136119c3a0efSyangbo lu } 136219c3a0efSyangbo lu 136319c3a0efSyangbo lu if (esdhc->peripheral_clock) { 136419c3a0efSyangbo lu esdhc_clock_enable(host, false); 136519c3a0efSyangbo lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 136619c3a0efSyangbo lu val |= ESDHC_PERIPHERAL_CLK_SEL; 136719c3a0efSyangbo lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 136819c3a0efSyangbo lu esdhc_clock_enable(host, true); 136919c3a0efSyangbo lu } 1370f4932cfdSyangbo lu } 1371f4932cfdSyangbo lu 137254e08d9aSYangbo Lu static int esdhc_hs400_prepare_ddr(struct mmc_host *mmc) 137354e08d9aSYangbo Lu { 137454e08d9aSYangbo Lu esdhc_tuning_block_enable(mmc_priv(mmc), false); 137554e08d9aSYangbo Lu return 0; 137654e08d9aSYangbo Lu } 137754e08d9aSYangbo Lu 1378c3be1efdSBill Pemberton static int sdhci_esdhc_probe(struct platform_device *pdev) 137938576af1SShawn Guo { 138066b50a00SOded Gabbay struct sdhci_host *host; 1381dcaff04dSOded Gabbay struct device_node *np; 13821ef5e49eSyangbo lu struct sdhci_pltfm_host *pltfm_host; 13831ef5e49eSyangbo lu struct sdhci_esdhc *esdhc; 138466b50a00SOded Gabbay int ret; 138566b50a00SOded Gabbay 1386f4932cfdSyangbo lu np = pdev->dev.of_node; 1387f4932cfdSyangbo lu 1388150d4240SJulia Lawall if (of_property_read_bool(np, "little-endian")) 13898605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, 13908605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1391f4932cfdSyangbo lu else 13928605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, 13938605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1394f4932cfdSyangbo lu 139566b50a00SOded Gabbay if (IS_ERR(host)) 139666b50a00SOded Gabbay return PTR_ERR(host); 139766b50a00SOded Gabbay 1398ea35645aSyangbo lu host->mmc_host_ops.start_signal_voltage_switch = 1399ea35645aSyangbo lu esdhc_signal_voltage_switch; 1400ba49cbd0Syangbo lu host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; 140154e08d9aSYangbo Lu host->mmc_host_ops.hs400_prepare_ddr = esdhc_hs400_prepare_ddr; 14026b236f37Syangbo lu host->tuning_delay = 1; 1403ea35645aSyangbo lu 1404f4932cfdSyangbo lu esdhc_init(pdev, host); 1405f4932cfdSyangbo lu 140666b50a00SOded Gabbay sdhci_get_of_property(pdev); 140766b50a00SOded Gabbay 14081ef5e49eSyangbo lu pltfm_host = sdhci_priv(host); 14098605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 141022dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type1)) 141122dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = true; 1412b1f378abSYinbo Zhu else 141322dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = false; 141422dc132dSYangbo Lu 141522dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type2)) 141622dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = true; 141722dc132dSYangbo Lu else 141822dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = false; 1419b1f378abSYinbo Zhu 14201ef5e49eSyangbo lu if (esdhc->vendor_ver == VENDOR_V_22) 14211ef5e49eSyangbo lu host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; 14221ef5e49eSyangbo lu 14231ef5e49eSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) 14241ef5e49eSyangbo lu host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; 14251ef5e49eSyangbo lu 142605cb6b2aSYinbo Zhu if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { 1427fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; 1428fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 142905cb6b2aSYinbo Zhu } 1430a46e4271SYinbo Zhu 143174fd5e30SYangbo Lu if (of_device_is_compatible(np, "fsl,p5040-esdhc") || 143274fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p5020-esdhc") || 143374fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p4080-esdhc") || 143474fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p1020-esdhc") || 1435e9acc77dSyangbo lu of_device_is_compatible(np, "fsl,t1040-esdhc")) 143674fd5e30SYangbo Lu host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; 143774fd5e30SYangbo Lu 1438a22950c8Syangbo lu if (of_device_is_compatible(np, "fsl,ls1021a-esdhc")) 1439a22950c8Syangbo lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 1440a22950c8Syangbo lu 14411f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = false; 1442dcaff04dSOded Gabbay if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 1443dcaff04dSOded Gabbay /* 1444dcaff04dSOded Gabbay * Freescale messed up with P2020 as it has a non-standard 1445dcaff04dSOded Gabbay * host control register 1446dcaff04dSOded Gabbay */ 1447dcaff04dSOded Gabbay host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; 14481f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = true; 1449dcaff04dSOded Gabbay } 1450dcaff04dSOded Gabbay 145166b50a00SOded Gabbay /* call to generic mmc_of_parse to support additional capabilities */ 1452f0991408SUlf Hansson ret = mmc_of_parse(host->mmc); 1453f0991408SUlf Hansson if (ret) 1454f0991408SUlf Hansson goto err; 1455f0991408SUlf Hansson 1456490104acSHaijun Zhang mmc_of_parse_voltage(np, &host->ocr_mask); 145766b50a00SOded Gabbay 145866b50a00SOded Gabbay ret = sdhci_add_host(host); 145966b50a00SOded Gabbay if (ret) 1460f0991408SUlf Hansson goto err; 146166b50a00SOded Gabbay 1462f0991408SUlf Hansson return 0; 1463f0991408SUlf Hansson err: 1464f0991408SUlf Hansson sdhci_pltfm_free(pdev); 146566b50a00SOded Gabbay return ret; 146638576af1SShawn Guo } 146738576af1SShawn Guo 146838576af1SShawn Guo static struct platform_driver sdhci_esdhc_driver = { 146938576af1SShawn Guo .driver = { 147038576af1SShawn Guo .name = "sdhci-esdhc", 147138576af1SShawn Guo .of_match_table = sdhci_esdhc_of_match, 14729e48b336SUlf Hansson .pm = &esdhc_of_dev_pm_ops, 147338576af1SShawn Guo }, 147438576af1SShawn Guo .probe = sdhci_esdhc_probe, 1475caebcae9SKevin Hao .remove = sdhci_pltfm_unregister, 147638576af1SShawn Guo }; 147738576af1SShawn Guo 1478d1f81a64SAxel Lin module_platform_driver(sdhci_esdhc_driver); 147938576af1SShawn Guo 148038576af1SShawn Guo MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); 148138576af1SShawn Guo MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " 148238576af1SShawn Guo "Anton Vorontsov <avorontsov@ru.mvista.com>"); 148338576af1SShawn Guo MODULE_LICENSE("GPL v2"); 1484