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. 7*011fde48SYangbo Lu * Copyright 2020 NXP 87657c3a7SAlbert Herranz * 97657c3a7SAlbert Herranz * Authors: Xiaobo Xie <X.Xie@freescale.com> 107657c3a7SAlbert Herranz * Anton Vorontsov <avorontsov@ru.mvista.com> 117657c3a7SAlbert Herranz */ 127657c3a7SAlbert Herranz 1366b50a00SOded Gabbay #include <linux/err.h> 147657c3a7SAlbert Herranz #include <linux/io.h> 15f060bc9cSJerry Huang #include <linux/of.h> 16ea35645aSyangbo lu #include <linux/of_address.h> 177657c3a7SAlbert Herranz #include <linux/delay.h> 1888b47679SPaul Gortmaker #include <linux/module.h> 19151ede40Syangbo lu #include <linux/sys_soc.h> 2019c3a0efSyangbo lu #include <linux/clk.h> 2119c3a0efSyangbo lu #include <linux/ktime.h> 225552d7adSLaurentiu Tudor #include <linux/dma-mapping.h> 23*011fde48SYangbo Lu #include <linux/iopoll.h> 247657c3a7SAlbert Herranz #include <linux/mmc/host.h> 25b214fe59SYinbo Zhu #include <linux/mmc/mmc.h> 2638576af1SShawn Guo #include "sdhci-pltfm.h" 2780872e21SWolfram Sang #include "sdhci-esdhc.h" 287657c3a7SAlbert Herranz 29137ccd46SJerry Huang #define VENDOR_V_22 0x12 30a4071fbbSHaijun Zhang #define VENDOR_V_23 0x13 31f4932cfdSyangbo lu 3267fdfbdfSyinbo.zhu #define MMC_TIMING_NUM (MMC_TIMING_MMC_HS400 + 1) 3367fdfbdfSyinbo.zhu 3467fdfbdfSyinbo.zhu struct esdhc_clk_fixup { 3567fdfbdfSyinbo.zhu const unsigned int sd_dflt_max_clk; 3667fdfbdfSyinbo.zhu const unsigned int max_clk[MMC_TIMING_NUM]; 3767fdfbdfSyinbo.zhu }; 3867fdfbdfSyinbo.zhu 3967fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup ls1021a_esdhc_clk = { 4067fdfbdfSyinbo.zhu .sd_dflt_max_clk = 25000000, 4167fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS] = 46500000, 4267fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_SD_HS] = 46500000, 4367fdfbdfSyinbo.zhu }; 4467fdfbdfSyinbo.zhu 4567fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup ls1046a_esdhc_clk = { 4667fdfbdfSyinbo.zhu .sd_dflt_max_clk = 25000000, 4767fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_UHS_SDR104] = 167000000, 4867fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS200] = 167000000, 4967fdfbdfSyinbo.zhu }; 5067fdfbdfSyinbo.zhu 5167fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup ls1012a_esdhc_clk = { 5267fdfbdfSyinbo.zhu .sd_dflt_max_clk = 25000000, 5367fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_UHS_SDR104] = 125000000, 5467fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS200] = 125000000, 5567fdfbdfSyinbo.zhu }; 5667fdfbdfSyinbo.zhu 5767fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup p1010_esdhc_clk = { 5867fdfbdfSyinbo.zhu .sd_dflt_max_clk = 20000000, 5967fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_LEGACY] = 20000000, 6067fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS] = 42000000, 6167fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_SD_HS] = 40000000, 6267fdfbdfSyinbo.zhu }; 6367fdfbdfSyinbo.zhu 6467fdfbdfSyinbo.zhu static const struct of_device_id sdhci_esdhc_of_match[] = { 6567fdfbdfSyinbo.zhu { .compatible = "fsl,ls1021a-esdhc", .data = &ls1021a_esdhc_clk}, 6667fdfbdfSyinbo.zhu { .compatible = "fsl,ls1046a-esdhc", .data = &ls1046a_esdhc_clk}, 6767fdfbdfSyinbo.zhu { .compatible = "fsl,ls1012a-esdhc", .data = &ls1012a_esdhc_clk}, 6867fdfbdfSyinbo.zhu { .compatible = "fsl,p1010-esdhc", .data = &p1010_esdhc_clk}, 6967fdfbdfSyinbo.zhu { .compatible = "fsl,mpc8379-esdhc" }, 7067fdfbdfSyinbo.zhu { .compatible = "fsl,mpc8536-esdhc" }, 7167fdfbdfSyinbo.zhu { .compatible = "fsl,esdhc" }, 7267fdfbdfSyinbo.zhu { } 7367fdfbdfSyinbo.zhu }; 7467fdfbdfSyinbo.zhu MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match); 7567fdfbdfSyinbo.zhu 76f4932cfdSyangbo lu struct sdhci_esdhc { 77f4932cfdSyangbo lu u8 vendor_ver; 78f4932cfdSyangbo lu u8 spec_ver; 79151ede40Syangbo lu bool quirk_incorrect_hostver; 806079e63cSYangbo Lu bool quirk_limited_clk_division; 8148e304ccSYangbo Lu bool quirk_unreliable_pulse_detection; 8222dc132dSYangbo Lu bool quirk_tuning_erratum_type1; 8322dc132dSYangbo Lu bool quirk_tuning_erratum_type2; 841f1929f3SYangbo Lu bool quirk_ignore_data_inhibit; 85f667216cSYangbo Lu bool quirk_delay_before_data_reset; 86060522d8SChris Packham bool quirk_trans_complete_erratum; 8722dc132dSYangbo Lu bool in_sw_tuning; 8819c3a0efSyangbo lu unsigned int peripheral_clock; 8967fdfbdfSyinbo.zhu const struct esdhc_clk_fixup *clk_fixup; 90b1f378abSYinbo Zhu u32 div_ratio; 91f4932cfdSyangbo lu }; 92f4932cfdSyangbo lu 93f4932cfdSyangbo lu /** 94f4932cfdSyangbo lu * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register 95f4932cfdSyangbo lu * to make it compatible with SD spec. 96f4932cfdSyangbo lu * 97f4932cfdSyangbo lu * @host: pointer to sdhci_host 98f4932cfdSyangbo lu * @spec_reg: SD spec register address 99f4932cfdSyangbo lu * @value: 32bit eSDHC register value on spec_reg address 100f4932cfdSyangbo lu * 101f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 102f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 103f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 104f4932cfdSyangbo lu * and SD spec. 105f4932cfdSyangbo lu * 106f4932cfdSyangbo lu * Return a fixed up register value 107f4932cfdSyangbo lu */ 108f4932cfdSyangbo lu static u32 esdhc_readl_fixup(struct sdhci_host *host, 109f4932cfdSyangbo lu int spec_reg, u32 value) 110137ccd46SJerry Huang { 111f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1128605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 113137ccd46SJerry Huang u32 ret; 114137ccd46SJerry Huang 115137ccd46SJerry Huang /* 116137ccd46SJerry Huang * The bit of ADMA flag in eSDHC is not compatible with standard 117137ccd46SJerry Huang * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is 118137ccd46SJerry Huang * supported by eSDHC. 119137ccd46SJerry Huang * And for many FSL eSDHC controller, the reset value of field 120f4932cfdSyangbo lu * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA, 121137ccd46SJerry Huang * only these vendor version is greater than 2.2/0x12 support ADMA. 122137ccd46SJerry Huang */ 123f4932cfdSyangbo lu if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) { 124f4932cfdSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) { 125f4932cfdSyangbo lu ret = value | SDHCI_CAN_DO_ADMA2; 126f4932cfdSyangbo lu return ret; 127137ccd46SJerry Huang } 128f4932cfdSyangbo lu } 129b0921d5cSMichael Walle /* 130b0921d5cSMichael Walle * The DAT[3:0] line signal levels and the CMD line signal level are 131b0921d5cSMichael Walle * not compatible with standard SDHC register. The line signal levels 132b0921d5cSMichael Walle * DAT[7:0] are at bits 31:24 and the command line signal level is at 133b0921d5cSMichael Walle * bit 23. All other bits are the same as in the standard SDHC 134b0921d5cSMichael Walle * register. 135b0921d5cSMichael Walle */ 136b0921d5cSMichael Walle if (spec_reg == SDHCI_PRESENT_STATE) { 137b0921d5cSMichael Walle ret = value & 0x000fffff; 138b0921d5cSMichael Walle ret |= (value >> 4) & SDHCI_DATA_LVL_MASK; 139b0921d5cSMichael Walle ret |= (value << 1) & SDHCI_CMD_LVL; 140b0921d5cSMichael Walle return ret; 141b0921d5cSMichael Walle } 142b0921d5cSMichael Walle 1432f3110ccSyangbo lu /* 1442f3110ccSyangbo lu * DTS properties of mmc host are used to enable each speed mode 1452f3110ccSyangbo lu * according to soc and board capability. So clean up 1462f3110ccSyangbo lu * SDR50/SDR104/DDR50 support bits here. 1472f3110ccSyangbo lu */ 1482f3110ccSyangbo lu if (spec_reg == SDHCI_CAPABILITIES_1) { 1492f3110ccSyangbo lu ret = value & ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | 1502f3110ccSyangbo lu SDHCI_SUPPORT_DDR50); 1512f3110ccSyangbo lu return ret; 1522f3110ccSyangbo lu } 1532f3110ccSyangbo lu 1541f1929f3SYangbo Lu /* 1551f1929f3SYangbo Lu * Some controllers have unreliable Data Line Active 1561f1929f3SYangbo Lu * bit for commands with busy signal. This affects 1571f1929f3SYangbo Lu * Command Inhibit (data) bit. Just ignore it since 1581f1929f3SYangbo Lu * MMC core driver has already polled card status 1591f1929f3SYangbo Lu * with CMD13 after any command with busy siganl. 1601f1929f3SYangbo Lu */ 1611f1929f3SYangbo Lu if ((spec_reg == SDHCI_PRESENT_STATE) && 1621f1929f3SYangbo Lu (esdhc->quirk_ignore_data_inhibit == true)) { 1631f1929f3SYangbo Lu ret = value & ~SDHCI_DATA_INHIBIT; 1641f1929f3SYangbo Lu return ret; 1651f1929f3SYangbo Lu } 1661f1929f3SYangbo Lu 167f4932cfdSyangbo lu ret = value; 168137ccd46SJerry Huang return ret; 169137ccd46SJerry Huang } 170137ccd46SJerry Huang 171f4932cfdSyangbo lu static u16 esdhc_readw_fixup(struct sdhci_host *host, 172f4932cfdSyangbo lu int spec_reg, u32 value) 1737657c3a7SAlbert Herranz { 174151ede40Syangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 175151ede40Syangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1767657c3a7SAlbert Herranz u16 ret; 177f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 1787657c3a7SAlbert Herranz 179429d939cSYangbo Lu if (spec_reg == SDHCI_TRANSFER_MODE) 180429d939cSYangbo Lu return pltfm_host->xfer_mode_shadow; 181429d939cSYangbo Lu 182f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_VERSION) 183f4932cfdSyangbo lu ret = value & 0xffff; 1847657c3a7SAlbert Herranz else 185f4932cfdSyangbo lu ret = (value >> shift) & 0xffff; 186151ede40Syangbo lu /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect 187151ede40Syangbo lu * vendor version and spec version information. 188151ede40Syangbo lu */ 189151ede40Syangbo lu if ((spec_reg == SDHCI_HOST_VERSION) && 190151ede40Syangbo lu (esdhc->quirk_incorrect_hostver)) 191151ede40Syangbo lu ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200; 192e51cbc9eSXu lei return ret; 193e51cbc9eSXu lei } 194e51cbc9eSXu lei 195f4932cfdSyangbo lu static u8 esdhc_readb_fixup(struct sdhci_host *host, 196f4932cfdSyangbo lu int spec_reg, u32 value) 197e51cbc9eSXu lei { 198f4932cfdSyangbo lu u8 ret; 199f4932cfdSyangbo lu u8 dma_bits; 200f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 201f4932cfdSyangbo lu 202f4932cfdSyangbo lu ret = (value >> shift) & 0xff; 203ba8c4dc9SRoy Zang 204ba8c4dc9SRoy Zang /* 205ba8c4dc9SRoy Zang * "DMA select" locates at offset 0x28 in SD specification, but on 206ba8c4dc9SRoy Zang * P5020 or P3041, it locates at 0x29. 207ba8c4dc9SRoy Zang */ 208f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 209ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 210f4932cfdSyangbo lu dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK; 211ba8c4dc9SRoy Zang /* fixup the result */ 212ba8c4dc9SRoy Zang ret &= ~SDHCI_CTRL_DMA_MASK; 213ba8c4dc9SRoy Zang ret |= dma_bits; 214ba8c4dc9SRoy Zang } 215f4932cfdSyangbo lu return ret; 216f4932cfdSyangbo lu } 217f4932cfdSyangbo lu 218f4932cfdSyangbo lu /** 219f4932cfdSyangbo lu * esdhc_write*_fixup - Fixup the SD spec register value so that it could be 220f4932cfdSyangbo lu * written into eSDHC register. 221f4932cfdSyangbo lu * 222f4932cfdSyangbo lu * @host: pointer to sdhci_host 223f4932cfdSyangbo lu * @spec_reg: SD spec register address 224f4932cfdSyangbo lu * @value: 8/16/32bit SD spec register value that would be written 225f4932cfdSyangbo lu * @old_value: 32bit eSDHC register value on spec_reg address 226f4932cfdSyangbo lu * 227f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 228f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 229f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 230f4932cfdSyangbo lu * and SD spec. 231f4932cfdSyangbo lu * 232f4932cfdSyangbo lu * Return a fixed up register value 233f4932cfdSyangbo lu */ 234f4932cfdSyangbo lu static u32 esdhc_writel_fixup(struct sdhci_host *host, 235f4932cfdSyangbo lu int spec_reg, u32 value, u32 old_value) 236f4932cfdSyangbo lu { 237f4932cfdSyangbo lu u32 ret; 238f4932cfdSyangbo lu 239f4932cfdSyangbo lu /* 240f4932cfdSyangbo lu * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] 241f4932cfdSyangbo lu * when SYSCTL[RSTD] is set for some special operations. 242f4932cfdSyangbo lu * No any impact on other operation. 243f4932cfdSyangbo lu */ 244f4932cfdSyangbo lu if (spec_reg == SDHCI_INT_ENABLE) 245f4932cfdSyangbo lu ret = value | SDHCI_INT_BLK_GAP; 246f4932cfdSyangbo lu else 247f4932cfdSyangbo lu ret = value; 248ba8c4dc9SRoy Zang 2497657c3a7SAlbert Herranz return ret; 2507657c3a7SAlbert Herranz } 2517657c3a7SAlbert Herranz 252f4932cfdSyangbo lu static u32 esdhc_writew_fixup(struct sdhci_host *host, 253f4932cfdSyangbo lu int spec_reg, u16 value, u32 old_value) 254a4071fbbSHaijun Zhang { 255f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 256f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 257f4932cfdSyangbo lu u32 ret; 258f4932cfdSyangbo lu 259f4932cfdSyangbo lu switch (spec_reg) { 260f4932cfdSyangbo lu case SDHCI_TRANSFER_MODE: 261a4071fbbSHaijun Zhang /* 262f4932cfdSyangbo lu * Postpone this write, we must do it together with a 263f4932cfdSyangbo lu * command write that is down below. Return old value. 264a4071fbbSHaijun Zhang */ 265f4932cfdSyangbo lu pltfm_host->xfer_mode_shadow = value; 266f4932cfdSyangbo lu return old_value; 267f4932cfdSyangbo lu case SDHCI_COMMAND: 268f4932cfdSyangbo lu ret = (value << 16) | pltfm_host->xfer_mode_shadow; 269f4932cfdSyangbo lu return ret; 270a4071fbbSHaijun Zhang } 271a4071fbbSHaijun Zhang 272f4932cfdSyangbo lu ret = old_value & (~(0xffff << shift)); 273f4932cfdSyangbo lu ret |= (value << shift); 274f4932cfdSyangbo lu 275f4932cfdSyangbo lu if (spec_reg == SDHCI_BLOCK_SIZE) { 2767657c3a7SAlbert Herranz /* 2777657c3a7SAlbert Herranz * Two last DMA bits are reserved, and first one is used for 2787657c3a7SAlbert Herranz * non-standard blksz of 4096 bytes that we don't support 2797657c3a7SAlbert Herranz * yet. So clear the DMA boundary bits. 2807657c3a7SAlbert Herranz */ 281f4932cfdSyangbo lu ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0)); 2827657c3a7SAlbert Herranz } 283f4932cfdSyangbo lu return ret; 2847657c3a7SAlbert Herranz } 2857657c3a7SAlbert Herranz 286f4932cfdSyangbo lu static u32 esdhc_writeb_fixup(struct sdhci_host *host, 287f4932cfdSyangbo lu int spec_reg, u8 value, u32 old_value) 2887657c3a7SAlbert Herranz { 289f4932cfdSyangbo lu u32 ret; 290f4932cfdSyangbo lu u32 dma_bits; 291f4932cfdSyangbo lu u8 tmp; 292f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 293f4932cfdSyangbo lu 294ba8c4dc9SRoy Zang /* 2959e4703dfSyangbo lu * eSDHC doesn't have a standard power control register, so we do 2969e4703dfSyangbo lu * nothing here to avoid incorrect operation. 2979e4703dfSyangbo lu */ 2989e4703dfSyangbo lu if (spec_reg == SDHCI_POWER_CONTROL) 2999e4703dfSyangbo lu return old_value; 3009e4703dfSyangbo lu /* 301ba8c4dc9SRoy Zang * "DMA select" location is offset 0x28 in SD specification, but on 302ba8c4dc9SRoy Zang * P5020 or P3041, it's located at 0x29. 303ba8c4dc9SRoy Zang */ 304f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 305dcaff04dSOded Gabbay /* 306dcaff04dSOded Gabbay * If host control register is not standard, exit 307dcaff04dSOded Gabbay * this function 308dcaff04dSOded Gabbay */ 309dcaff04dSOded Gabbay if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) 310f4932cfdSyangbo lu return old_value; 311dcaff04dSOded Gabbay 312ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 313f4932cfdSyangbo lu dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5; 314f4932cfdSyangbo lu ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits; 315f4932cfdSyangbo lu tmp = (value & (~SDHCI_CTRL_DMA_MASK)) | 316f4932cfdSyangbo lu (old_value & SDHCI_CTRL_DMA_MASK); 317f4932cfdSyangbo lu ret = (ret & (~0xff)) | tmp; 318f4932cfdSyangbo lu 319f4932cfdSyangbo lu /* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */ 320f4932cfdSyangbo lu ret &= ~ESDHC_HOST_CONTROL_RES; 321f4932cfdSyangbo lu return ret; 322ba8c4dc9SRoy Zang } 323ba8c4dc9SRoy Zang 324f4932cfdSyangbo lu ret = (old_value & (~(0xff << shift))) | (value << shift); 325f4932cfdSyangbo lu return ret; 326f4932cfdSyangbo lu } 327f4932cfdSyangbo lu 328f4932cfdSyangbo lu static u32 esdhc_be_readl(struct sdhci_host *host, int reg) 329f4932cfdSyangbo lu { 330f4932cfdSyangbo lu u32 ret; 331f4932cfdSyangbo lu u32 value; 332f4932cfdSyangbo lu 3332f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3342f3110ccSyangbo lu value = ioread32be(host->ioaddr + ESDHC_CAPABILITIES_1); 3352f3110ccSyangbo lu else 336f4932cfdSyangbo lu value = ioread32be(host->ioaddr + reg); 3372f3110ccSyangbo lu 338f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 339f4932cfdSyangbo lu 340f4932cfdSyangbo lu return ret; 341f4932cfdSyangbo lu } 342f4932cfdSyangbo lu 343f4932cfdSyangbo lu static u32 esdhc_le_readl(struct sdhci_host *host, int reg) 344f4932cfdSyangbo lu { 345f4932cfdSyangbo lu u32 ret; 346f4932cfdSyangbo lu u32 value; 347f4932cfdSyangbo lu 3482f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3492f3110ccSyangbo lu value = ioread32(host->ioaddr + ESDHC_CAPABILITIES_1); 3502f3110ccSyangbo lu else 351f4932cfdSyangbo lu value = ioread32(host->ioaddr + reg); 3522f3110ccSyangbo lu 353f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 354f4932cfdSyangbo lu 355f4932cfdSyangbo lu return ret; 356f4932cfdSyangbo lu } 357f4932cfdSyangbo lu 358f4932cfdSyangbo lu static u16 esdhc_be_readw(struct sdhci_host *host, int reg) 359f4932cfdSyangbo lu { 360f4932cfdSyangbo lu u16 ret; 361f4932cfdSyangbo lu u32 value; 362f4932cfdSyangbo lu int base = reg & ~0x3; 363f4932cfdSyangbo lu 364f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 365f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 366f4932cfdSyangbo lu return ret; 367f4932cfdSyangbo lu } 368f4932cfdSyangbo lu 369f4932cfdSyangbo lu static u16 esdhc_le_readw(struct sdhci_host *host, int reg) 370f4932cfdSyangbo lu { 371f4932cfdSyangbo lu u16 ret; 372f4932cfdSyangbo lu u32 value; 373f4932cfdSyangbo lu int base = reg & ~0x3; 374f4932cfdSyangbo lu 375f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 376f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 377f4932cfdSyangbo lu return ret; 378f4932cfdSyangbo lu } 379f4932cfdSyangbo lu 380f4932cfdSyangbo lu static u8 esdhc_be_readb(struct sdhci_host *host, int reg) 381f4932cfdSyangbo lu { 382f4932cfdSyangbo lu u8 ret; 383f4932cfdSyangbo lu u32 value; 384f4932cfdSyangbo lu int base = reg & ~0x3; 385f4932cfdSyangbo lu 386f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 387f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 388f4932cfdSyangbo lu return ret; 389f4932cfdSyangbo lu } 390f4932cfdSyangbo lu 391f4932cfdSyangbo lu static u8 esdhc_le_readb(struct sdhci_host *host, int reg) 392f4932cfdSyangbo lu { 393f4932cfdSyangbo lu u8 ret; 394f4932cfdSyangbo lu u32 value; 395f4932cfdSyangbo lu int base = reg & ~0x3; 396f4932cfdSyangbo lu 397f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 398f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 399f4932cfdSyangbo lu return ret; 400f4932cfdSyangbo lu } 401f4932cfdSyangbo lu 402f4932cfdSyangbo lu static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg) 403f4932cfdSyangbo lu { 404f4932cfdSyangbo lu u32 value; 405f4932cfdSyangbo lu 406f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 407f4932cfdSyangbo lu iowrite32be(value, host->ioaddr + reg); 408f4932cfdSyangbo lu } 409f4932cfdSyangbo lu 410f4932cfdSyangbo lu static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg) 411f4932cfdSyangbo lu { 412f4932cfdSyangbo lu u32 value; 413f4932cfdSyangbo lu 414f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 415f4932cfdSyangbo lu iowrite32(value, host->ioaddr + reg); 416f4932cfdSyangbo lu } 417f4932cfdSyangbo lu 418f4932cfdSyangbo lu static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg) 419f4932cfdSyangbo lu { 42022dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 42122dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 422f4932cfdSyangbo lu int base = reg & ~0x3; 423f4932cfdSyangbo lu u32 value; 424f4932cfdSyangbo lu u32 ret; 425f4932cfdSyangbo lu 426f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 427f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 428f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 429f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 43022dc132dSYangbo Lu 43122dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 43222dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 43322dc132dSYangbo Lu */ 43422dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 43522dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 43622dc132dSYangbo Lu esdhc->in_sw_tuning) { 43722dc132dSYangbo Lu udelay(1); 43822dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 43922dc132dSYangbo Lu iowrite32be(ret, host->ioaddr + base); 44022dc132dSYangbo Lu } 44122dc132dSYangbo Lu } 442f4932cfdSyangbo lu } 443f4932cfdSyangbo lu 444f4932cfdSyangbo lu static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg) 445f4932cfdSyangbo lu { 44622dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 44722dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 448f4932cfdSyangbo lu int base = reg & ~0x3; 449f4932cfdSyangbo lu u32 value; 450f4932cfdSyangbo lu u32 ret; 451f4932cfdSyangbo lu 452f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 453f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 454f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 455f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 45622dc132dSYangbo Lu 45722dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 45822dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 45922dc132dSYangbo Lu */ 46022dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 46122dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 46222dc132dSYangbo Lu esdhc->in_sw_tuning) { 46322dc132dSYangbo Lu udelay(1); 46422dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 46522dc132dSYangbo Lu iowrite32(ret, host->ioaddr + base); 46622dc132dSYangbo Lu } 46722dc132dSYangbo Lu } 468f4932cfdSyangbo lu } 469f4932cfdSyangbo lu 470f4932cfdSyangbo lu static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg) 471f4932cfdSyangbo lu { 472f4932cfdSyangbo lu int base = reg & ~0x3; 473f4932cfdSyangbo lu u32 value; 474f4932cfdSyangbo lu u32 ret; 475f4932cfdSyangbo lu 476f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 477f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 478f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 479f4932cfdSyangbo lu } 480f4932cfdSyangbo lu 481f4932cfdSyangbo lu static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg) 482f4932cfdSyangbo lu { 483f4932cfdSyangbo lu int base = reg & ~0x3; 484f4932cfdSyangbo lu u32 value; 485f4932cfdSyangbo lu u32 ret; 486f4932cfdSyangbo lu 487f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 488f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 489f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 4907657c3a7SAlbert Herranz } 4917657c3a7SAlbert Herranz 492a4071fbbSHaijun Zhang /* 493a4071fbbSHaijun Zhang * For Abort or Suspend after Stop at Block Gap, ignore the ADMA 494a4071fbbSHaijun Zhang * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) 495a4071fbbSHaijun Zhang * and Block Gap Event(IRQSTAT[BGE]) are also set. 496a4071fbbSHaijun Zhang * For Continue, apply soft reset for data(SYSCTL[RSTD]); 497a4071fbbSHaijun Zhang * and re-issue the entire read transaction from beginning. 498a4071fbbSHaijun Zhang */ 499f4932cfdSyangbo lu static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) 500a4071fbbSHaijun Zhang { 501f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 5028605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 503a4071fbbSHaijun Zhang bool applicable; 504a4071fbbSHaijun Zhang dma_addr_t dmastart; 505a4071fbbSHaijun Zhang dma_addr_t dmanow; 506a4071fbbSHaijun Zhang 507a4071fbbSHaijun Zhang applicable = (intmask & SDHCI_INT_DATA_END) && 508a4071fbbSHaijun Zhang (intmask & SDHCI_INT_BLK_GAP) && 509f4932cfdSyangbo lu (esdhc->vendor_ver == VENDOR_V_23); 510a4071fbbSHaijun Zhang if (!applicable) 511a4071fbbSHaijun Zhang return; 512a4071fbbSHaijun Zhang 513a4071fbbSHaijun Zhang host->data->error = 0; 514a4071fbbSHaijun Zhang dmastart = sg_dma_address(host->data->sg); 515a4071fbbSHaijun Zhang dmanow = dmastart + host->data->bytes_xfered; 516a4071fbbSHaijun Zhang /* 517a4071fbbSHaijun Zhang * Force update to the next DMA block boundary. 518a4071fbbSHaijun Zhang */ 519a4071fbbSHaijun Zhang dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 520a4071fbbSHaijun Zhang SDHCI_DEFAULT_BOUNDARY_SIZE; 521a4071fbbSHaijun Zhang host->data->bytes_xfered = dmanow - dmastart; 522a4071fbbSHaijun Zhang sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); 523a4071fbbSHaijun Zhang } 524a4071fbbSHaijun Zhang 52580872e21SWolfram Sang static int esdhc_of_enable_dma(struct sdhci_host *host) 5267657c3a7SAlbert Herranz { 527f4932cfdSyangbo lu u32 value; 5285552d7adSLaurentiu Tudor struct device *dev = mmc_dev(host->mmc); 5295552d7adSLaurentiu Tudor 5305552d7adSLaurentiu Tudor if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || 5315552d7adSLaurentiu Tudor of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) 5325552d7adSLaurentiu Tudor dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); 533f4932cfdSyangbo lu 534f4932cfdSyangbo lu value = sdhci_readl(host, ESDHC_DMA_SYSCTL); 535121bd08bSRussell King 536121bd08bSRussell King if (of_dma_is_coherent(dev->of_node)) 537f4932cfdSyangbo lu value |= ESDHC_DMA_SNOOP; 538121bd08bSRussell King else 539121bd08bSRussell King value &= ~ESDHC_DMA_SNOOP; 540121bd08bSRussell King 541f4932cfdSyangbo lu sdhci_writel(host, value, ESDHC_DMA_SYSCTL); 5427657c3a7SAlbert Herranz return 0; 5437657c3a7SAlbert Herranz } 5447657c3a7SAlbert Herranz 54580872e21SWolfram Sang static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host) 5467657c3a7SAlbert Herranz { 547e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 54819c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 5497657c3a7SAlbert Herranz 55019c3a0efSyangbo lu if (esdhc->peripheral_clock) 55119c3a0efSyangbo lu return esdhc->peripheral_clock; 55219c3a0efSyangbo lu else 553e307148fSShawn Guo return pltfm_host->clock; 5547657c3a7SAlbert Herranz } 5557657c3a7SAlbert Herranz 55680872e21SWolfram Sang static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) 5577657c3a7SAlbert Herranz { 558e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 55919c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 56019c3a0efSyangbo lu unsigned int clock; 5617657c3a7SAlbert Herranz 56219c3a0efSyangbo lu if (esdhc->peripheral_clock) 56319c3a0efSyangbo lu clock = esdhc->peripheral_clock; 56419c3a0efSyangbo lu else 56519c3a0efSyangbo lu clock = pltfm_host->clock; 56619c3a0efSyangbo lu return clock / 256 / 16; 5677657c3a7SAlbert Herranz } 5687657c3a7SAlbert Herranz 569dd3f6983Syangbo lu static void esdhc_clock_enable(struct sdhci_host *host, bool enable) 570dd3f6983Syangbo lu { 5711b21a701SYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 5721b21a701SYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 573dd3f6983Syangbo lu ktime_t timeout; 5741b21a701SYangbo Lu u32 val, clk_en; 5751b21a701SYangbo Lu 5761b21a701SYangbo Lu clk_en = ESDHC_CLOCK_SDCLKEN; 5771b21a701SYangbo Lu 5781b21a701SYangbo Lu /* 5791b21a701SYangbo Lu * IPGEN/HCKEN/PEREN bits exist on eSDHC whose vendor version 5801b21a701SYangbo Lu * is 2.2 or lower. 5811b21a701SYangbo Lu */ 5821b21a701SYangbo Lu if (esdhc->vendor_ver <= VENDOR_V_22) 5831b21a701SYangbo Lu clk_en |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | 5841b21a701SYangbo Lu ESDHC_CLOCK_PEREN); 585dd3f6983Syangbo lu 586dd3f6983Syangbo lu val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 587dd3f6983Syangbo lu 588dd3f6983Syangbo lu if (enable) 5891b21a701SYangbo Lu val |= clk_en; 590dd3f6983Syangbo lu else 5911b21a701SYangbo Lu val &= ~clk_en; 592dd3f6983Syangbo lu 593dd3f6983Syangbo lu sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL); 594dd3f6983Syangbo lu 5951b21a701SYangbo Lu /* 5961b21a701SYangbo Lu * Wait max 20 ms. If vendor version is 2.2 or lower, do not 5971b21a701SYangbo Lu * wait clock stable bit which does not exist. 5981b21a701SYangbo Lu */ 599dd3f6983Syangbo lu timeout = ktime_add_ms(ktime_get(), 20); 6001b21a701SYangbo Lu while (esdhc->vendor_ver > VENDOR_V_22) { 601ea6d0273SAdrian Hunter bool timedout = ktime_after(ktime_get(), timeout); 602ea6d0273SAdrian Hunter 6031b21a701SYangbo Lu if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) 604ea6d0273SAdrian Hunter break; 605ea6d0273SAdrian Hunter if (timedout) { 606dd3f6983Syangbo lu pr_err("%s: Internal clock never stabilised.\n", 607dd3f6983Syangbo lu mmc_hostname(host->mmc)); 608dd3f6983Syangbo lu break; 609dd3f6983Syangbo lu } 6101b21a701SYangbo Lu usleep_range(10, 20); 611dd3f6983Syangbo lu } 612dd3f6983Syangbo lu } 613dd3f6983Syangbo lu 6146e32f65cSYangbo Lu static void esdhc_flush_async_fifo(struct sdhci_host *host) 6156e32f65cSYangbo Lu { 6166e32f65cSYangbo Lu ktime_t timeout; 6176e32f65cSYangbo Lu u32 val; 6186e32f65cSYangbo Lu 6196e32f65cSYangbo Lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 6206e32f65cSYangbo Lu val |= ESDHC_FLUSH_ASYNC_FIFO; 6216e32f65cSYangbo Lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 6226e32f65cSYangbo Lu 6236e32f65cSYangbo Lu /* Wait max 20 ms */ 6246e32f65cSYangbo Lu timeout = ktime_add_ms(ktime_get(), 20); 6256e32f65cSYangbo Lu while (1) { 6266e32f65cSYangbo Lu bool timedout = ktime_after(ktime_get(), timeout); 6276e32f65cSYangbo Lu 6286e32f65cSYangbo Lu if (!(sdhci_readl(host, ESDHC_DMA_SYSCTL) & 6296e32f65cSYangbo Lu ESDHC_FLUSH_ASYNC_FIFO)) 6306e32f65cSYangbo Lu break; 6316e32f65cSYangbo Lu if (timedout) { 6326e32f65cSYangbo Lu pr_err("%s: flushing asynchronous FIFO timeout.\n", 6336e32f65cSYangbo Lu mmc_hostname(host->mmc)); 6346e32f65cSYangbo Lu break; 6356e32f65cSYangbo Lu } 6366e32f65cSYangbo Lu usleep_range(10, 20); 6376e32f65cSYangbo Lu } 6386e32f65cSYangbo Lu } 6396e32f65cSYangbo Lu 640f060bc9cSJerry Huang static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) 641f060bc9cSJerry Huang { 642f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 6438605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 6441b21a701SYangbo Lu unsigned int pre_div = 1, div = 1; 6451b21a701SYangbo Lu unsigned int clock_fixup = 0; 646e145ac45Syangbo lu ktime_t timeout; 647d31fc00aSDong Aisheng u32 temp; 648d31fc00aSDong Aisheng 649dd3f6983Syangbo lu if (clock == 0) { 6501b21a701SYangbo Lu host->mmc->actual_clock = 0; 651dd3f6983Syangbo lu esdhc_clock_enable(host, false); 652373073efSRussell King return; 653dd3f6983Syangbo lu } 654d31fc00aSDong Aisheng 6551b21a701SYangbo Lu /* Start pre_div at 2 for vendor version < 2.3. */ 656f4932cfdSyangbo lu if (esdhc->vendor_ver < VENDOR_V_23) 65777bd2f6fSYangbo Lu pre_div = 2; 65877bd2f6fSYangbo Lu 6591b21a701SYangbo Lu /* Fix clock value. */ 66067fdfbdfSyinbo.zhu if (host->mmc->card && mmc_card_sd(host->mmc->card) && 66167fdfbdfSyinbo.zhu esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) 6621b21a701SYangbo Lu clock_fixup = esdhc->clk_fixup->sd_dflt_max_clk; 66367fdfbdfSyinbo.zhu else if (esdhc->clk_fixup) 6641b21a701SYangbo Lu clock_fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; 665a627f025Syangbo lu 6661b21a701SYangbo Lu if (clock_fixup == 0 || clock < clock_fixup) 6671b21a701SYangbo Lu clock_fixup = clock; 668f060bc9cSJerry Huang 6691b21a701SYangbo Lu /* Calculate pre_div and div. */ 6701b21a701SYangbo Lu while (host->max_clk / pre_div / 16 > clock_fixup && pre_div < 256) 671d31fc00aSDong Aisheng pre_div *= 2; 672d31fc00aSDong Aisheng 6731b21a701SYangbo Lu while (host->max_clk / pre_div / div > clock_fixup && div < 16) 674d31fc00aSDong Aisheng div++; 675d31fc00aSDong Aisheng 6761b21a701SYangbo Lu esdhc->div_ratio = pre_div * div; 6771b21a701SYangbo Lu 6781b21a701SYangbo Lu /* Limit clock division for HS400 200MHz clock for quirk. */ 6796079e63cSYangbo Lu if (esdhc->quirk_limited_clk_division && 6806079e63cSYangbo Lu clock == MMC_HS200_MAX_DTR && 6816079e63cSYangbo Lu (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 || 6826079e63cSYangbo Lu host->flags & SDHCI_HS400_TUNING)) { 6831b21a701SYangbo Lu if (esdhc->div_ratio <= 4) { 6846079e63cSYangbo Lu pre_div = 4; 6856079e63cSYangbo Lu div = 1; 6861b21a701SYangbo Lu } else if (esdhc->div_ratio <= 8) { 6876079e63cSYangbo Lu pre_div = 4; 6886079e63cSYangbo Lu div = 2; 6891b21a701SYangbo Lu } else if (esdhc->div_ratio <= 12) { 6906079e63cSYangbo Lu pre_div = 4; 6916079e63cSYangbo Lu div = 3; 6926079e63cSYangbo Lu } else { 693b11c36d5SColin Ian King pr_warn("%s: using unsupported clock division.\n", 6946079e63cSYangbo Lu mmc_hostname(host->mmc)); 6956079e63cSYangbo Lu } 6961b21a701SYangbo Lu esdhc->div_ratio = pre_div * div; 6976079e63cSYangbo Lu } 6986079e63cSYangbo Lu 6991b21a701SYangbo Lu host->mmc->actual_clock = host->max_clk / esdhc->div_ratio; 7001b21a701SYangbo Lu 701d31fc00aSDong Aisheng dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", 7021b21a701SYangbo Lu clock, host->mmc->actual_clock); 7031b21a701SYangbo Lu 7041b21a701SYangbo Lu /* Set clock division into register. */ 705d31fc00aSDong Aisheng pre_div >>= 1; 706d31fc00aSDong Aisheng div--; 707d31fc00aSDong Aisheng 7081b21a701SYangbo Lu esdhc_clock_enable(host, false); 7091b21a701SYangbo Lu 710d31fc00aSDong Aisheng temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 7111b21a701SYangbo Lu temp &= ~ESDHC_CLOCK_MASK; 7121b21a701SYangbo Lu temp |= ((div << ESDHC_DIVIDER_SHIFT) | 7131b21a701SYangbo Lu (pre_div << ESDHC_PREDIV_SHIFT)); 714d31fc00aSDong Aisheng sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 715e87d2db2Syangbo lu 7161b21a701SYangbo Lu /* 7171b21a701SYangbo Lu * Wait max 20 ms. If vendor version is 2.2 or lower, do not 7181b21a701SYangbo Lu * wait clock stable bit which does not exist. 7191b21a701SYangbo Lu */ 7201b21a701SYangbo Lu timeout = ktime_add_ms(ktime_get(), 20); 7211b21a701SYangbo Lu while (esdhc->vendor_ver > VENDOR_V_22) { 7221b21a701SYangbo Lu bool timedout = ktime_after(ktime_get(), timeout); 7231b21a701SYangbo Lu 7241b21a701SYangbo Lu if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) 7251b21a701SYangbo Lu break; 7261b21a701SYangbo Lu if (timedout) { 7271b21a701SYangbo Lu pr_err("%s: Internal clock never stabilised.\n", 7281b21a701SYangbo Lu mmc_hostname(host->mmc)); 7291b21a701SYangbo Lu break; 7301b21a701SYangbo Lu } 7311b21a701SYangbo Lu usleep_range(10, 20); 7321b21a701SYangbo Lu } 7331b21a701SYangbo Lu 7341b21a701SYangbo Lu /* Additional setting for HS400. */ 73554e08d9aSYangbo Lu if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && 73654e08d9aSYangbo Lu clock == MMC_HS200_MAX_DTR) { 73754e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 73854e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_MODE, ESDHC_TBCTL); 73954e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_SDCLKCTL); 74054e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_CMD_CLK_CTL, ESDHC_SDCLKCTL); 74154e08d9aSYangbo Lu esdhc_clock_enable(host, true); 74254e08d9aSYangbo Lu 74354e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_DLLCFG0); 74458d0bf84SYangbo Lu temp |= ESDHC_DLL_ENABLE; 74558d0bf84SYangbo Lu if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) 74658d0bf84SYangbo Lu temp |= ESDHC_DLL_FREQ_SEL; 74754e08d9aSYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 748*011fde48SYangbo Lu 749*011fde48SYangbo Lu temp |= ESDHC_DLL_RESET; 750*011fde48SYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 751*011fde48SYangbo Lu udelay(1); 752*011fde48SYangbo Lu temp &= ~ESDHC_DLL_RESET; 753*011fde48SYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 754*011fde48SYangbo Lu 755*011fde48SYangbo Lu /* Wait max 20 ms */ 756*011fde48SYangbo Lu if (read_poll_timeout(sdhci_readl, temp, 757*011fde48SYangbo Lu temp & ESDHC_DLL_STS_SLV_LOCK, 758*011fde48SYangbo Lu 10, 20000, false, 759*011fde48SYangbo Lu host, ESDHC_DLLSTAT0)) 760*011fde48SYangbo Lu pr_err("%s: timeout for delay chain lock.\n", 761*011fde48SYangbo Lu mmc_hostname(host->mmc)); 762*011fde48SYangbo Lu 76354e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 76454e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL); 76554e08d9aSYangbo Lu 76654e08d9aSYangbo Lu esdhc_clock_enable(host, false); 7676e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 76854e08d9aSYangbo Lu } 76980c74823SYangbo Lu esdhc_clock_enable(host, true); 770e87d2db2Syangbo lu } 771e87d2db2Syangbo lu 7722317f56cSRussell King static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) 77366b50a00SOded Gabbay { 77466b50a00SOded Gabbay u32 ctrl; 77566b50a00SOded Gabbay 776f4932cfdSyangbo lu ctrl = sdhci_readl(host, ESDHC_PROCTL); 777f4932cfdSyangbo lu ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK); 77866b50a00SOded Gabbay switch (width) { 77966b50a00SOded Gabbay case MMC_BUS_WIDTH_8: 780f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_8BITBUS; 78166b50a00SOded Gabbay break; 78266b50a00SOded Gabbay 78366b50a00SOded Gabbay case MMC_BUS_WIDTH_4: 784f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_4BITBUS; 78566b50a00SOded Gabbay break; 78666b50a00SOded Gabbay 78766b50a00SOded Gabbay default: 78866b50a00SOded Gabbay break; 78966b50a00SOded Gabbay } 79066b50a00SOded Gabbay 791f4932cfdSyangbo lu sdhci_writel(host, ctrl, ESDHC_PROCTL); 79266b50a00SOded Gabbay } 79366b50a00SOded Gabbay 794304f0a98SAlessio Igor Bogani static void esdhc_reset(struct sdhci_host *host, u8 mask) 795304f0a98SAlessio Igor Bogani { 79648e304ccSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 79748e304ccSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 7982aa3d826SYangbo Lu u32 val, bus_width = 0; 799f2bc6000Syinbo.zhu 8002aa3d826SYangbo Lu /* 8012aa3d826SYangbo Lu * Add delay to make sure all the DMA transfers are finished 8022aa3d826SYangbo Lu * for quirk. 8032aa3d826SYangbo Lu */ 804f667216cSYangbo Lu if (esdhc->quirk_delay_before_data_reset && 805f667216cSYangbo Lu (mask & SDHCI_RESET_DATA) && 806f667216cSYangbo Lu (host->flags & SDHCI_REQ_USE_DMA)) 807f667216cSYangbo Lu mdelay(5); 808f667216cSYangbo Lu 8092aa3d826SYangbo Lu /* 8102aa3d826SYangbo Lu * Save bus-width for eSDHC whose vendor version is 2.2 8112aa3d826SYangbo Lu * or lower for data reset. 8122aa3d826SYangbo Lu */ 8132aa3d826SYangbo Lu if ((mask & SDHCI_RESET_DATA) && 8142aa3d826SYangbo Lu (esdhc->vendor_ver <= VENDOR_V_22)) { 8152aa3d826SYangbo Lu val = sdhci_readl(host, ESDHC_PROCTL); 8162aa3d826SYangbo Lu bus_width = val & ESDHC_CTRL_BUSWIDTH_MASK; 8172aa3d826SYangbo Lu } 8182aa3d826SYangbo Lu 819304f0a98SAlessio Igor Bogani sdhci_reset(host, mask); 820304f0a98SAlessio Igor Bogani 8212aa3d826SYangbo Lu /* 8222aa3d826SYangbo Lu * Restore bus-width setting and interrupt registers for eSDHC 8232aa3d826SYangbo Lu * whose vendor version is 2.2 or lower for data reset. 8242aa3d826SYangbo Lu */ 8252aa3d826SYangbo Lu if ((mask & SDHCI_RESET_DATA) && 8262aa3d826SYangbo Lu (esdhc->vendor_ver <= VENDOR_V_22)) { 8272aa3d826SYangbo Lu val = sdhci_readl(host, ESDHC_PROCTL); 8282aa3d826SYangbo Lu val &= ~ESDHC_CTRL_BUSWIDTH_MASK; 8292aa3d826SYangbo Lu val |= bus_width; 8302aa3d826SYangbo Lu sdhci_writel(host, val, ESDHC_PROCTL); 8312aa3d826SYangbo Lu 832304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 833304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 8342aa3d826SYangbo Lu } 835f2bc6000Syinbo.zhu 8362aa3d826SYangbo Lu /* 8372aa3d826SYangbo Lu * Some bits have to be cleaned manually for eSDHC whose spec 8382aa3d826SYangbo Lu * version is higher than 3.0 for all reset. 8392aa3d826SYangbo Lu */ 8402aa3d826SYangbo Lu if ((mask & SDHCI_RESET_ALL) && 8412aa3d826SYangbo Lu (esdhc->spec_ver >= SDHCI_SPEC_300)) { 842f2bc6000Syinbo.zhu val = sdhci_readl(host, ESDHC_TBCTL); 843f2bc6000Syinbo.zhu val &= ~ESDHC_TB_EN; 844f2bc6000Syinbo.zhu sdhci_writel(host, val, ESDHC_TBCTL); 84548e304ccSYangbo Lu 8462aa3d826SYangbo Lu /* 8472aa3d826SYangbo Lu * Initialize eSDHC_DLLCFG1[DLL_PD_PULSE_STRETCH_SEL] to 8482aa3d826SYangbo Lu * 0 for quirk. 8492aa3d826SYangbo Lu */ 85048e304ccSYangbo Lu if (esdhc->quirk_unreliable_pulse_detection) { 85148e304ccSYangbo Lu val = sdhci_readl(host, ESDHC_DLLCFG1); 85248e304ccSYangbo Lu val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL; 85348e304ccSYangbo Lu sdhci_writel(host, val, ESDHC_DLLCFG1); 85448e304ccSYangbo Lu } 855f2bc6000Syinbo.zhu } 856304f0a98SAlessio Igor Bogani } 857304f0a98SAlessio Igor Bogani 858ea35645aSyangbo lu /* The SCFG, Supplemental Configuration Unit, provides SoC specific 859ea35645aSyangbo lu * configuration and status registers for the device. There is a 860ea35645aSyangbo lu * SDHC IO VSEL control register on SCFG for some platforms. It's 861ea35645aSyangbo lu * used to support SDHC IO voltage switching. 862ea35645aSyangbo lu */ 863ea35645aSyangbo lu static const struct of_device_id scfg_device_ids[] = { 864ea35645aSyangbo lu { .compatible = "fsl,t1040-scfg", }, 865ea35645aSyangbo lu { .compatible = "fsl,ls1012a-scfg", }, 866ea35645aSyangbo lu { .compatible = "fsl,ls1046a-scfg", }, 867ea35645aSyangbo lu {} 868ea35645aSyangbo lu }; 869ea35645aSyangbo lu 870ea35645aSyangbo lu /* SDHC IO VSEL control register definition */ 871ea35645aSyangbo lu #define SCFG_SDHCIOVSELCR 0x408 872ea35645aSyangbo lu #define SDHCIOVSELCR_TGLEN 0x80000000 873ea35645aSyangbo lu #define SDHCIOVSELCR_VSELVAL 0x60000000 874ea35645aSyangbo lu #define SDHCIOVSELCR_SDHC_VS 0x00000001 875ea35645aSyangbo lu 876ea35645aSyangbo lu static int esdhc_signal_voltage_switch(struct mmc_host *mmc, 877ea35645aSyangbo lu struct mmc_ios *ios) 878ea35645aSyangbo lu { 879ea35645aSyangbo lu struct sdhci_host *host = mmc_priv(mmc); 880ea35645aSyangbo lu struct device_node *scfg_node; 881ea35645aSyangbo lu void __iomem *scfg_base = NULL; 882ea35645aSyangbo lu u32 sdhciovselcr; 883ea35645aSyangbo lu u32 val; 884ea35645aSyangbo lu 885ea35645aSyangbo lu /* 886ea35645aSyangbo lu * Signal Voltage Switching is only applicable for Host Controllers 887ea35645aSyangbo lu * v3.00 and above. 888ea35645aSyangbo lu */ 889ea35645aSyangbo lu if (host->version < SDHCI_SPEC_300) 890ea35645aSyangbo lu return 0; 891ea35645aSyangbo lu 892ea35645aSyangbo lu val = sdhci_readl(host, ESDHC_PROCTL); 893ea35645aSyangbo lu 894ea35645aSyangbo lu switch (ios->signal_voltage) { 895ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_330: 896ea35645aSyangbo lu val &= ~ESDHC_VOLT_SEL; 897ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 898ea35645aSyangbo lu return 0; 899ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_180: 900ea35645aSyangbo lu scfg_node = of_find_matching_node(NULL, scfg_device_ids); 901ea35645aSyangbo lu if (scfg_node) 902ea35645aSyangbo lu scfg_base = of_iomap(scfg_node, 0); 903ea35645aSyangbo lu if (scfg_base) { 904ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 905ea35645aSyangbo lu SDHCIOVSELCR_VSELVAL; 906ea35645aSyangbo lu iowrite32be(sdhciovselcr, 907ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 908ea35645aSyangbo lu 909ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 910ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 911ea35645aSyangbo lu mdelay(5); 912ea35645aSyangbo lu 913ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 914ea35645aSyangbo lu SDHCIOVSELCR_SDHC_VS; 915ea35645aSyangbo lu iowrite32be(sdhciovselcr, 916ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 917ea35645aSyangbo lu iounmap(scfg_base); 918ea35645aSyangbo lu } else { 919ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 920ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 921ea35645aSyangbo lu } 922ea35645aSyangbo lu return 0; 923ea35645aSyangbo lu default: 924ea35645aSyangbo lu return 0; 925ea35645aSyangbo lu } 926ea35645aSyangbo lu } 927ea35645aSyangbo lu 92822dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type1[] = { 9295b742232SYangbo Lu { .family = "QorIQ T1023", }, 9305b742232SYangbo Lu { .family = "QorIQ T1040", }, 9315b742232SYangbo Lu { .family = "QorIQ T2080", }, 9325b742232SYangbo Lu { .family = "QorIQ LS1021A", }, 93322dc132dSYangbo Lu { }, 93422dc132dSYangbo Lu }; 93522dc132dSYangbo Lu 93622dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type2[] = { 9375b742232SYangbo Lu { .family = "QorIQ LS1012A", }, 9385b742232SYangbo Lu { .family = "QorIQ LS1043A", }, 9395b742232SYangbo Lu { .family = "QorIQ LS1046A", }, 9405b742232SYangbo Lu { .family = "QorIQ LS1080A", }, 9415b742232SYangbo Lu { .family = "QorIQ LS2080A", }, 9425b742232SYangbo Lu { .family = "QorIQ LA1575A", }, 943b1f378abSYinbo Zhu { }, 944b1f378abSYinbo Zhu }; 945b1f378abSYinbo Zhu 94654e08d9aSYangbo Lu static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable) 947ba49cbd0Syangbo lu { 948ba49cbd0Syangbo lu u32 val; 949ba49cbd0Syangbo lu 950ba49cbd0Syangbo lu esdhc_clock_enable(host, false); 9516e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 952ba49cbd0Syangbo lu 953ba49cbd0Syangbo lu val = sdhci_readl(host, ESDHC_TBCTL); 95454e08d9aSYangbo Lu if (enable) 955ba49cbd0Syangbo lu val |= ESDHC_TB_EN; 95654e08d9aSYangbo Lu else 95754e08d9aSYangbo Lu val &= ~ESDHC_TB_EN; 958ba49cbd0Syangbo lu sdhci_writel(host, val, ESDHC_TBCTL); 959ba49cbd0Syangbo lu 96054e08d9aSYangbo Lu esdhc_clock_enable(host, true); 96154e08d9aSYangbo Lu } 96254e08d9aSYangbo Lu 963f3c20825SYangbo Lu static void esdhc_tuning_window_ptr(struct sdhci_host *host, u8 *window_start, 96422dc132dSYangbo Lu u8 *window_end) 96522dc132dSYangbo Lu { 96622dc132dSYangbo Lu u32 val; 96722dc132dSYangbo Lu 96822dc132dSYangbo Lu /* Write TBCTL[11:8]=4'h8 */ 96922dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 97022dc132dSYangbo Lu val &= ~(0xf << 8); 97122dc132dSYangbo Lu val |= 8 << 8; 97222dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 97322dc132dSYangbo Lu 97422dc132dSYangbo Lu mdelay(1); 97522dc132dSYangbo Lu 97622dc132dSYangbo Lu /* Read TBCTL[31:0] register and rewrite again */ 97722dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 97822dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 97922dc132dSYangbo Lu 98022dc132dSYangbo Lu mdelay(1); 98122dc132dSYangbo Lu 98222dc132dSYangbo Lu /* Read the TBSTAT[31:0] register twice */ 98322dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 98422dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 98522dc132dSYangbo Lu 986f3c20825SYangbo Lu *window_end = val & 0xff; 987f3c20825SYangbo Lu *window_start = (val >> 8) & 0xff; 988f3c20825SYangbo Lu } 989f3c20825SYangbo Lu 990f3c20825SYangbo Lu static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start, 991f3c20825SYangbo Lu u8 *window_end) 992f3c20825SYangbo Lu { 993f3c20825SYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 994f3c20825SYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 995f3c20825SYangbo Lu u8 start_ptr, end_ptr; 996f3c20825SYangbo Lu 997f3c20825SYangbo Lu if (esdhc->quirk_tuning_erratum_type1) { 998f3c20825SYangbo Lu *window_start = 5 * esdhc->div_ratio; 999f3c20825SYangbo Lu *window_end = 3 * esdhc->div_ratio; 1000f3c20825SYangbo Lu return; 1001f3c20825SYangbo Lu } 1002f3c20825SYangbo Lu 1003f3c20825SYangbo Lu esdhc_tuning_window_ptr(host, &start_ptr, &end_ptr); 1004f3c20825SYangbo Lu 100522dc132dSYangbo Lu /* Reset data lines by setting ESDHCCTL[RSTD] */ 100622dc132dSYangbo Lu sdhci_reset(host, SDHCI_RESET_DATA); 100722dc132dSYangbo Lu /* Write 32'hFFFF_FFFF to IRQSTAT register */ 100822dc132dSYangbo Lu sdhci_writel(host, 0xFFFFFFFF, SDHCI_INT_STATUS); 100922dc132dSYangbo Lu 10105b742232SYangbo Lu /* If TBSTAT[15:8]-TBSTAT[7:0] > (4 * div_ratio) + 2 10115b742232SYangbo Lu * or TBSTAT[7:0]-TBSTAT[15:8] > (4 * div_ratio) + 2, 101222dc132dSYangbo Lu * then program TBPTR[TB_WNDW_END_PTR] = 4 * div_ratio 101322dc132dSYangbo Lu * and program TBPTR[TB_WNDW_START_PTR] = 8 * div_ratio. 101422dc132dSYangbo Lu */ 101522dc132dSYangbo Lu 10165b742232SYangbo Lu if (abs(start_ptr - end_ptr) > (4 * esdhc->div_ratio + 2)) { 101722dc132dSYangbo Lu *window_start = 8 * esdhc->div_ratio; 101822dc132dSYangbo Lu *window_end = 4 * esdhc->div_ratio; 101922dc132dSYangbo Lu } else { 102022dc132dSYangbo Lu *window_start = 5 * esdhc->div_ratio; 102122dc132dSYangbo Lu *window_end = 3 * esdhc->div_ratio; 102222dc132dSYangbo Lu } 102322dc132dSYangbo Lu } 102422dc132dSYangbo Lu 102522dc132dSYangbo Lu static int esdhc_execute_sw_tuning(struct mmc_host *mmc, u32 opcode, 102622dc132dSYangbo Lu u8 window_start, u8 window_end) 102722dc132dSYangbo Lu { 102822dc132dSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 102922dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 103022dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 103122dc132dSYangbo Lu u32 val; 103222dc132dSYangbo Lu int ret; 103322dc132dSYangbo Lu 103422dc132dSYangbo Lu /* Program TBPTR[TB_WNDW_END_PTR] and TBPTR[TB_WNDW_START_PTR] */ 103522dc132dSYangbo Lu val = ((u32)window_start << ESDHC_WNDW_STRT_PTR_SHIFT) & 103622dc132dSYangbo Lu ESDHC_WNDW_STRT_PTR_MASK; 103722dc132dSYangbo Lu val |= window_end & ESDHC_WNDW_END_PTR_MASK; 103822dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBPTR); 103922dc132dSYangbo Lu 104022dc132dSYangbo Lu /* Program the software tuning mode by setting TBCTL[TB_MODE]=2'h3 */ 104122dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 104222dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 104322dc132dSYangbo Lu val |= ESDHC_TB_MODE_SW; 104422dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 104522dc132dSYangbo Lu 104622dc132dSYangbo Lu esdhc->in_sw_tuning = true; 104722dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 104822dc132dSYangbo Lu esdhc->in_sw_tuning = false; 104922dc132dSYangbo Lu return ret; 105022dc132dSYangbo Lu } 105122dc132dSYangbo Lu 105254e08d9aSYangbo Lu static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) 105354e08d9aSYangbo Lu { 105454e08d9aSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 105554e08d9aSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 105654e08d9aSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 105722dc132dSYangbo Lu u8 window_start, window_end; 105822dc132dSYangbo Lu int ret, retries = 1; 105954e08d9aSYangbo Lu bool hs400_tuning; 106004509d77SYangbo Lu unsigned int clk; 106154e08d9aSYangbo Lu u32 val; 106254e08d9aSYangbo Lu 106304509d77SYangbo Lu /* For tuning mode, the sd clock divisor value 106404509d77SYangbo Lu * must be larger than 3 according to reference manual. 106504509d77SYangbo Lu */ 106604509d77SYangbo Lu clk = esdhc->peripheral_clock / 3; 106704509d77SYangbo Lu if (host->clock > clk) 106804509d77SYangbo Lu esdhc_of_set_clock(host, clk); 106904509d77SYangbo Lu 107054e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 107154e08d9aSYangbo Lu 10720add6e9bSMichael Walle /* 10730add6e9bSMichael Walle * The eSDHC controller takes the data timeout value into account 10740add6e9bSMichael Walle * during tuning. If the SD card is too slow sending the response, the 10750add6e9bSMichael Walle * timer will expire and a "Buffer Read Ready" interrupt without data 10760add6e9bSMichael Walle * is triggered. This leads to tuning errors. 10770add6e9bSMichael Walle * 10780add6e9bSMichael Walle * Just set the timeout to the maximum value because the core will 10790add6e9bSMichael Walle * already take care of it in sdhci_send_tuning(). 10800add6e9bSMichael Walle */ 10810add6e9bSMichael Walle sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); 10820add6e9bSMichael Walle 108354e08d9aSYangbo Lu hs400_tuning = host->flags & SDHCI_HS400_TUNING; 108454e08d9aSYangbo Lu 108522dc132dSYangbo Lu do { 108622dc132dSYangbo Lu if (esdhc->quirk_limited_clk_division && 108722dc132dSYangbo Lu hs400_tuning) 108822dc132dSYangbo Lu esdhc_of_set_clock(host, host->clock); 108922dc132dSYangbo Lu 109022dc132dSYangbo Lu /* Do HW tuning */ 109122dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 109222dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 109322dc132dSYangbo Lu val |= ESDHC_TB_MODE_3; 109422dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 109522dc132dSYangbo Lu 109622dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 109722dc132dSYangbo Lu if (ret) 109822dc132dSYangbo Lu break; 109922dc132dSYangbo Lu 11005b742232SYangbo Lu /* For type2 affected platforms of the tuning erratum, 11015b742232SYangbo Lu * tuning may succeed although eSDHC might not have 11025b742232SYangbo Lu * tuned properly. Need to check tuning window. 11035b742232SYangbo Lu */ 11045b742232SYangbo Lu if (esdhc->quirk_tuning_erratum_type2 && 11055b742232SYangbo Lu !host->tuning_err) { 11065b742232SYangbo Lu esdhc_tuning_window_ptr(host, &window_start, 11075b742232SYangbo Lu &window_end); 11085b742232SYangbo Lu if (abs(window_start - window_end) > 11095b742232SYangbo Lu (4 * esdhc->div_ratio + 2)) 11105b742232SYangbo Lu host->tuning_err = -EAGAIN; 11115b742232SYangbo Lu } 11125b742232SYangbo Lu 111322dc132dSYangbo Lu /* If HW tuning fails and triggers erratum, 111422dc132dSYangbo Lu * try workaround. 111522dc132dSYangbo Lu */ 111622dc132dSYangbo Lu ret = host->tuning_err; 111722dc132dSYangbo Lu if (ret == -EAGAIN && 111822dc132dSYangbo Lu (esdhc->quirk_tuning_erratum_type1 || 111922dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2)) { 112022dc132dSYangbo Lu /* Recover HS400 tuning flag */ 112122dc132dSYangbo Lu if (hs400_tuning) 112222dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 112322dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try SW tuning!\n", 112422dc132dSYangbo Lu mmc_hostname(mmc)); 112522dc132dSYangbo Lu /* Do SW tuning */ 112622dc132dSYangbo Lu esdhc_prepare_sw_tuning(host, &window_start, 112722dc132dSYangbo Lu &window_end); 112822dc132dSYangbo Lu ret = esdhc_execute_sw_tuning(mmc, opcode, 112922dc132dSYangbo Lu window_start, 113022dc132dSYangbo Lu window_end); 113122dc132dSYangbo Lu if (ret) 113222dc132dSYangbo Lu break; 113322dc132dSYangbo Lu 113422dc132dSYangbo Lu /* Retry both HW/SW tuning with reduced clock. */ 113522dc132dSYangbo Lu ret = host->tuning_err; 113622dc132dSYangbo Lu if (ret == -EAGAIN && retries) { 113722dc132dSYangbo Lu /* Recover HS400 tuning flag */ 113822dc132dSYangbo Lu if (hs400_tuning) 113922dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 114022dc132dSYangbo Lu 114122dc132dSYangbo Lu clk = host->max_clk / (esdhc->div_ratio + 1); 114222dc132dSYangbo Lu esdhc_of_set_clock(host, clk); 114322dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try tuning with reduced clock!\n", 114422dc132dSYangbo Lu mmc_hostname(mmc)); 114522dc132dSYangbo Lu } else { 114622dc132dSYangbo Lu break; 114722dc132dSYangbo Lu } 114822dc132dSYangbo Lu } else { 114922dc132dSYangbo Lu break; 115022dc132dSYangbo Lu } 115122dc132dSYangbo Lu } while (retries--); 115222dc132dSYangbo Lu 115322dc132dSYangbo Lu if (ret) { 115422dc132dSYangbo Lu esdhc_tuning_block_enable(host, false); 115522dc132dSYangbo Lu } else if (hs400_tuning) { 115654e08d9aSYangbo Lu val = sdhci_readl(host, ESDHC_SDTIMNGCTL); 115754e08d9aSYangbo Lu val |= ESDHC_FLW_CTL_BG; 115854e08d9aSYangbo Lu sdhci_writel(host, val, ESDHC_SDTIMNGCTL); 115954e08d9aSYangbo Lu } 116054e08d9aSYangbo Lu 116154e08d9aSYangbo Lu return ret; 116254e08d9aSYangbo Lu } 116354e08d9aSYangbo Lu 116454e08d9aSYangbo Lu static void esdhc_set_uhs_signaling(struct sdhci_host *host, 116554e08d9aSYangbo Lu unsigned int timing) 116654e08d9aSYangbo Lu { 116747e9e107SYangbo Lu u32 val; 116847e9e107SYangbo Lu 116947e9e107SYangbo Lu /* 117047e9e107SYangbo Lu * There are specific registers setting for HS400 mode. 117147e9e107SYangbo Lu * Clean all of them if controller is in HS400 mode to 117247e9e107SYangbo Lu * exit HS400 mode before re-setting any speed mode. 117347e9e107SYangbo Lu */ 117447e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 117547e9e107SYangbo Lu if (val & ESDHC_HS400_MODE) { 117647e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_SDTIMNGCTL); 117747e9e107SYangbo Lu val &= ~ESDHC_FLW_CTL_BG; 117847e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_SDTIMNGCTL); 117947e9e107SYangbo Lu 118047e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_SDCLKCTL); 118147e9e107SYangbo Lu val &= ~ESDHC_CMD_CLK_CTL; 118247e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_SDCLKCTL); 118347e9e107SYangbo Lu 118447e9e107SYangbo Lu esdhc_clock_enable(host, false); 118547e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 118647e9e107SYangbo Lu val &= ~ESDHC_HS400_MODE; 118747e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 118847e9e107SYangbo Lu esdhc_clock_enable(host, true); 118947e9e107SYangbo Lu 119047e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_DLLCFG0); 119147e9e107SYangbo Lu val &= ~(ESDHC_DLL_ENABLE | ESDHC_DLL_FREQ_SEL); 119247e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_DLLCFG0); 119347e9e107SYangbo Lu 119447e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 119547e9e107SYangbo Lu val &= ~ESDHC_HS400_WNDW_ADJUST; 119647e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 119747e9e107SYangbo Lu 119847e9e107SYangbo Lu esdhc_tuning_block_enable(host, false); 119947e9e107SYangbo Lu } 120047e9e107SYangbo Lu 120154e08d9aSYangbo Lu if (timing == MMC_TIMING_MMC_HS400) 120254e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 120354e08d9aSYangbo Lu else 120454e08d9aSYangbo Lu sdhci_set_uhs_signaling(host, timing); 1205ba49cbd0Syangbo lu } 1206ba49cbd0Syangbo lu 1207b214fe59SYinbo Zhu static u32 esdhc_irq(struct sdhci_host *host, u32 intmask) 1208b214fe59SYinbo Zhu { 1209060522d8SChris Packham struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1210060522d8SChris Packham struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1211b214fe59SYinbo Zhu u32 command; 1212b214fe59SYinbo Zhu 1213060522d8SChris Packham if (esdhc->quirk_trans_complete_erratum) { 1214b214fe59SYinbo Zhu command = SDHCI_GET_CMD(sdhci_readw(host, 1215b214fe59SYinbo Zhu SDHCI_COMMAND)); 1216b214fe59SYinbo Zhu if (command == MMC_WRITE_MULTIPLE_BLOCK && 1217b214fe59SYinbo Zhu sdhci_readw(host, SDHCI_BLOCK_COUNT) && 1218b214fe59SYinbo Zhu intmask & SDHCI_INT_DATA_END) { 1219b214fe59SYinbo Zhu intmask &= ~SDHCI_INT_DATA_END; 1220b214fe59SYinbo Zhu sdhci_writel(host, SDHCI_INT_DATA_END, 1221b214fe59SYinbo Zhu SDHCI_INT_STATUS); 1222b214fe59SYinbo Zhu } 1223b214fe59SYinbo Zhu } 1224b214fe59SYinbo Zhu return intmask; 1225b214fe59SYinbo Zhu } 1226b214fe59SYinbo Zhu 12279e48b336SUlf Hansson #ifdef CONFIG_PM_SLEEP 1228723f7924SRussell King static u32 esdhc_proctl; 1229723f7924SRussell King static int esdhc_of_suspend(struct device *dev) 1230723f7924SRussell King { 1231723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1232723f7924SRussell King 1233f4932cfdSyangbo lu esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL); 1234723f7924SRussell King 1235d38dcad4SAdrian Hunter if (host->tuning_mode != SDHCI_TUNING_MODE_3) 1236d38dcad4SAdrian Hunter mmc_retune_needed(host->mmc); 1237d38dcad4SAdrian Hunter 1238723f7924SRussell King return sdhci_suspend_host(host); 1239723f7924SRussell King } 1240723f7924SRussell King 124106732b84SUlf Hansson static int esdhc_of_resume(struct device *dev) 1242723f7924SRussell King { 1243723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1244723f7924SRussell King int ret = sdhci_resume_host(host); 1245723f7924SRussell King 1246723f7924SRussell King if (ret == 0) { 1247723f7924SRussell King /* Isn't this already done by sdhci_resume_host() ? --rmk */ 1248723f7924SRussell King esdhc_of_enable_dma(host); 1249f4932cfdSyangbo lu sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); 1250723f7924SRussell King } 1251723f7924SRussell King return ret; 1252723f7924SRussell King } 1253723f7924SRussell King #endif 1254723f7924SRussell King 12559e48b336SUlf Hansson static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, 12569e48b336SUlf Hansson esdhc_of_suspend, 12579e48b336SUlf Hansson esdhc_of_resume); 12589e48b336SUlf Hansson 1259f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_be_ops = { 1260f4932cfdSyangbo lu .read_l = esdhc_be_readl, 1261f4932cfdSyangbo lu .read_w = esdhc_be_readw, 1262f4932cfdSyangbo lu .read_b = esdhc_be_readb, 1263f4932cfdSyangbo lu .write_l = esdhc_be_writel, 1264f4932cfdSyangbo lu .write_w = esdhc_be_writew, 1265f4932cfdSyangbo lu .write_b = esdhc_be_writeb, 1266f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1267f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1268f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1269f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1270f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1271f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1272f4932cfdSyangbo lu .reset = esdhc_reset, 127354e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1274b214fe59SYinbo Zhu .irq = esdhc_irq, 1275f4932cfdSyangbo lu }; 1276f4932cfdSyangbo lu 1277f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_le_ops = { 1278f4932cfdSyangbo lu .read_l = esdhc_le_readl, 1279f4932cfdSyangbo lu .read_w = esdhc_le_readw, 1280f4932cfdSyangbo lu .read_b = esdhc_le_readb, 1281f4932cfdSyangbo lu .write_l = esdhc_le_writel, 1282f4932cfdSyangbo lu .write_w = esdhc_le_writew, 1283f4932cfdSyangbo lu .write_b = esdhc_le_writeb, 1284f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1285f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1286f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1287f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1288f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1289f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1290f4932cfdSyangbo lu .reset = esdhc_reset, 129154e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1292b214fe59SYinbo Zhu .irq = esdhc_irq, 1293f4932cfdSyangbo lu }; 1294f4932cfdSyangbo lu 1295f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { 1296e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1297e9acc77dSyangbo lu #ifdef CONFIG_PPC 1298e9acc77dSyangbo lu SDHCI_QUIRK_BROKEN_CARD_DETECTION | 1299e9acc77dSyangbo lu #endif 1300e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1301e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1302f4932cfdSyangbo lu .ops = &sdhci_esdhc_be_ops, 13037657c3a7SAlbert Herranz }; 130438576af1SShawn Guo 1305f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = { 1306e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1307e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1308e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1309f4932cfdSyangbo lu .ops = &sdhci_esdhc_le_ops, 1310f4932cfdSyangbo lu }; 1311f4932cfdSyangbo lu 1312151ede40Syangbo lu static struct soc_device_attribute soc_incorrect_hostver[] = { 1313151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "1.0", }, 1314151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "2.0", }, 1315151ede40Syangbo lu { }, 1316151ede40Syangbo lu }; 1317151ede40Syangbo lu 13186079e63cSYangbo Lu static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = { 13196079e63cSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 13208e9a6919SYinbo Zhu { .family = "QorIQ LX2160A", .revision = "2.0", }, 13215f3ad196SYinbo Zhu { .family = "QorIQ LS1028A", .revision = "1.0", }, 13226079e63cSYangbo Lu { }, 13236079e63cSYangbo Lu }; 13246079e63cSYangbo Lu 132548e304ccSYangbo Lu static struct soc_device_attribute soc_unreliable_pulse_detection[] = { 132648e304ccSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 132748e304ccSYangbo Lu { }, 132848e304ccSYangbo Lu }; 132948e304ccSYangbo Lu 1330f4932cfdSyangbo lu static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) 1331f4932cfdSyangbo lu { 133267fdfbdfSyinbo.zhu const struct of_device_id *match; 1333f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host; 1334f4932cfdSyangbo lu struct sdhci_esdhc *esdhc; 133519c3a0efSyangbo lu struct device_node *np; 133619c3a0efSyangbo lu struct clk *clk; 133719c3a0efSyangbo lu u32 val; 1338f4932cfdSyangbo lu u16 host_ver; 1339f4932cfdSyangbo lu 1340f4932cfdSyangbo lu pltfm_host = sdhci_priv(host); 13418605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 1342f4932cfdSyangbo lu 1343f4932cfdSyangbo lu host_ver = sdhci_readw(host, SDHCI_HOST_VERSION); 1344f4932cfdSyangbo lu esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> 1345f4932cfdSyangbo lu SDHCI_VENDOR_VER_SHIFT; 1346f4932cfdSyangbo lu esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; 1347151ede40Syangbo lu if (soc_device_match(soc_incorrect_hostver)) 1348151ede40Syangbo lu esdhc->quirk_incorrect_hostver = true; 1349151ede40Syangbo lu else 1350151ede40Syangbo lu esdhc->quirk_incorrect_hostver = false; 135119c3a0efSyangbo lu 13526079e63cSYangbo Lu if (soc_device_match(soc_fixup_sdhc_clkdivs)) 13536079e63cSYangbo Lu esdhc->quirk_limited_clk_division = true; 13546079e63cSYangbo Lu else 13556079e63cSYangbo Lu esdhc->quirk_limited_clk_division = false; 13566079e63cSYangbo Lu 135748e304ccSYangbo Lu if (soc_device_match(soc_unreliable_pulse_detection)) 135848e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = true; 135948e304ccSYangbo Lu else 136048e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = false; 136148e304ccSYangbo Lu 136267fdfbdfSyinbo.zhu match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); 136367fdfbdfSyinbo.zhu if (match) 136467fdfbdfSyinbo.zhu esdhc->clk_fixup = match->data; 136519c3a0efSyangbo lu np = pdev->dev.of_node; 1366f667216cSYangbo Lu 1367060522d8SChris Packham if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 1368f667216cSYangbo Lu esdhc->quirk_delay_before_data_reset = true; 1369060522d8SChris Packham esdhc->quirk_trans_complete_erratum = true; 1370060522d8SChris Packham } 1371f667216cSYangbo Lu 137219c3a0efSyangbo lu clk = of_clk_get(np, 0); 137319c3a0efSyangbo lu if (!IS_ERR(clk)) { 137419c3a0efSyangbo lu /* 137519c3a0efSyangbo lu * esdhc->peripheral_clock would be assigned with a value 137619c3a0efSyangbo lu * which is eSDHC base clock when use periperal clock. 1377791463baSYangbo Lu * For some platforms, the clock value got by common clk 1378791463baSYangbo Lu * API is peripheral clock while the eSDHC base clock is 1379791463baSYangbo Lu * 1/2 peripheral clock. 138019c3a0efSyangbo lu */ 1381791463baSYangbo Lu if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || 138266a83febSYangbo Lu of_device_is_compatible(np, "fsl,ls1028a-esdhc") || 138366a83febSYangbo Lu of_device_is_compatible(np, "fsl,ls1088a-esdhc")) 138419c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk) / 2; 138519c3a0efSyangbo lu else 138619c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk); 138719c3a0efSyangbo lu 138819c3a0efSyangbo lu clk_put(clk); 138919c3a0efSyangbo lu } 139019c3a0efSyangbo lu 139119c3a0efSyangbo lu esdhc_clock_enable(host, false); 139219c3a0efSyangbo lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 1393975520fcSYangbo Lu /* 1394975520fcSYangbo Lu * This bit is not able to be reset by SDHCI_RESET_ALL. Need to 1395975520fcSYangbo Lu * initialize it as 1 or 0 once, to override the different value 1396975520fcSYangbo Lu * which may be configured in bootloader. 1397975520fcSYangbo Lu */ 1398975520fcSYangbo Lu if (esdhc->peripheral_clock) 139919c3a0efSyangbo lu val |= ESDHC_PERIPHERAL_CLK_SEL; 1400975520fcSYangbo Lu else 1401975520fcSYangbo Lu val &= ~ESDHC_PERIPHERAL_CLK_SEL; 140219c3a0efSyangbo lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 140319c3a0efSyangbo lu esdhc_clock_enable(host, true); 140419c3a0efSyangbo lu } 1405f4932cfdSyangbo lu 140654e08d9aSYangbo Lu static int esdhc_hs400_prepare_ddr(struct mmc_host *mmc) 140754e08d9aSYangbo Lu { 140854e08d9aSYangbo Lu esdhc_tuning_block_enable(mmc_priv(mmc), false); 140954e08d9aSYangbo Lu return 0; 141054e08d9aSYangbo Lu } 141154e08d9aSYangbo Lu 1412c3be1efdSBill Pemberton static int sdhci_esdhc_probe(struct platform_device *pdev) 141338576af1SShawn Guo { 141466b50a00SOded Gabbay struct sdhci_host *host; 1415dcaff04dSOded Gabbay struct device_node *np; 14161ef5e49eSyangbo lu struct sdhci_pltfm_host *pltfm_host; 14171ef5e49eSyangbo lu struct sdhci_esdhc *esdhc; 141866b50a00SOded Gabbay int ret; 141966b50a00SOded Gabbay 1420f4932cfdSyangbo lu np = pdev->dev.of_node; 1421f4932cfdSyangbo lu 1422150d4240SJulia Lawall if (of_property_read_bool(np, "little-endian")) 14238605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, 14248605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1425f4932cfdSyangbo lu else 14268605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, 14278605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1428f4932cfdSyangbo lu 142966b50a00SOded Gabbay if (IS_ERR(host)) 143066b50a00SOded Gabbay return PTR_ERR(host); 143166b50a00SOded Gabbay 1432ea35645aSyangbo lu host->mmc_host_ops.start_signal_voltage_switch = 1433ea35645aSyangbo lu esdhc_signal_voltage_switch; 1434ba49cbd0Syangbo lu host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; 143554e08d9aSYangbo Lu host->mmc_host_ops.hs400_prepare_ddr = esdhc_hs400_prepare_ddr; 14366b236f37Syangbo lu host->tuning_delay = 1; 1437ea35645aSyangbo lu 1438f4932cfdSyangbo lu esdhc_init(pdev, host); 1439f4932cfdSyangbo lu 144066b50a00SOded Gabbay sdhci_get_of_property(pdev); 144166b50a00SOded Gabbay 14421ef5e49eSyangbo lu pltfm_host = sdhci_priv(host); 14438605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 144422dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type1)) 144522dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = true; 1446b1f378abSYinbo Zhu else 144722dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = false; 144822dc132dSYangbo Lu 144922dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type2)) 145022dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = true; 145122dc132dSYangbo Lu else 145222dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = false; 1453b1f378abSYinbo Zhu 14541ef5e49eSyangbo lu if (esdhc->vendor_ver == VENDOR_V_22) 14551ef5e49eSyangbo lu host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; 14561ef5e49eSyangbo lu 14571ef5e49eSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) 14581ef5e49eSyangbo lu host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; 14591ef5e49eSyangbo lu 146005cb6b2aSYinbo Zhu if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { 1461fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; 1462fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 146305cb6b2aSYinbo Zhu } 1464a46e4271SYinbo Zhu 146574fd5e30SYangbo Lu if (of_device_is_compatible(np, "fsl,p5040-esdhc") || 146674fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p5020-esdhc") || 146774fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p4080-esdhc") || 146874fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p1020-esdhc") || 1469e9acc77dSyangbo lu of_device_is_compatible(np, "fsl,t1040-esdhc")) 147074fd5e30SYangbo Lu host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; 147174fd5e30SYangbo Lu 1472a22950c8Syangbo lu if (of_device_is_compatible(np, "fsl,ls1021a-esdhc")) 1473a22950c8Syangbo lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 1474a22950c8Syangbo lu 14751f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = false; 1476dcaff04dSOded Gabbay if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 1477dcaff04dSOded Gabbay /* 1478dcaff04dSOded Gabbay * Freescale messed up with P2020 as it has a non-standard 1479dcaff04dSOded Gabbay * host control register 1480dcaff04dSOded Gabbay */ 1481dcaff04dSOded Gabbay host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; 14821f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = true; 1483dcaff04dSOded Gabbay } 1484dcaff04dSOded Gabbay 148566b50a00SOded Gabbay /* call to generic mmc_of_parse to support additional capabilities */ 1486f0991408SUlf Hansson ret = mmc_of_parse(host->mmc); 1487f0991408SUlf Hansson if (ret) 1488f0991408SUlf Hansson goto err; 1489f0991408SUlf Hansson 1490490104acSHaijun Zhang mmc_of_parse_voltage(np, &host->ocr_mask); 149166b50a00SOded Gabbay 149266b50a00SOded Gabbay ret = sdhci_add_host(host); 149366b50a00SOded Gabbay if (ret) 1494f0991408SUlf Hansson goto err; 149566b50a00SOded Gabbay 1496f0991408SUlf Hansson return 0; 1497f0991408SUlf Hansson err: 1498f0991408SUlf Hansson sdhci_pltfm_free(pdev); 149966b50a00SOded Gabbay return ret; 150038576af1SShawn Guo } 150138576af1SShawn Guo 150238576af1SShawn Guo static struct platform_driver sdhci_esdhc_driver = { 150338576af1SShawn Guo .driver = { 150438576af1SShawn Guo .name = "sdhci-esdhc", 150521b2cec6SDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS, 150638576af1SShawn Guo .of_match_table = sdhci_esdhc_of_match, 15079e48b336SUlf Hansson .pm = &esdhc_of_dev_pm_ops, 150838576af1SShawn Guo }, 150938576af1SShawn Guo .probe = sdhci_esdhc_probe, 1510caebcae9SKevin Hao .remove = sdhci_pltfm_unregister, 151138576af1SShawn Guo }; 151238576af1SShawn Guo 1513d1f81a64SAxel Lin module_platform_driver(sdhci_esdhc_driver); 151438576af1SShawn Guo 151538576af1SShawn Guo MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); 151638576af1SShawn Guo MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " 151738576af1SShawn Guo "Anton Vorontsov <avorontsov@ru.mvista.com>"); 151838576af1SShawn Guo MODULE_LICENSE("GPL v2"); 1519