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. 7011fde48SYangbo 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> 23011fde48SYangbo 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 45c8d2d76dSAndy Tang static const struct esdhc_clk_fixup ls1043a_esdhc_clk = { 46c8d2d76dSAndy Tang .sd_dflt_max_clk = 25000000, 47c8d2d76dSAndy Tang .max_clk[MMC_TIMING_UHS_SDR104] = 116700000, 48c8d2d76dSAndy Tang .max_clk[MMC_TIMING_MMC_HS200] = 116700000, 49c8d2d76dSAndy Tang }; 50c8d2d76dSAndy Tang 5167fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup ls1046a_esdhc_clk = { 5267fdfbdfSyinbo.zhu .sd_dflt_max_clk = 25000000, 5367fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_UHS_SDR104] = 167000000, 5467fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS200] = 167000000, 5567fdfbdfSyinbo.zhu }; 5667fdfbdfSyinbo.zhu 5767fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup ls1012a_esdhc_clk = { 5867fdfbdfSyinbo.zhu .sd_dflt_max_clk = 25000000, 5967fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_UHS_SDR104] = 125000000, 6067fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS200] = 125000000, 6167fdfbdfSyinbo.zhu }; 6267fdfbdfSyinbo.zhu 6367fdfbdfSyinbo.zhu static const struct esdhc_clk_fixup p1010_esdhc_clk = { 6467fdfbdfSyinbo.zhu .sd_dflt_max_clk = 20000000, 6567fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_LEGACY] = 20000000, 6667fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_MMC_HS] = 42000000, 6767fdfbdfSyinbo.zhu .max_clk[MMC_TIMING_SD_HS] = 40000000, 6867fdfbdfSyinbo.zhu }; 6967fdfbdfSyinbo.zhu 7067fdfbdfSyinbo.zhu static const struct of_device_id sdhci_esdhc_of_match[] = { 7167fdfbdfSyinbo.zhu { .compatible = "fsl,ls1021a-esdhc", .data = &ls1021a_esdhc_clk}, 72c8d2d76dSAndy Tang { .compatible = "fsl,ls1043a-esdhc", .data = &ls1043a_esdhc_clk}, 7367fdfbdfSyinbo.zhu { .compatible = "fsl,ls1046a-esdhc", .data = &ls1046a_esdhc_clk}, 7467fdfbdfSyinbo.zhu { .compatible = "fsl,ls1012a-esdhc", .data = &ls1012a_esdhc_clk}, 7567fdfbdfSyinbo.zhu { .compatible = "fsl,p1010-esdhc", .data = &p1010_esdhc_clk}, 7667fdfbdfSyinbo.zhu { .compatible = "fsl,mpc8379-esdhc" }, 7767fdfbdfSyinbo.zhu { .compatible = "fsl,mpc8536-esdhc" }, 7867fdfbdfSyinbo.zhu { .compatible = "fsl,esdhc" }, 7967fdfbdfSyinbo.zhu { } 8067fdfbdfSyinbo.zhu }; 8167fdfbdfSyinbo.zhu MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match); 8267fdfbdfSyinbo.zhu 83f4932cfdSyangbo lu struct sdhci_esdhc { 84f4932cfdSyangbo lu u8 vendor_ver; 85f4932cfdSyangbo lu u8 spec_ver; 86151ede40Syangbo lu bool quirk_incorrect_hostver; 876079e63cSYangbo Lu bool quirk_limited_clk_division; 8848e304ccSYangbo Lu bool quirk_unreliable_pulse_detection; 8922dc132dSYangbo Lu bool quirk_tuning_erratum_type1; 9022dc132dSYangbo Lu bool quirk_tuning_erratum_type2; 911f1929f3SYangbo Lu bool quirk_ignore_data_inhibit; 92f667216cSYangbo Lu bool quirk_delay_before_data_reset; 93060522d8SChris Packham bool quirk_trans_complete_erratum; 9422dc132dSYangbo Lu bool in_sw_tuning; 9519c3a0efSyangbo lu unsigned int peripheral_clock; 9667fdfbdfSyinbo.zhu const struct esdhc_clk_fixup *clk_fixup; 97b1f378abSYinbo Zhu u32 div_ratio; 98f4932cfdSyangbo lu }; 99f4932cfdSyangbo lu 100f4932cfdSyangbo lu /** 10119dafe9cSJiapeng Chong * esdhc_readl_fixup - Fixup the value read from incompatible eSDHC register 102f4932cfdSyangbo lu * to make it compatible with SD spec. 103f4932cfdSyangbo lu * 104f4932cfdSyangbo lu * @host: pointer to sdhci_host 105f4932cfdSyangbo lu * @spec_reg: SD spec register address 106f4932cfdSyangbo lu * @value: 32bit eSDHC register value on spec_reg address 107f4932cfdSyangbo lu * 108f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 109f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 110f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 111f4932cfdSyangbo lu * and SD spec. 112f4932cfdSyangbo lu * 113f4932cfdSyangbo lu * Return a fixed up register value 114f4932cfdSyangbo lu */ 115f4932cfdSyangbo lu static u32 esdhc_readl_fixup(struct sdhci_host *host, 116f4932cfdSyangbo lu int spec_reg, u32 value) 117137ccd46SJerry Huang { 118f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1198605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 120137ccd46SJerry Huang u32 ret; 121137ccd46SJerry Huang 122137ccd46SJerry Huang /* 123137ccd46SJerry Huang * The bit of ADMA flag in eSDHC is not compatible with standard 124137ccd46SJerry Huang * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is 125137ccd46SJerry Huang * supported by eSDHC. 126137ccd46SJerry Huang * And for many FSL eSDHC controller, the reset value of field 127f4932cfdSyangbo lu * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA, 128137ccd46SJerry Huang * only these vendor version is greater than 2.2/0x12 support ADMA. 129137ccd46SJerry Huang */ 130f4932cfdSyangbo lu if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) { 131f4932cfdSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) { 132f4932cfdSyangbo lu ret = value | SDHCI_CAN_DO_ADMA2; 133f4932cfdSyangbo lu return ret; 134137ccd46SJerry Huang } 135f4932cfdSyangbo lu } 1360dd83160SGeorgii Kruglov 137b0921d5cSMichael Walle /* 138b0921d5cSMichael Walle * The DAT[3:0] line signal levels and the CMD line signal level are 139b0921d5cSMichael Walle * not compatible with standard SDHC register. The line signal levels 140b0921d5cSMichael Walle * DAT[7:0] are at bits 31:24 and the command line signal level is at 141b0921d5cSMichael Walle * bit 23. All other bits are the same as in the standard SDHC 142b0921d5cSMichael Walle * register. 143b0921d5cSMichael Walle */ 144b0921d5cSMichael Walle if (spec_reg == SDHCI_PRESENT_STATE) { 145b0921d5cSMichael Walle ret = value & 0x000fffff; 146b0921d5cSMichael Walle ret |= (value >> 4) & SDHCI_DATA_LVL_MASK; 147b0921d5cSMichael Walle ret |= (value << 1) & SDHCI_CMD_LVL; 1480dd83160SGeorgii Kruglov 1490dd83160SGeorgii Kruglov /* 1500dd83160SGeorgii Kruglov * Some controllers have unreliable Data Line Active 1510dd83160SGeorgii Kruglov * bit for commands with busy signal. This affects 1520dd83160SGeorgii Kruglov * Command Inhibit (data) bit. Just ignore it since 1530dd83160SGeorgii Kruglov * MMC core driver has already polled card status 1540dd83160SGeorgii Kruglov * with CMD13 after any command with busy siganl. 1550dd83160SGeorgii Kruglov */ 1560dd83160SGeorgii Kruglov if (esdhc->quirk_ignore_data_inhibit) 1570dd83160SGeorgii Kruglov ret &= ~SDHCI_DATA_INHIBIT; 158b0921d5cSMichael Walle return ret; 159b0921d5cSMichael Walle } 160b0921d5cSMichael Walle 1612f3110ccSyangbo lu /* 1622f3110ccSyangbo lu * DTS properties of mmc host are used to enable each speed mode 1632f3110ccSyangbo lu * according to soc and board capability. So clean up 1642f3110ccSyangbo lu * SDR50/SDR104/DDR50 support bits here. 1652f3110ccSyangbo lu */ 1662f3110ccSyangbo lu if (spec_reg == SDHCI_CAPABILITIES_1) { 1672f3110ccSyangbo lu ret = value & ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | 1682f3110ccSyangbo lu SDHCI_SUPPORT_DDR50); 1692f3110ccSyangbo lu return ret; 1702f3110ccSyangbo lu } 1712f3110ccSyangbo lu 172f4932cfdSyangbo lu ret = value; 173137ccd46SJerry Huang return ret; 174137ccd46SJerry Huang } 175137ccd46SJerry Huang 176f4932cfdSyangbo lu static u16 esdhc_readw_fixup(struct sdhci_host *host, 177f4932cfdSyangbo lu int spec_reg, u32 value) 1787657c3a7SAlbert Herranz { 179151ede40Syangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 180151ede40Syangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1817657c3a7SAlbert Herranz u16 ret; 182f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 1837657c3a7SAlbert Herranz 184429d939cSYangbo Lu if (spec_reg == SDHCI_TRANSFER_MODE) 185429d939cSYangbo Lu return pltfm_host->xfer_mode_shadow; 186429d939cSYangbo Lu 187f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_VERSION) 188f4932cfdSyangbo lu ret = value & 0xffff; 1897657c3a7SAlbert Herranz else 190f4932cfdSyangbo lu ret = (value >> shift) & 0xffff; 191151ede40Syangbo lu /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect 192151ede40Syangbo lu * vendor version and spec version information. 193151ede40Syangbo lu */ 194151ede40Syangbo lu if ((spec_reg == SDHCI_HOST_VERSION) && 195151ede40Syangbo lu (esdhc->quirk_incorrect_hostver)) 196151ede40Syangbo lu ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200; 197e51cbc9eSXu lei return ret; 198e51cbc9eSXu lei } 199e51cbc9eSXu lei 200f4932cfdSyangbo lu static u8 esdhc_readb_fixup(struct sdhci_host *host, 201f4932cfdSyangbo lu int spec_reg, u32 value) 202e51cbc9eSXu lei { 203f4932cfdSyangbo lu u8 ret; 204f4932cfdSyangbo lu u8 dma_bits; 205f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 206f4932cfdSyangbo lu 207f4932cfdSyangbo lu ret = (value >> shift) & 0xff; 208ba8c4dc9SRoy Zang 209ba8c4dc9SRoy Zang /* 210ba8c4dc9SRoy Zang * "DMA select" locates at offset 0x28 in SD specification, but on 211ba8c4dc9SRoy Zang * P5020 or P3041, it locates at 0x29. 212ba8c4dc9SRoy Zang */ 213f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 214ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 215f4932cfdSyangbo lu dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK; 216ba8c4dc9SRoy Zang /* fixup the result */ 217ba8c4dc9SRoy Zang ret &= ~SDHCI_CTRL_DMA_MASK; 218ba8c4dc9SRoy Zang ret |= dma_bits; 219ba8c4dc9SRoy Zang } 220f4932cfdSyangbo lu return ret; 221f4932cfdSyangbo lu } 222f4932cfdSyangbo lu 223f4932cfdSyangbo lu /** 22419dafe9cSJiapeng Chong * esdhc_writel_fixup - Fixup the SD spec register value so that it could be 225f4932cfdSyangbo lu * written into eSDHC register. 226f4932cfdSyangbo lu * 227f4932cfdSyangbo lu * @host: pointer to sdhci_host 228f4932cfdSyangbo lu * @spec_reg: SD spec register address 229f4932cfdSyangbo lu * @value: 8/16/32bit SD spec register value that would be written 230f4932cfdSyangbo lu * @old_value: 32bit eSDHC register value on spec_reg address 231f4932cfdSyangbo lu * 232f4932cfdSyangbo lu * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC 233f4932cfdSyangbo lu * registers are 32 bits. There are differences in register size, register 234f4932cfdSyangbo lu * address, register function, bit position and function between eSDHC spec 235f4932cfdSyangbo lu * and SD spec. 236f4932cfdSyangbo lu * 237f4932cfdSyangbo lu * Return a fixed up register value 238f4932cfdSyangbo lu */ 239f4932cfdSyangbo lu static u32 esdhc_writel_fixup(struct sdhci_host *host, 240f4932cfdSyangbo lu int spec_reg, u32 value, u32 old_value) 241f4932cfdSyangbo lu { 242f4932cfdSyangbo lu u32 ret; 243f4932cfdSyangbo lu 244f4932cfdSyangbo lu /* 245f4932cfdSyangbo lu * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] 246f4932cfdSyangbo lu * when SYSCTL[RSTD] is set for some special operations. 247f4932cfdSyangbo lu * No any impact on other operation. 248f4932cfdSyangbo lu */ 249f4932cfdSyangbo lu if (spec_reg == SDHCI_INT_ENABLE) 250f4932cfdSyangbo lu ret = value | SDHCI_INT_BLK_GAP; 251f4932cfdSyangbo lu else 252f4932cfdSyangbo lu ret = value; 253ba8c4dc9SRoy Zang 2547657c3a7SAlbert Herranz return ret; 2557657c3a7SAlbert Herranz } 2567657c3a7SAlbert Herranz 257f4932cfdSyangbo lu static u32 esdhc_writew_fixup(struct sdhci_host *host, 258f4932cfdSyangbo lu int spec_reg, u16 value, u32 old_value) 259a4071fbbSHaijun Zhang { 260f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 261f4932cfdSyangbo lu int shift = (spec_reg & 0x2) * 8; 262f4932cfdSyangbo lu u32 ret; 263f4932cfdSyangbo lu 264f4932cfdSyangbo lu switch (spec_reg) { 265f4932cfdSyangbo lu case SDHCI_TRANSFER_MODE: 266a4071fbbSHaijun Zhang /* 267f4932cfdSyangbo lu * Postpone this write, we must do it together with a 268f4932cfdSyangbo lu * command write that is down below. Return old value. 269a4071fbbSHaijun Zhang */ 270f4932cfdSyangbo lu pltfm_host->xfer_mode_shadow = value; 271f4932cfdSyangbo lu return old_value; 272f4932cfdSyangbo lu case SDHCI_COMMAND: 273f4932cfdSyangbo lu ret = (value << 16) | pltfm_host->xfer_mode_shadow; 274f4932cfdSyangbo lu return ret; 275a4071fbbSHaijun Zhang } 276a4071fbbSHaijun Zhang 277f4932cfdSyangbo lu ret = old_value & (~(0xffff << shift)); 278f4932cfdSyangbo lu ret |= (value << shift); 279f4932cfdSyangbo lu 280f4932cfdSyangbo lu if (spec_reg == SDHCI_BLOCK_SIZE) { 2817657c3a7SAlbert Herranz /* 2827657c3a7SAlbert Herranz * Two last DMA bits are reserved, and first one is used for 2837657c3a7SAlbert Herranz * non-standard blksz of 4096 bytes that we don't support 2847657c3a7SAlbert Herranz * yet. So clear the DMA boundary bits. 2857657c3a7SAlbert Herranz */ 286f4932cfdSyangbo lu ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0)); 2877657c3a7SAlbert Herranz } 288f4932cfdSyangbo lu return ret; 2897657c3a7SAlbert Herranz } 2907657c3a7SAlbert Herranz 291f4932cfdSyangbo lu static u32 esdhc_writeb_fixup(struct sdhci_host *host, 292f4932cfdSyangbo lu int spec_reg, u8 value, u32 old_value) 2937657c3a7SAlbert Herranz { 294f4932cfdSyangbo lu u32 ret; 295f4932cfdSyangbo lu u32 dma_bits; 296f4932cfdSyangbo lu u8 tmp; 297f4932cfdSyangbo lu int shift = (spec_reg & 0x3) * 8; 298f4932cfdSyangbo lu 299ba8c4dc9SRoy Zang /* 3009e4703dfSyangbo lu * eSDHC doesn't have a standard power control register, so we do 3019e4703dfSyangbo lu * nothing here to avoid incorrect operation. 3029e4703dfSyangbo lu */ 3039e4703dfSyangbo lu if (spec_reg == SDHCI_POWER_CONTROL) 3049e4703dfSyangbo lu return old_value; 3059e4703dfSyangbo lu /* 306ba8c4dc9SRoy Zang * "DMA select" location is offset 0x28 in SD specification, but on 307ba8c4dc9SRoy Zang * P5020 or P3041, it's located at 0x29. 308ba8c4dc9SRoy Zang */ 309f4932cfdSyangbo lu if (spec_reg == SDHCI_HOST_CONTROL) { 310dcaff04dSOded Gabbay /* 311dcaff04dSOded Gabbay * If host control register is not standard, exit 312dcaff04dSOded Gabbay * this function 313dcaff04dSOded Gabbay */ 314dcaff04dSOded Gabbay if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) 315f4932cfdSyangbo lu return old_value; 316dcaff04dSOded Gabbay 317ba8c4dc9SRoy Zang /* DMA select is 22,23 bits in Protocol Control Register */ 318f4932cfdSyangbo lu dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5; 319f4932cfdSyangbo lu ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits; 320f4932cfdSyangbo lu tmp = (value & (~SDHCI_CTRL_DMA_MASK)) | 321f4932cfdSyangbo lu (old_value & SDHCI_CTRL_DMA_MASK); 322f4932cfdSyangbo lu ret = (ret & (~0xff)) | tmp; 323f4932cfdSyangbo lu 324f4932cfdSyangbo lu /* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */ 325f4932cfdSyangbo lu ret &= ~ESDHC_HOST_CONTROL_RES; 326f4932cfdSyangbo lu return ret; 327ba8c4dc9SRoy Zang } 328ba8c4dc9SRoy Zang 329f4932cfdSyangbo lu ret = (old_value & (~(0xff << shift))) | (value << shift); 330f4932cfdSyangbo lu return ret; 331f4932cfdSyangbo lu } 332f4932cfdSyangbo lu 333f4932cfdSyangbo lu static u32 esdhc_be_readl(struct sdhci_host *host, int reg) 334f4932cfdSyangbo lu { 335f4932cfdSyangbo lu u32 ret; 336f4932cfdSyangbo lu u32 value; 337f4932cfdSyangbo lu 3382f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3392f3110ccSyangbo lu value = ioread32be(host->ioaddr + ESDHC_CAPABILITIES_1); 3402f3110ccSyangbo lu else 341f4932cfdSyangbo lu value = ioread32be(host->ioaddr + reg); 3422f3110ccSyangbo lu 343f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 344f4932cfdSyangbo lu 345f4932cfdSyangbo lu return ret; 346f4932cfdSyangbo lu } 347f4932cfdSyangbo lu 348f4932cfdSyangbo lu static u32 esdhc_le_readl(struct sdhci_host *host, int reg) 349f4932cfdSyangbo lu { 350f4932cfdSyangbo lu u32 ret; 351f4932cfdSyangbo lu u32 value; 352f4932cfdSyangbo lu 3532f3110ccSyangbo lu if (reg == SDHCI_CAPABILITIES_1) 3542f3110ccSyangbo lu value = ioread32(host->ioaddr + ESDHC_CAPABILITIES_1); 3552f3110ccSyangbo lu else 356f4932cfdSyangbo lu value = ioread32(host->ioaddr + reg); 3572f3110ccSyangbo lu 358f4932cfdSyangbo lu ret = esdhc_readl_fixup(host, reg, value); 359f4932cfdSyangbo lu 360f4932cfdSyangbo lu return ret; 361f4932cfdSyangbo lu } 362f4932cfdSyangbo lu 363f4932cfdSyangbo lu static u16 esdhc_be_readw(struct sdhci_host *host, int reg) 364f4932cfdSyangbo lu { 365f4932cfdSyangbo lu u16 ret; 366f4932cfdSyangbo lu u32 value; 367f4932cfdSyangbo lu int base = reg & ~0x3; 368f4932cfdSyangbo lu 369f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 370f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 371f4932cfdSyangbo lu return ret; 372f4932cfdSyangbo lu } 373f4932cfdSyangbo lu 374f4932cfdSyangbo lu static u16 esdhc_le_readw(struct sdhci_host *host, int reg) 375f4932cfdSyangbo lu { 376f4932cfdSyangbo lu u16 ret; 377f4932cfdSyangbo lu u32 value; 378f4932cfdSyangbo lu int base = reg & ~0x3; 379f4932cfdSyangbo lu 380f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 381f4932cfdSyangbo lu ret = esdhc_readw_fixup(host, reg, value); 382f4932cfdSyangbo lu return ret; 383f4932cfdSyangbo lu } 384f4932cfdSyangbo lu 385f4932cfdSyangbo lu static u8 esdhc_be_readb(struct sdhci_host *host, int reg) 386f4932cfdSyangbo lu { 387f4932cfdSyangbo lu u8 ret; 388f4932cfdSyangbo lu u32 value; 389f4932cfdSyangbo lu int base = reg & ~0x3; 390f4932cfdSyangbo lu 391f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 392f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 393f4932cfdSyangbo lu return ret; 394f4932cfdSyangbo lu } 395f4932cfdSyangbo lu 396f4932cfdSyangbo lu static u8 esdhc_le_readb(struct sdhci_host *host, int reg) 397f4932cfdSyangbo lu { 398f4932cfdSyangbo lu u8 ret; 399f4932cfdSyangbo lu u32 value; 400f4932cfdSyangbo lu int base = reg & ~0x3; 401f4932cfdSyangbo lu 402f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 403f4932cfdSyangbo lu ret = esdhc_readb_fixup(host, reg, value); 404f4932cfdSyangbo lu return ret; 405f4932cfdSyangbo lu } 406f4932cfdSyangbo lu 407f4932cfdSyangbo lu static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg) 408f4932cfdSyangbo lu { 409f4932cfdSyangbo lu u32 value; 410f4932cfdSyangbo lu 411f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 412f4932cfdSyangbo lu iowrite32be(value, host->ioaddr + reg); 413f4932cfdSyangbo lu } 414f4932cfdSyangbo lu 415f4932cfdSyangbo lu static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg) 416f4932cfdSyangbo lu { 417f4932cfdSyangbo lu u32 value; 418f4932cfdSyangbo lu 419f4932cfdSyangbo lu value = esdhc_writel_fixup(host, reg, val, 0); 420f4932cfdSyangbo lu iowrite32(value, host->ioaddr + reg); 421f4932cfdSyangbo lu } 422f4932cfdSyangbo lu 423f4932cfdSyangbo lu static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg) 424f4932cfdSyangbo lu { 42522dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 42622dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 427f4932cfdSyangbo lu int base = reg & ~0x3; 428f4932cfdSyangbo lu u32 value; 429f4932cfdSyangbo lu u32 ret; 430f4932cfdSyangbo lu 431f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 432f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 433f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 434f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 43522dc132dSYangbo Lu 43622dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 43722dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 43822dc132dSYangbo Lu */ 43922dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 44022dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 44122dc132dSYangbo Lu esdhc->in_sw_tuning) { 44222dc132dSYangbo Lu udelay(1); 44322dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 44422dc132dSYangbo Lu iowrite32be(ret, host->ioaddr + base); 44522dc132dSYangbo Lu } 44622dc132dSYangbo Lu } 447f4932cfdSyangbo lu } 448f4932cfdSyangbo lu 449f4932cfdSyangbo lu static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg) 450f4932cfdSyangbo lu { 45122dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 45222dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 453f4932cfdSyangbo lu int base = reg & ~0x3; 454f4932cfdSyangbo lu u32 value; 455f4932cfdSyangbo lu u32 ret; 456f4932cfdSyangbo lu 457f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 458f4932cfdSyangbo lu ret = esdhc_writew_fixup(host, reg, val, value); 459f4932cfdSyangbo lu if (reg != SDHCI_TRANSFER_MODE) 460f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 46122dc132dSYangbo Lu 46222dc132dSYangbo Lu /* Starting SW tuning requires ESDHC_SMPCLKSEL to be set 46322dc132dSYangbo Lu * 1us later after ESDHC_EXTN is set. 46422dc132dSYangbo Lu */ 46522dc132dSYangbo Lu if (base == ESDHC_SYSTEM_CONTROL_2) { 46622dc132dSYangbo Lu if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) && 46722dc132dSYangbo Lu esdhc->in_sw_tuning) { 46822dc132dSYangbo Lu udelay(1); 46922dc132dSYangbo Lu ret |= ESDHC_SMPCLKSEL; 47022dc132dSYangbo Lu iowrite32(ret, host->ioaddr + base); 47122dc132dSYangbo Lu } 47222dc132dSYangbo Lu } 473f4932cfdSyangbo lu } 474f4932cfdSyangbo lu 475f4932cfdSyangbo lu static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg) 476f4932cfdSyangbo lu { 477f4932cfdSyangbo lu int base = reg & ~0x3; 478f4932cfdSyangbo lu u32 value; 479f4932cfdSyangbo lu u32 ret; 480f4932cfdSyangbo lu 481f4932cfdSyangbo lu value = ioread32be(host->ioaddr + base); 482f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 483f4932cfdSyangbo lu iowrite32be(ret, host->ioaddr + base); 484f4932cfdSyangbo lu } 485f4932cfdSyangbo lu 486f4932cfdSyangbo lu static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg) 487f4932cfdSyangbo lu { 488f4932cfdSyangbo lu int base = reg & ~0x3; 489f4932cfdSyangbo lu u32 value; 490f4932cfdSyangbo lu u32 ret; 491f4932cfdSyangbo lu 492f4932cfdSyangbo lu value = ioread32(host->ioaddr + base); 493f4932cfdSyangbo lu ret = esdhc_writeb_fixup(host, reg, val, value); 494f4932cfdSyangbo lu iowrite32(ret, host->ioaddr + base); 4957657c3a7SAlbert Herranz } 4967657c3a7SAlbert Herranz 497a4071fbbSHaijun Zhang /* 498a4071fbbSHaijun Zhang * For Abort or Suspend after Stop at Block Gap, ignore the ADMA 499a4071fbbSHaijun Zhang * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) 500a4071fbbSHaijun Zhang * and Block Gap Event(IRQSTAT[BGE]) are also set. 501a4071fbbSHaijun Zhang * For Continue, apply soft reset for data(SYSCTL[RSTD]); 502a4071fbbSHaijun Zhang * and re-issue the entire read transaction from beginning. 503a4071fbbSHaijun Zhang */ 504f4932cfdSyangbo lu static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) 505a4071fbbSHaijun Zhang { 506f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 5078605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 508a4071fbbSHaijun Zhang bool applicable; 509a4071fbbSHaijun Zhang dma_addr_t dmastart; 510a4071fbbSHaijun Zhang dma_addr_t dmanow; 511a4071fbbSHaijun Zhang 512a4071fbbSHaijun Zhang applicable = (intmask & SDHCI_INT_DATA_END) && 513a4071fbbSHaijun Zhang (intmask & SDHCI_INT_BLK_GAP) && 514f4932cfdSyangbo lu (esdhc->vendor_ver == VENDOR_V_23); 515a4071fbbSHaijun Zhang if (!applicable) 516a4071fbbSHaijun Zhang return; 517a4071fbbSHaijun Zhang 518a4071fbbSHaijun Zhang host->data->error = 0; 519a4071fbbSHaijun Zhang dmastart = sg_dma_address(host->data->sg); 520a4071fbbSHaijun Zhang dmanow = dmastart + host->data->bytes_xfered; 521a4071fbbSHaijun Zhang /* 522a4071fbbSHaijun Zhang * Force update to the next DMA block boundary. 523a4071fbbSHaijun Zhang */ 524a4071fbbSHaijun Zhang dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + 525a4071fbbSHaijun Zhang SDHCI_DEFAULT_BOUNDARY_SIZE; 526a4071fbbSHaijun Zhang host->data->bytes_xfered = dmanow - dmastart; 527a4071fbbSHaijun Zhang sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); 528a4071fbbSHaijun Zhang } 529a4071fbbSHaijun Zhang 53080872e21SWolfram Sang static int esdhc_of_enable_dma(struct sdhci_host *host) 5317657c3a7SAlbert Herranz { 53240c67c29SJiasheng Jiang int ret; 533f4932cfdSyangbo lu u32 value; 5345552d7adSLaurentiu Tudor struct device *dev = mmc_dev(host->mmc); 5355552d7adSLaurentiu Tudor 5365552d7adSLaurentiu Tudor if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || 53740c67c29SJiasheng Jiang of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) { 53840c67c29SJiasheng Jiang ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); 53940c67c29SJiasheng Jiang if (ret) 54040c67c29SJiasheng Jiang return ret; 54140c67c29SJiasheng Jiang } 542f4932cfdSyangbo lu 543f4932cfdSyangbo lu value = sdhci_readl(host, ESDHC_DMA_SYSCTL); 544121bd08bSRussell King 545121bd08bSRussell King if (of_dma_is_coherent(dev->of_node)) 546f4932cfdSyangbo lu value |= ESDHC_DMA_SNOOP; 547121bd08bSRussell King else 548121bd08bSRussell King value &= ~ESDHC_DMA_SNOOP; 549121bd08bSRussell King 550f4932cfdSyangbo lu sdhci_writel(host, value, ESDHC_DMA_SYSCTL); 5517657c3a7SAlbert Herranz return 0; 5527657c3a7SAlbert Herranz } 5537657c3a7SAlbert Herranz 55480872e21SWolfram Sang static unsigned int esdhc_of_get_max_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); 5587657c3a7SAlbert Herranz 55919c3a0efSyangbo lu if (esdhc->peripheral_clock) 56019c3a0efSyangbo lu return esdhc->peripheral_clock; 56119c3a0efSyangbo lu else 562e307148fSShawn Guo return pltfm_host->clock; 5637657c3a7SAlbert Herranz } 5647657c3a7SAlbert Herranz 56580872e21SWolfram Sang static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) 5667657c3a7SAlbert Herranz { 567e307148fSShawn Guo struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 56819c3a0efSyangbo lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 56919c3a0efSyangbo lu unsigned int clock; 5707657c3a7SAlbert Herranz 57119c3a0efSyangbo lu if (esdhc->peripheral_clock) 57219c3a0efSyangbo lu clock = esdhc->peripheral_clock; 57319c3a0efSyangbo lu else 57419c3a0efSyangbo lu clock = pltfm_host->clock; 57519c3a0efSyangbo lu return clock / 256 / 16; 5767657c3a7SAlbert Herranz } 5777657c3a7SAlbert Herranz 578dd3f6983Syangbo lu static void esdhc_clock_enable(struct sdhci_host *host, bool enable) 579dd3f6983Syangbo lu { 5801b21a701SYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 5811b21a701SYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 582dd3f6983Syangbo lu ktime_t timeout; 5831b21a701SYangbo Lu u32 val, clk_en; 5841b21a701SYangbo Lu 5851b21a701SYangbo Lu clk_en = ESDHC_CLOCK_SDCLKEN; 5861b21a701SYangbo Lu 5871b21a701SYangbo Lu /* 5881b21a701SYangbo Lu * IPGEN/HCKEN/PEREN bits exist on eSDHC whose vendor version 5891b21a701SYangbo Lu * is 2.2 or lower. 5901b21a701SYangbo Lu */ 5911b21a701SYangbo Lu if (esdhc->vendor_ver <= VENDOR_V_22) 5921b21a701SYangbo Lu clk_en |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | 5931b21a701SYangbo Lu ESDHC_CLOCK_PEREN); 594dd3f6983Syangbo lu 595dd3f6983Syangbo lu val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 596dd3f6983Syangbo lu 597dd3f6983Syangbo lu if (enable) 5981b21a701SYangbo Lu val |= clk_en; 599dd3f6983Syangbo lu else 6001b21a701SYangbo Lu val &= ~clk_en; 601dd3f6983Syangbo lu 602dd3f6983Syangbo lu sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL); 603dd3f6983Syangbo lu 6041b21a701SYangbo Lu /* 6051b21a701SYangbo Lu * Wait max 20 ms. If vendor version is 2.2 or lower, do not 6061b21a701SYangbo Lu * wait clock stable bit which does not exist. 6071b21a701SYangbo Lu */ 608dd3f6983Syangbo lu timeout = ktime_add_ms(ktime_get(), 20); 6091b21a701SYangbo Lu while (esdhc->vendor_ver > VENDOR_V_22) { 610ea6d0273SAdrian Hunter bool timedout = ktime_after(ktime_get(), timeout); 611ea6d0273SAdrian Hunter 6121b21a701SYangbo Lu if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) 613ea6d0273SAdrian Hunter break; 614ea6d0273SAdrian Hunter if (timedout) { 615dd3f6983Syangbo lu pr_err("%s: Internal clock never stabilised.\n", 616dd3f6983Syangbo lu mmc_hostname(host->mmc)); 617dd3f6983Syangbo lu break; 618dd3f6983Syangbo lu } 6191b21a701SYangbo Lu usleep_range(10, 20); 620dd3f6983Syangbo lu } 621dd3f6983Syangbo lu } 622dd3f6983Syangbo lu 6236e32f65cSYangbo Lu static void esdhc_flush_async_fifo(struct sdhci_host *host) 6246e32f65cSYangbo Lu { 6256e32f65cSYangbo Lu ktime_t timeout; 6266e32f65cSYangbo Lu u32 val; 6276e32f65cSYangbo Lu 6286e32f65cSYangbo Lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 6296e32f65cSYangbo Lu val |= ESDHC_FLUSH_ASYNC_FIFO; 6306e32f65cSYangbo Lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 6316e32f65cSYangbo Lu 6326e32f65cSYangbo Lu /* Wait max 20 ms */ 6336e32f65cSYangbo Lu timeout = ktime_add_ms(ktime_get(), 20); 6346e32f65cSYangbo Lu while (1) { 6356e32f65cSYangbo Lu bool timedout = ktime_after(ktime_get(), timeout); 6366e32f65cSYangbo Lu 6376e32f65cSYangbo Lu if (!(sdhci_readl(host, ESDHC_DMA_SYSCTL) & 6386e32f65cSYangbo Lu ESDHC_FLUSH_ASYNC_FIFO)) 6396e32f65cSYangbo Lu break; 6406e32f65cSYangbo Lu if (timedout) { 6416e32f65cSYangbo Lu pr_err("%s: flushing asynchronous FIFO timeout.\n", 6426e32f65cSYangbo Lu mmc_hostname(host->mmc)); 6436e32f65cSYangbo Lu break; 6446e32f65cSYangbo Lu } 6456e32f65cSYangbo Lu usleep_range(10, 20); 6466e32f65cSYangbo Lu } 6476e32f65cSYangbo Lu } 6486e32f65cSYangbo Lu 649f060bc9cSJerry Huang static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) 650f060bc9cSJerry Huang { 651f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 6528605e7aeSJisheng Zhang struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 6531b21a701SYangbo Lu unsigned int pre_div = 1, div = 1; 6541b21a701SYangbo Lu unsigned int clock_fixup = 0; 655e145ac45Syangbo lu ktime_t timeout; 656d31fc00aSDong Aisheng u32 temp; 657d31fc00aSDong Aisheng 658dd3f6983Syangbo lu if (clock == 0) { 6591b21a701SYangbo Lu host->mmc->actual_clock = 0; 660dd3f6983Syangbo lu esdhc_clock_enable(host, false); 661373073efSRussell King return; 662dd3f6983Syangbo lu } 663d31fc00aSDong Aisheng 6641b21a701SYangbo Lu /* Start pre_div at 2 for vendor version < 2.3. */ 665f4932cfdSyangbo lu if (esdhc->vendor_ver < VENDOR_V_23) 66677bd2f6fSYangbo Lu pre_div = 2; 66777bd2f6fSYangbo Lu 6681b21a701SYangbo Lu /* Fix clock value. */ 66967fdfbdfSyinbo.zhu if (host->mmc->card && mmc_card_sd(host->mmc->card) && 67067fdfbdfSyinbo.zhu esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) 6711b21a701SYangbo Lu clock_fixup = esdhc->clk_fixup->sd_dflt_max_clk; 67267fdfbdfSyinbo.zhu else if (esdhc->clk_fixup) 6731b21a701SYangbo Lu clock_fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; 674a627f025Syangbo lu 6751b21a701SYangbo Lu if (clock_fixup == 0 || clock < clock_fixup) 6761b21a701SYangbo Lu clock_fixup = clock; 677f060bc9cSJerry Huang 6781b21a701SYangbo Lu /* Calculate pre_div and div. */ 6791b21a701SYangbo Lu while (host->max_clk / pre_div / 16 > clock_fixup && pre_div < 256) 680d31fc00aSDong Aisheng pre_div *= 2; 681d31fc00aSDong Aisheng 6821b21a701SYangbo Lu while (host->max_clk / pre_div / div > clock_fixup && div < 16) 683d31fc00aSDong Aisheng div++; 684d31fc00aSDong Aisheng 6851b21a701SYangbo Lu esdhc->div_ratio = pre_div * div; 6861b21a701SYangbo Lu 6871b21a701SYangbo Lu /* Limit clock division for HS400 200MHz clock for quirk. */ 6886079e63cSYangbo Lu if (esdhc->quirk_limited_clk_division && 6896079e63cSYangbo Lu clock == MMC_HS200_MAX_DTR && 6906079e63cSYangbo Lu (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 || 6916079e63cSYangbo Lu host->flags & SDHCI_HS400_TUNING)) { 6921b21a701SYangbo Lu if (esdhc->div_ratio <= 4) { 6936079e63cSYangbo Lu pre_div = 4; 6946079e63cSYangbo Lu div = 1; 6951b21a701SYangbo Lu } else if (esdhc->div_ratio <= 8) { 6966079e63cSYangbo Lu pre_div = 4; 6976079e63cSYangbo Lu div = 2; 6981b21a701SYangbo Lu } else if (esdhc->div_ratio <= 12) { 6996079e63cSYangbo Lu pre_div = 4; 7006079e63cSYangbo Lu div = 3; 7016079e63cSYangbo Lu } else { 702b11c36d5SColin Ian King pr_warn("%s: using unsupported clock division.\n", 7036079e63cSYangbo Lu mmc_hostname(host->mmc)); 7046079e63cSYangbo Lu } 7051b21a701SYangbo Lu esdhc->div_ratio = pre_div * div; 7066079e63cSYangbo Lu } 7076079e63cSYangbo Lu 7081b21a701SYangbo Lu host->mmc->actual_clock = host->max_clk / esdhc->div_ratio; 7091b21a701SYangbo Lu 710d31fc00aSDong Aisheng dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", 7111b21a701SYangbo Lu clock, host->mmc->actual_clock); 7121b21a701SYangbo Lu 7131b21a701SYangbo Lu /* Set clock division into register. */ 714d31fc00aSDong Aisheng pre_div >>= 1; 715d31fc00aSDong Aisheng div--; 716d31fc00aSDong Aisheng 7171b21a701SYangbo Lu esdhc_clock_enable(host, false); 7181b21a701SYangbo Lu 719d31fc00aSDong Aisheng temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); 7201b21a701SYangbo Lu temp &= ~ESDHC_CLOCK_MASK; 7211b21a701SYangbo Lu temp |= ((div << ESDHC_DIVIDER_SHIFT) | 7221b21a701SYangbo Lu (pre_div << ESDHC_PREDIV_SHIFT)); 723d31fc00aSDong Aisheng sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); 724e87d2db2Syangbo lu 7251b21a701SYangbo Lu /* 7261b21a701SYangbo Lu * Wait max 20 ms. If vendor version is 2.2 or lower, do not 7271b21a701SYangbo Lu * wait clock stable bit which does not exist. 7281b21a701SYangbo Lu */ 7291b21a701SYangbo Lu timeout = ktime_add_ms(ktime_get(), 20); 7301b21a701SYangbo Lu while (esdhc->vendor_ver > VENDOR_V_22) { 7311b21a701SYangbo Lu bool timedout = ktime_after(ktime_get(), timeout); 7321b21a701SYangbo Lu 7331b21a701SYangbo Lu if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) 7341b21a701SYangbo Lu break; 7351b21a701SYangbo Lu if (timedout) { 7361b21a701SYangbo Lu pr_err("%s: Internal clock never stabilised.\n", 7371b21a701SYangbo Lu mmc_hostname(host->mmc)); 7381b21a701SYangbo Lu break; 7391b21a701SYangbo Lu } 7401b21a701SYangbo Lu usleep_range(10, 20); 7411b21a701SYangbo Lu } 7421b21a701SYangbo Lu 7431b21a701SYangbo Lu /* Additional setting for HS400. */ 74454e08d9aSYangbo Lu if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && 74554e08d9aSYangbo Lu clock == MMC_HS200_MAX_DTR) { 74654e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 74754e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_MODE, ESDHC_TBCTL); 74854e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_SDCLKCTL); 74954e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_CMD_CLK_CTL, ESDHC_SDCLKCTL); 75054e08d9aSYangbo Lu esdhc_clock_enable(host, true); 75154e08d9aSYangbo Lu 75254e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_DLLCFG0); 75358d0bf84SYangbo Lu temp |= ESDHC_DLL_ENABLE; 75458d0bf84SYangbo Lu if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) 75558d0bf84SYangbo Lu temp |= ESDHC_DLL_FREQ_SEL; 75654e08d9aSYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 757011fde48SYangbo Lu 758011fde48SYangbo Lu temp |= ESDHC_DLL_RESET; 759011fde48SYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 760011fde48SYangbo Lu udelay(1); 761011fde48SYangbo Lu temp &= ~ESDHC_DLL_RESET; 762011fde48SYangbo Lu sdhci_writel(host, temp, ESDHC_DLLCFG0); 763011fde48SYangbo Lu 764011fde48SYangbo Lu /* Wait max 20 ms */ 765011fde48SYangbo Lu if (read_poll_timeout(sdhci_readl, temp, 766011fde48SYangbo Lu temp & ESDHC_DLL_STS_SLV_LOCK, 767011fde48SYangbo Lu 10, 20000, false, 768011fde48SYangbo Lu host, ESDHC_DLLSTAT0)) 769011fde48SYangbo Lu pr_err("%s: timeout for delay chain lock.\n", 770011fde48SYangbo Lu mmc_hostname(host->mmc)); 771011fde48SYangbo Lu 77254e08d9aSYangbo Lu temp = sdhci_readl(host, ESDHC_TBCTL); 77354e08d9aSYangbo Lu sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL); 77454e08d9aSYangbo Lu 77554e08d9aSYangbo Lu esdhc_clock_enable(host, false); 7766e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 77754e08d9aSYangbo Lu } 77880c74823SYangbo Lu esdhc_clock_enable(host, true); 779e87d2db2Syangbo lu } 780e87d2db2Syangbo lu 7812317f56cSRussell King static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) 78266b50a00SOded Gabbay { 78366b50a00SOded Gabbay u32 ctrl; 78466b50a00SOded Gabbay 785f4932cfdSyangbo lu ctrl = sdhci_readl(host, ESDHC_PROCTL); 786f4932cfdSyangbo lu ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK); 78766b50a00SOded Gabbay switch (width) { 78866b50a00SOded Gabbay case MMC_BUS_WIDTH_8: 789f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_8BITBUS; 79066b50a00SOded Gabbay break; 79166b50a00SOded Gabbay 79266b50a00SOded Gabbay case MMC_BUS_WIDTH_4: 793f4932cfdSyangbo lu ctrl |= ESDHC_CTRL_4BITBUS; 79466b50a00SOded Gabbay break; 79566b50a00SOded Gabbay 79666b50a00SOded Gabbay default: 79766b50a00SOded Gabbay break; 79866b50a00SOded Gabbay } 79966b50a00SOded Gabbay 800f4932cfdSyangbo lu sdhci_writel(host, ctrl, ESDHC_PROCTL); 80166b50a00SOded Gabbay } 80266b50a00SOded Gabbay 803304f0a98SAlessio Igor Bogani static void esdhc_reset(struct sdhci_host *host, u8 mask) 804304f0a98SAlessio Igor Bogani { 80548e304ccSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 80648e304ccSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 8072aa3d826SYangbo Lu u32 val, bus_width = 0; 808f2bc6000Syinbo.zhu 8092aa3d826SYangbo Lu /* 8102aa3d826SYangbo Lu * Add delay to make sure all the DMA transfers are finished 8112aa3d826SYangbo Lu * for quirk. 8122aa3d826SYangbo Lu */ 813f667216cSYangbo Lu if (esdhc->quirk_delay_before_data_reset && 814f667216cSYangbo Lu (mask & SDHCI_RESET_DATA) && 815f667216cSYangbo Lu (host->flags & SDHCI_REQ_USE_DMA)) 816f667216cSYangbo Lu mdelay(5); 817f667216cSYangbo Lu 8182aa3d826SYangbo Lu /* 8192aa3d826SYangbo Lu * Save bus-width for eSDHC whose vendor version is 2.2 8202aa3d826SYangbo Lu * or lower for data reset. 8212aa3d826SYangbo Lu */ 8222aa3d826SYangbo Lu if ((mask & SDHCI_RESET_DATA) && 8232aa3d826SYangbo Lu (esdhc->vendor_ver <= VENDOR_V_22)) { 8242aa3d826SYangbo Lu val = sdhci_readl(host, ESDHC_PROCTL); 8252aa3d826SYangbo Lu bus_width = val & ESDHC_CTRL_BUSWIDTH_MASK; 8262aa3d826SYangbo Lu } 8272aa3d826SYangbo Lu 828304f0a98SAlessio Igor Bogani sdhci_reset(host, mask); 829304f0a98SAlessio Igor Bogani 8302aa3d826SYangbo Lu /* 8312aa3d826SYangbo Lu * Restore bus-width setting and interrupt registers for eSDHC 8322aa3d826SYangbo Lu * whose vendor version is 2.2 or lower for data reset. 8332aa3d826SYangbo Lu */ 8342aa3d826SYangbo Lu if ((mask & SDHCI_RESET_DATA) && 8352aa3d826SYangbo Lu (esdhc->vendor_ver <= VENDOR_V_22)) { 8362aa3d826SYangbo Lu val = sdhci_readl(host, ESDHC_PROCTL); 8372aa3d826SYangbo Lu val &= ~ESDHC_CTRL_BUSWIDTH_MASK; 8382aa3d826SYangbo Lu val |= bus_width; 8392aa3d826SYangbo Lu sdhci_writel(host, val, ESDHC_PROCTL); 8402aa3d826SYangbo Lu 841304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 842304f0a98SAlessio Igor Bogani sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 8432aa3d826SYangbo Lu } 844f2bc6000Syinbo.zhu 8452aa3d826SYangbo Lu /* 8462aa3d826SYangbo Lu * Some bits have to be cleaned manually for eSDHC whose spec 8472aa3d826SYangbo Lu * version is higher than 3.0 for all reset. 8482aa3d826SYangbo Lu */ 8492aa3d826SYangbo Lu if ((mask & SDHCI_RESET_ALL) && 8502aa3d826SYangbo Lu (esdhc->spec_ver >= SDHCI_SPEC_300)) { 851f2bc6000Syinbo.zhu val = sdhci_readl(host, ESDHC_TBCTL); 852f2bc6000Syinbo.zhu val &= ~ESDHC_TB_EN; 853f2bc6000Syinbo.zhu sdhci_writel(host, val, ESDHC_TBCTL); 85448e304ccSYangbo Lu 8552aa3d826SYangbo Lu /* 8562aa3d826SYangbo Lu * Initialize eSDHC_DLLCFG1[DLL_PD_PULSE_STRETCH_SEL] to 8572aa3d826SYangbo Lu * 0 for quirk. 8582aa3d826SYangbo Lu */ 85948e304ccSYangbo Lu if (esdhc->quirk_unreliable_pulse_detection) { 86048e304ccSYangbo Lu val = sdhci_readl(host, ESDHC_DLLCFG1); 86148e304ccSYangbo Lu val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL; 86248e304ccSYangbo Lu sdhci_writel(host, val, ESDHC_DLLCFG1); 86348e304ccSYangbo Lu } 864f2bc6000Syinbo.zhu } 865304f0a98SAlessio Igor Bogani } 866304f0a98SAlessio Igor Bogani 867ea35645aSyangbo lu /* The SCFG, Supplemental Configuration Unit, provides SoC specific 868ea35645aSyangbo lu * configuration and status registers for the device. There is a 869ea35645aSyangbo lu * SDHC IO VSEL control register on SCFG for some platforms. It's 870ea35645aSyangbo lu * used to support SDHC IO voltage switching. 871ea35645aSyangbo lu */ 872ea35645aSyangbo lu static const struct of_device_id scfg_device_ids[] = { 873ea35645aSyangbo lu { .compatible = "fsl,t1040-scfg", }, 874ea35645aSyangbo lu { .compatible = "fsl,ls1012a-scfg", }, 875ea35645aSyangbo lu { .compatible = "fsl,ls1046a-scfg", }, 876ea35645aSyangbo lu {} 877ea35645aSyangbo lu }; 878ea35645aSyangbo lu 879ea35645aSyangbo lu /* SDHC IO VSEL control register definition */ 880ea35645aSyangbo lu #define SCFG_SDHCIOVSELCR 0x408 881ea35645aSyangbo lu #define SDHCIOVSELCR_TGLEN 0x80000000 882ea35645aSyangbo lu #define SDHCIOVSELCR_VSELVAL 0x60000000 883ea35645aSyangbo lu #define SDHCIOVSELCR_SDHC_VS 0x00000001 884ea35645aSyangbo lu 885ea35645aSyangbo lu static int esdhc_signal_voltage_switch(struct mmc_host *mmc, 886ea35645aSyangbo lu struct mmc_ios *ios) 887ea35645aSyangbo lu { 888ea35645aSyangbo lu struct sdhci_host *host = mmc_priv(mmc); 889ea35645aSyangbo lu struct device_node *scfg_node; 890ea35645aSyangbo lu void __iomem *scfg_base = NULL; 891ea35645aSyangbo lu u32 sdhciovselcr; 892ea35645aSyangbo lu u32 val; 893ea35645aSyangbo lu 894ea35645aSyangbo lu /* 895ea35645aSyangbo lu * Signal Voltage Switching is only applicable for Host Controllers 896ea35645aSyangbo lu * v3.00 and above. 897ea35645aSyangbo lu */ 898ea35645aSyangbo lu if (host->version < SDHCI_SPEC_300) 899ea35645aSyangbo lu return 0; 900ea35645aSyangbo lu 901ea35645aSyangbo lu val = sdhci_readl(host, ESDHC_PROCTL); 902ea35645aSyangbo lu 903ea35645aSyangbo lu switch (ios->signal_voltage) { 904ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_330: 905ea35645aSyangbo lu val &= ~ESDHC_VOLT_SEL; 906ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 907ea35645aSyangbo lu return 0; 908ea35645aSyangbo lu case MMC_SIGNAL_VOLTAGE_180: 909ea35645aSyangbo lu scfg_node = of_find_matching_node(NULL, scfg_device_ids); 910ea35645aSyangbo lu if (scfg_node) 911ea35645aSyangbo lu scfg_base = of_iomap(scfg_node, 0); 912b5899a3eSMiaoqian Lin of_node_put(scfg_node); 913ea35645aSyangbo lu if (scfg_base) { 914ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 915ea35645aSyangbo lu SDHCIOVSELCR_VSELVAL; 916ea35645aSyangbo lu iowrite32be(sdhciovselcr, 917ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 918ea35645aSyangbo lu 919ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 920ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 921ea35645aSyangbo lu mdelay(5); 922ea35645aSyangbo lu 923ea35645aSyangbo lu sdhciovselcr = SDHCIOVSELCR_TGLEN | 924ea35645aSyangbo lu SDHCIOVSELCR_SDHC_VS; 925ea35645aSyangbo lu iowrite32be(sdhciovselcr, 926ea35645aSyangbo lu scfg_base + SCFG_SDHCIOVSELCR); 927ea35645aSyangbo lu iounmap(scfg_base); 928ea35645aSyangbo lu } else { 929ea35645aSyangbo lu val |= ESDHC_VOLT_SEL; 930ea35645aSyangbo lu sdhci_writel(host, val, ESDHC_PROCTL); 931ea35645aSyangbo lu } 932ea35645aSyangbo lu return 0; 933ea35645aSyangbo lu default: 934ea35645aSyangbo lu return 0; 935ea35645aSyangbo lu } 936ea35645aSyangbo lu } 937ea35645aSyangbo lu 93822dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type1[] = { 9395b742232SYangbo Lu { .family = "QorIQ T1023", }, 9405b742232SYangbo Lu { .family = "QorIQ T1040", }, 9415b742232SYangbo Lu { .family = "QorIQ T2080", }, 9425b742232SYangbo Lu { .family = "QorIQ LS1021A", }, 9430ffd498dSGeert Uytterhoeven { /* sentinel */ } 94422dc132dSYangbo Lu }; 94522dc132dSYangbo Lu 94622dc132dSYangbo Lu static struct soc_device_attribute soc_tuning_erratum_type2[] = { 9475b742232SYangbo Lu { .family = "QorIQ LS1012A", }, 9485b742232SYangbo Lu { .family = "QorIQ LS1043A", }, 9495b742232SYangbo Lu { .family = "QorIQ LS1046A", }, 9505b742232SYangbo Lu { .family = "QorIQ LS1080A", }, 9515b742232SYangbo Lu { .family = "QorIQ LS2080A", }, 9525b742232SYangbo Lu { .family = "QorIQ LA1575A", }, 9530ffd498dSGeert Uytterhoeven { /* sentinel */ } 954b1f378abSYinbo Zhu }; 955b1f378abSYinbo Zhu 95654e08d9aSYangbo Lu static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable) 957ba49cbd0Syangbo lu { 958ba49cbd0Syangbo lu u32 val; 959ba49cbd0Syangbo lu 960ba49cbd0Syangbo lu esdhc_clock_enable(host, false); 9616e32f65cSYangbo Lu esdhc_flush_async_fifo(host); 962ba49cbd0Syangbo lu 963ba49cbd0Syangbo lu val = sdhci_readl(host, ESDHC_TBCTL); 96454e08d9aSYangbo Lu if (enable) 965ba49cbd0Syangbo lu val |= ESDHC_TB_EN; 96654e08d9aSYangbo Lu else 96754e08d9aSYangbo Lu val &= ~ESDHC_TB_EN; 968ba49cbd0Syangbo lu sdhci_writel(host, val, ESDHC_TBCTL); 969ba49cbd0Syangbo lu 97054e08d9aSYangbo Lu esdhc_clock_enable(host, true); 97154e08d9aSYangbo Lu } 97254e08d9aSYangbo Lu 973f3c20825SYangbo Lu static void esdhc_tuning_window_ptr(struct sdhci_host *host, u8 *window_start, 97422dc132dSYangbo Lu u8 *window_end) 97522dc132dSYangbo Lu { 97622dc132dSYangbo Lu u32 val; 97722dc132dSYangbo Lu 97822dc132dSYangbo Lu /* Write TBCTL[11:8]=4'h8 */ 97922dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 98022dc132dSYangbo Lu val &= ~(0xf << 8); 98122dc132dSYangbo Lu val |= 8 << 8; 98222dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 98322dc132dSYangbo Lu 98422dc132dSYangbo Lu mdelay(1); 98522dc132dSYangbo Lu 98622dc132dSYangbo Lu /* Read TBCTL[31:0] register and rewrite again */ 98722dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 98822dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 98922dc132dSYangbo Lu 99022dc132dSYangbo Lu mdelay(1); 99122dc132dSYangbo Lu 99222dc132dSYangbo Lu /* Read the TBSTAT[31:0] register twice */ 99322dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 99422dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBSTAT); 99522dc132dSYangbo Lu 996f3c20825SYangbo Lu *window_end = val & 0xff; 997f3c20825SYangbo Lu *window_start = (val >> 8) & 0xff; 998f3c20825SYangbo Lu } 999f3c20825SYangbo Lu 1000f3c20825SYangbo Lu static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start, 1001f3c20825SYangbo Lu u8 *window_end) 1002f3c20825SYangbo Lu { 1003f3c20825SYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1004f3c20825SYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1005f3c20825SYangbo Lu u8 start_ptr, end_ptr; 1006f3c20825SYangbo Lu 1007f3c20825SYangbo Lu if (esdhc->quirk_tuning_erratum_type1) { 1008f3c20825SYangbo Lu *window_start = 5 * esdhc->div_ratio; 1009f3c20825SYangbo Lu *window_end = 3 * esdhc->div_ratio; 1010f3c20825SYangbo Lu return; 1011f3c20825SYangbo Lu } 1012f3c20825SYangbo Lu 1013f3c20825SYangbo Lu esdhc_tuning_window_ptr(host, &start_ptr, &end_ptr); 1014f3c20825SYangbo Lu 101522dc132dSYangbo Lu /* Reset data lines by setting ESDHCCTL[RSTD] */ 101622dc132dSYangbo Lu sdhci_reset(host, SDHCI_RESET_DATA); 101722dc132dSYangbo Lu /* Write 32'hFFFF_FFFF to IRQSTAT register */ 101822dc132dSYangbo Lu sdhci_writel(host, 0xFFFFFFFF, SDHCI_INT_STATUS); 101922dc132dSYangbo Lu 10205b742232SYangbo Lu /* If TBSTAT[15:8]-TBSTAT[7:0] > (4 * div_ratio) + 2 10215b742232SYangbo Lu * or TBSTAT[7:0]-TBSTAT[15:8] > (4 * div_ratio) + 2, 102222dc132dSYangbo Lu * then program TBPTR[TB_WNDW_END_PTR] = 4 * div_ratio 102322dc132dSYangbo Lu * and program TBPTR[TB_WNDW_START_PTR] = 8 * div_ratio. 102422dc132dSYangbo Lu */ 102522dc132dSYangbo Lu 10265b742232SYangbo Lu if (abs(start_ptr - end_ptr) > (4 * esdhc->div_ratio + 2)) { 102722dc132dSYangbo Lu *window_start = 8 * esdhc->div_ratio; 102822dc132dSYangbo Lu *window_end = 4 * esdhc->div_ratio; 102922dc132dSYangbo Lu } else { 103022dc132dSYangbo Lu *window_start = 5 * esdhc->div_ratio; 103122dc132dSYangbo Lu *window_end = 3 * esdhc->div_ratio; 103222dc132dSYangbo Lu } 103322dc132dSYangbo Lu } 103422dc132dSYangbo Lu 103522dc132dSYangbo Lu static int esdhc_execute_sw_tuning(struct mmc_host *mmc, u32 opcode, 103622dc132dSYangbo Lu u8 window_start, u8 window_end) 103722dc132dSYangbo Lu { 103822dc132dSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 103922dc132dSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 104022dc132dSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 104122dc132dSYangbo Lu u32 val; 104222dc132dSYangbo Lu int ret; 104322dc132dSYangbo Lu 104422dc132dSYangbo Lu /* Program TBPTR[TB_WNDW_END_PTR] and TBPTR[TB_WNDW_START_PTR] */ 104522dc132dSYangbo Lu val = ((u32)window_start << ESDHC_WNDW_STRT_PTR_SHIFT) & 104622dc132dSYangbo Lu ESDHC_WNDW_STRT_PTR_MASK; 104722dc132dSYangbo Lu val |= window_end & ESDHC_WNDW_END_PTR_MASK; 104822dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBPTR); 104922dc132dSYangbo Lu 105022dc132dSYangbo Lu /* Program the software tuning mode by setting TBCTL[TB_MODE]=2'h3 */ 105122dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 105222dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 105322dc132dSYangbo Lu val |= ESDHC_TB_MODE_SW; 105422dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 105522dc132dSYangbo Lu 105622dc132dSYangbo Lu esdhc->in_sw_tuning = true; 105722dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 105822dc132dSYangbo Lu esdhc->in_sw_tuning = false; 105922dc132dSYangbo Lu return ret; 106022dc132dSYangbo Lu } 106122dc132dSYangbo Lu 106254e08d9aSYangbo Lu static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) 106354e08d9aSYangbo Lu { 106454e08d9aSYangbo Lu struct sdhci_host *host = mmc_priv(mmc); 106554e08d9aSYangbo Lu struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 106654e08d9aSYangbo Lu struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 106722dc132dSYangbo Lu u8 window_start, window_end; 106822dc132dSYangbo Lu int ret, retries = 1; 106954e08d9aSYangbo Lu bool hs400_tuning; 107004509d77SYangbo Lu unsigned int clk; 107154e08d9aSYangbo Lu u32 val; 107254e08d9aSYangbo Lu 107304509d77SYangbo Lu /* For tuning mode, the sd clock divisor value 107404509d77SYangbo Lu * must be larger than 3 according to reference manual. 107504509d77SYangbo Lu */ 107604509d77SYangbo Lu clk = esdhc->peripheral_clock / 3; 107704509d77SYangbo Lu if (host->clock > clk) 107804509d77SYangbo Lu esdhc_of_set_clock(host, clk); 107904509d77SYangbo Lu 108054e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 108154e08d9aSYangbo Lu 10820add6e9bSMichael Walle /* 10830add6e9bSMichael Walle * The eSDHC controller takes the data timeout value into account 10840add6e9bSMichael Walle * during tuning. If the SD card is too slow sending the response, the 10850add6e9bSMichael Walle * timer will expire and a "Buffer Read Ready" interrupt without data 10860add6e9bSMichael Walle * is triggered. This leads to tuning errors. 10870add6e9bSMichael Walle * 10880add6e9bSMichael Walle * Just set the timeout to the maximum value because the core will 10890add6e9bSMichael Walle * already take care of it in sdhci_send_tuning(). 10900add6e9bSMichael Walle */ 10910add6e9bSMichael Walle sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); 10920add6e9bSMichael Walle 109354e08d9aSYangbo Lu hs400_tuning = host->flags & SDHCI_HS400_TUNING; 109454e08d9aSYangbo Lu 109522dc132dSYangbo Lu do { 109622dc132dSYangbo Lu if (esdhc->quirk_limited_clk_division && 109722dc132dSYangbo Lu hs400_tuning) 109822dc132dSYangbo Lu esdhc_of_set_clock(host, host->clock); 109922dc132dSYangbo Lu 110022dc132dSYangbo Lu /* Do HW tuning */ 110122dc132dSYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 110222dc132dSYangbo Lu val &= ~ESDHC_TB_MODE_MASK; 110322dc132dSYangbo Lu val |= ESDHC_TB_MODE_3; 110422dc132dSYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 110522dc132dSYangbo Lu 110622dc132dSYangbo Lu ret = sdhci_execute_tuning(mmc, opcode); 110722dc132dSYangbo Lu if (ret) 110822dc132dSYangbo Lu break; 110922dc132dSYangbo Lu 11105b742232SYangbo Lu /* For type2 affected platforms of the tuning erratum, 11115b742232SYangbo Lu * tuning may succeed although eSDHC might not have 11125b742232SYangbo Lu * tuned properly. Need to check tuning window. 11135b742232SYangbo Lu */ 11145b742232SYangbo Lu if (esdhc->quirk_tuning_erratum_type2 && 11155b742232SYangbo Lu !host->tuning_err) { 11165b742232SYangbo Lu esdhc_tuning_window_ptr(host, &window_start, 11175b742232SYangbo Lu &window_end); 11185b742232SYangbo Lu if (abs(window_start - window_end) > 11195b742232SYangbo Lu (4 * esdhc->div_ratio + 2)) 11205b742232SYangbo Lu host->tuning_err = -EAGAIN; 11215b742232SYangbo Lu } 11225b742232SYangbo Lu 112322dc132dSYangbo Lu /* If HW tuning fails and triggers erratum, 112422dc132dSYangbo Lu * try workaround. 112522dc132dSYangbo Lu */ 112622dc132dSYangbo Lu ret = host->tuning_err; 112722dc132dSYangbo Lu if (ret == -EAGAIN && 112822dc132dSYangbo Lu (esdhc->quirk_tuning_erratum_type1 || 112922dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2)) { 113022dc132dSYangbo Lu /* Recover HS400 tuning flag */ 113122dc132dSYangbo Lu if (hs400_tuning) 113222dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 113322dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try SW tuning!\n", 113422dc132dSYangbo Lu mmc_hostname(mmc)); 113522dc132dSYangbo Lu /* Do SW tuning */ 113622dc132dSYangbo Lu esdhc_prepare_sw_tuning(host, &window_start, 113722dc132dSYangbo Lu &window_end); 113822dc132dSYangbo Lu ret = esdhc_execute_sw_tuning(mmc, opcode, 113922dc132dSYangbo Lu window_start, 114022dc132dSYangbo Lu window_end); 114122dc132dSYangbo Lu if (ret) 114222dc132dSYangbo Lu break; 114322dc132dSYangbo Lu 114422dc132dSYangbo Lu /* Retry both HW/SW tuning with reduced clock. */ 114522dc132dSYangbo Lu ret = host->tuning_err; 114622dc132dSYangbo Lu if (ret == -EAGAIN && retries) { 114722dc132dSYangbo Lu /* Recover HS400 tuning flag */ 114822dc132dSYangbo Lu if (hs400_tuning) 114922dc132dSYangbo Lu host->flags |= SDHCI_HS400_TUNING; 115022dc132dSYangbo Lu 115122dc132dSYangbo Lu clk = host->max_clk / (esdhc->div_ratio + 1); 115222dc132dSYangbo Lu esdhc_of_set_clock(host, clk); 115322dc132dSYangbo Lu pr_info("%s: Hold on to use fixed sampling clock. Try tuning with reduced clock!\n", 115422dc132dSYangbo Lu mmc_hostname(mmc)); 115522dc132dSYangbo Lu } else { 115622dc132dSYangbo Lu break; 115722dc132dSYangbo Lu } 115822dc132dSYangbo Lu } else { 115922dc132dSYangbo Lu break; 116022dc132dSYangbo Lu } 116122dc132dSYangbo Lu } while (retries--); 116222dc132dSYangbo Lu 116322dc132dSYangbo Lu if (ret) { 116422dc132dSYangbo Lu esdhc_tuning_block_enable(host, false); 116522dc132dSYangbo Lu } else if (hs400_tuning) { 116654e08d9aSYangbo Lu val = sdhci_readl(host, ESDHC_SDTIMNGCTL); 116754e08d9aSYangbo Lu val |= ESDHC_FLW_CTL_BG; 116854e08d9aSYangbo Lu sdhci_writel(host, val, ESDHC_SDTIMNGCTL); 116954e08d9aSYangbo Lu } 117054e08d9aSYangbo Lu 117154e08d9aSYangbo Lu return ret; 117254e08d9aSYangbo Lu } 117354e08d9aSYangbo Lu 117454e08d9aSYangbo Lu static void esdhc_set_uhs_signaling(struct sdhci_host *host, 117554e08d9aSYangbo Lu unsigned int timing) 117654e08d9aSYangbo Lu { 117747e9e107SYangbo Lu u32 val; 117847e9e107SYangbo Lu 117947e9e107SYangbo Lu /* 118047e9e107SYangbo Lu * There are specific registers setting for HS400 mode. 118147e9e107SYangbo Lu * Clean all of them if controller is in HS400 mode to 118247e9e107SYangbo Lu * exit HS400 mode before re-setting any speed mode. 118347e9e107SYangbo Lu */ 118447e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 118547e9e107SYangbo Lu if (val & ESDHC_HS400_MODE) { 118647e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_SDTIMNGCTL); 118747e9e107SYangbo Lu val &= ~ESDHC_FLW_CTL_BG; 118847e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_SDTIMNGCTL); 118947e9e107SYangbo Lu 119047e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_SDCLKCTL); 119147e9e107SYangbo Lu val &= ~ESDHC_CMD_CLK_CTL; 119247e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_SDCLKCTL); 119347e9e107SYangbo Lu 119447e9e107SYangbo Lu esdhc_clock_enable(host, false); 119547e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 119647e9e107SYangbo Lu val &= ~ESDHC_HS400_MODE; 119747e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 119847e9e107SYangbo Lu esdhc_clock_enable(host, true); 119947e9e107SYangbo Lu 120047e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_DLLCFG0); 120147e9e107SYangbo Lu val &= ~(ESDHC_DLL_ENABLE | ESDHC_DLL_FREQ_SEL); 120247e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_DLLCFG0); 120347e9e107SYangbo Lu 120447e9e107SYangbo Lu val = sdhci_readl(host, ESDHC_TBCTL); 120547e9e107SYangbo Lu val &= ~ESDHC_HS400_WNDW_ADJUST; 120647e9e107SYangbo Lu sdhci_writel(host, val, ESDHC_TBCTL); 120747e9e107SYangbo Lu 120847e9e107SYangbo Lu esdhc_tuning_block_enable(host, false); 120947e9e107SYangbo Lu } 121047e9e107SYangbo Lu 121154e08d9aSYangbo Lu if (timing == MMC_TIMING_MMC_HS400) 121254e08d9aSYangbo Lu esdhc_tuning_block_enable(host, true); 121354e08d9aSYangbo Lu else 121454e08d9aSYangbo Lu sdhci_set_uhs_signaling(host, timing); 1215ba49cbd0Syangbo lu } 1216ba49cbd0Syangbo lu 1217b214fe59SYinbo Zhu static u32 esdhc_irq(struct sdhci_host *host, u32 intmask) 1218b214fe59SYinbo Zhu { 1219060522d8SChris Packham struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1220060522d8SChris Packham struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); 1221b214fe59SYinbo Zhu u32 command; 1222b214fe59SYinbo Zhu 1223060522d8SChris Packham if (esdhc->quirk_trans_complete_erratum) { 1224b214fe59SYinbo Zhu command = SDHCI_GET_CMD(sdhci_readw(host, 1225b214fe59SYinbo Zhu SDHCI_COMMAND)); 1226b214fe59SYinbo Zhu if (command == MMC_WRITE_MULTIPLE_BLOCK && 1227b214fe59SYinbo Zhu sdhci_readw(host, SDHCI_BLOCK_COUNT) && 1228b214fe59SYinbo Zhu intmask & SDHCI_INT_DATA_END) { 1229b214fe59SYinbo Zhu intmask &= ~SDHCI_INT_DATA_END; 1230b214fe59SYinbo Zhu sdhci_writel(host, SDHCI_INT_DATA_END, 1231b214fe59SYinbo Zhu SDHCI_INT_STATUS); 1232b214fe59SYinbo Zhu } 1233b214fe59SYinbo Zhu } 1234b214fe59SYinbo Zhu return intmask; 1235b214fe59SYinbo Zhu } 1236b214fe59SYinbo Zhu 12379e48b336SUlf Hansson #ifdef CONFIG_PM_SLEEP 1238723f7924SRussell King static u32 esdhc_proctl; 1239723f7924SRussell King static int esdhc_of_suspend(struct device *dev) 1240723f7924SRussell King { 1241723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1242723f7924SRussell King 1243f4932cfdSyangbo lu esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL); 1244723f7924SRussell King 1245d38dcad4SAdrian Hunter if (host->tuning_mode != SDHCI_TUNING_MODE_3) 1246d38dcad4SAdrian Hunter mmc_retune_needed(host->mmc); 1247d38dcad4SAdrian Hunter 1248723f7924SRussell King return sdhci_suspend_host(host); 1249723f7924SRussell King } 1250723f7924SRussell King 125106732b84SUlf Hansson static int esdhc_of_resume(struct device *dev) 1252723f7924SRussell King { 1253723f7924SRussell King struct sdhci_host *host = dev_get_drvdata(dev); 1254723f7924SRussell King int ret = sdhci_resume_host(host); 1255723f7924SRussell King 1256723f7924SRussell King if (ret == 0) { 1257723f7924SRussell King /* Isn't this already done by sdhci_resume_host() ? --rmk */ 1258723f7924SRussell King esdhc_of_enable_dma(host); 1259f4932cfdSyangbo lu sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); 1260723f7924SRussell King } 1261723f7924SRussell King return ret; 1262723f7924SRussell King } 1263723f7924SRussell King #endif 1264723f7924SRussell King 12659e48b336SUlf Hansson static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, 12669e48b336SUlf Hansson esdhc_of_suspend, 12679e48b336SUlf Hansson esdhc_of_resume); 12689e48b336SUlf Hansson 1269f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_be_ops = { 1270f4932cfdSyangbo lu .read_l = esdhc_be_readl, 1271f4932cfdSyangbo lu .read_w = esdhc_be_readw, 1272f4932cfdSyangbo lu .read_b = esdhc_be_readb, 1273f4932cfdSyangbo lu .write_l = esdhc_be_writel, 1274f4932cfdSyangbo lu .write_w = esdhc_be_writew, 1275f4932cfdSyangbo lu .write_b = esdhc_be_writeb, 1276f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1277f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1278f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1279f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1280f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1281f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1282f4932cfdSyangbo lu .reset = esdhc_reset, 128354e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1284b214fe59SYinbo Zhu .irq = esdhc_irq, 1285f4932cfdSyangbo lu }; 1286f4932cfdSyangbo lu 1287f4932cfdSyangbo lu static const struct sdhci_ops sdhci_esdhc_le_ops = { 1288f4932cfdSyangbo lu .read_l = esdhc_le_readl, 1289f4932cfdSyangbo lu .read_w = esdhc_le_readw, 1290f4932cfdSyangbo lu .read_b = esdhc_le_readb, 1291f4932cfdSyangbo lu .write_l = esdhc_le_writel, 1292f4932cfdSyangbo lu .write_w = esdhc_le_writew, 1293f4932cfdSyangbo lu .write_b = esdhc_le_writeb, 1294f4932cfdSyangbo lu .set_clock = esdhc_of_set_clock, 1295f4932cfdSyangbo lu .enable_dma = esdhc_of_enable_dma, 1296f4932cfdSyangbo lu .get_max_clock = esdhc_of_get_max_clock, 1297f4932cfdSyangbo lu .get_min_clock = esdhc_of_get_min_clock, 1298f4932cfdSyangbo lu .adma_workaround = esdhc_of_adma_workaround, 1299f4932cfdSyangbo lu .set_bus_width = esdhc_pltfm_set_bus_width, 1300f4932cfdSyangbo lu .reset = esdhc_reset, 130154e08d9aSYangbo Lu .set_uhs_signaling = esdhc_set_uhs_signaling, 1302b214fe59SYinbo Zhu .irq = esdhc_irq, 1303f4932cfdSyangbo lu }; 1304f4932cfdSyangbo lu 1305f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { 1306e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1307e9acc77dSyangbo lu #ifdef CONFIG_PPC 1308e9acc77dSyangbo lu SDHCI_QUIRK_BROKEN_CARD_DETECTION | 1309e9acc77dSyangbo lu #endif 1310e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1311e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1312f4932cfdSyangbo lu .ops = &sdhci_esdhc_be_ops, 13137657c3a7SAlbert Herranz }; 131438576af1SShawn Guo 1315f4932cfdSyangbo lu static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = { 1316e9acc77dSyangbo lu .quirks = ESDHC_DEFAULT_QUIRKS | 1317e9acc77dSyangbo lu SDHCI_QUIRK_NO_CARD_NO_RESET | 1318e9acc77dSyangbo lu SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1319f4932cfdSyangbo lu .ops = &sdhci_esdhc_le_ops, 1320f4932cfdSyangbo lu }; 1321f4932cfdSyangbo lu 1322151ede40Syangbo lu static struct soc_device_attribute soc_incorrect_hostver[] = { 1323151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "1.0", }, 1324151ede40Syangbo lu { .family = "QorIQ T4240", .revision = "2.0", }, 13250ffd498dSGeert Uytterhoeven { /* sentinel */ } 1326151ede40Syangbo lu }; 1327151ede40Syangbo lu 13286079e63cSYangbo Lu static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = { 13296079e63cSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 13308e9a6919SYinbo Zhu { .family = "QorIQ LX2160A", .revision = "2.0", }, 13315f3ad196SYinbo Zhu { .family = "QorIQ LS1028A", .revision = "1.0", }, 13320ffd498dSGeert Uytterhoeven { /* sentinel */ } 13336079e63cSYangbo Lu }; 13346079e63cSYangbo Lu 133548e304ccSYangbo Lu static struct soc_device_attribute soc_unreliable_pulse_detection[] = { 133648e304ccSYangbo Lu { .family = "QorIQ LX2160A", .revision = "1.0", }, 133771b05327SYangbo Lu { .family = "QorIQ LX2160A", .revision = "2.0", }, 133871b05327SYangbo Lu { .family = "QorIQ LS1028A", .revision = "1.0", }, 13390ffd498dSGeert Uytterhoeven { /* sentinel */ } 134048e304ccSYangbo Lu }; 134148e304ccSYangbo Lu 1342f4932cfdSyangbo lu static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) 1343f4932cfdSyangbo lu { 134467fdfbdfSyinbo.zhu const struct of_device_id *match; 1345f4932cfdSyangbo lu struct sdhci_pltfm_host *pltfm_host; 1346f4932cfdSyangbo lu struct sdhci_esdhc *esdhc; 134719c3a0efSyangbo lu struct device_node *np; 134819c3a0efSyangbo lu struct clk *clk; 134919c3a0efSyangbo lu u32 val; 1350f4932cfdSyangbo lu u16 host_ver; 1351f4932cfdSyangbo lu 1352f4932cfdSyangbo lu pltfm_host = sdhci_priv(host); 13538605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 1354f4932cfdSyangbo lu 1355f4932cfdSyangbo lu host_ver = sdhci_readw(host, SDHCI_HOST_VERSION); 1356f4932cfdSyangbo lu esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> 1357f4932cfdSyangbo lu SDHCI_VENDOR_VER_SHIFT; 1358f4932cfdSyangbo lu esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; 1359151ede40Syangbo lu if (soc_device_match(soc_incorrect_hostver)) 1360151ede40Syangbo lu esdhc->quirk_incorrect_hostver = true; 1361151ede40Syangbo lu else 1362151ede40Syangbo lu esdhc->quirk_incorrect_hostver = false; 136319c3a0efSyangbo lu 13646079e63cSYangbo Lu if (soc_device_match(soc_fixup_sdhc_clkdivs)) 13656079e63cSYangbo Lu esdhc->quirk_limited_clk_division = true; 13666079e63cSYangbo Lu else 13676079e63cSYangbo Lu esdhc->quirk_limited_clk_division = false; 13686079e63cSYangbo Lu 136948e304ccSYangbo Lu if (soc_device_match(soc_unreliable_pulse_detection)) 137048e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = true; 137148e304ccSYangbo Lu else 137248e304ccSYangbo Lu esdhc->quirk_unreliable_pulse_detection = false; 137348e304ccSYangbo Lu 137467fdfbdfSyinbo.zhu match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); 137567fdfbdfSyinbo.zhu if (match) 137667fdfbdfSyinbo.zhu esdhc->clk_fixup = match->data; 137719c3a0efSyangbo lu np = pdev->dev.of_node; 1378f667216cSYangbo Lu 1379060522d8SChris Packham if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 1380f667216cSYangbo Lu esdhc->quirk_delay_before_data_reset = true; 1381060522d8SChris Packham esdhc->quirk_trans_complete_erratum = true; 1382060522d8SChris Packham } 1383f667216cSYangbo Lu 138419c3a0efSyangbo lu clk = of_clk_get(np, 0); 138519c3a0efSyangbo lu if (!IS_ERR(clk)) { 138619c3a0efSyangbo lu /* 138719c3a0efSyangbo lu * esdhc->peripheral_clock would be assigned with a value 138819c3a0efSyangbo lu * which is eSDHC base clock when use periperal clock. 1389791463baSYangbo Lu * For some platforms, the clock value got by common clk 1390791463baSYangbo Lu * API is peripheral clock while the eSDHC base clock is 1391791463baSYangbo Lu * 1/2 peripheral clock. 139219c3a0efSyangbo lu */ 1393791463baSYangbo Lu if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || 139466a83febSYangbo Lu of_device_is_compatible(np, "fsl,ls1028a-esdhc") || 139566a83febSYangbo Lu of_device_is_compatible(np, "fsl,ls1088a-esdhc")) 139619c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk) / 2; 139719c3a0efSyangbo lu else 139819c3a0efSyangbo lu esdhc->peripheral_clock = clk_get_rate(clk); 139919c3a0efSyangbo lu 140019c3a0efSyangbo lu clk_put(clk); 140119c3a0efSyangbo lu } 140219c3a0efSyangbo lu 140319c3a0efSyangbo lu esdhc_clock_enable(host, false); 140419c3a0efSyangbo lu val = sdhci_readl(host, ESDHC_DMA_SYSCTL); 1405975520fcSYangbo Lu /* 1406975520fcSYangbo Lu * This bit is not able to be reset by SDHCI_RESET_ALL. Need to 1407975520fcSYangbo Lu * initialize it as 1 or 0 once, to override the different value 1408975520fcSYangbo Lu * which may be configured in bootloader. 1409975520fcSYangbo Lu */ 1410975520fcSYangbo Lu if (esdhc->peripheral_clock) 141119c3a0efSyangbo lu val |= ESDHC_PERIPHERAL_CLK_SEL; 1412975520fcSYangbo Lu else 1413975520fcSYangbo Lu val &= ~ESDHC_PERIPHERAL_CLK_SEL; 141419c3a0efSyangbo lu sdhci_writel(host, val, ESDHC_DMA_SYSCTL); 141519c3a0efSyangbo lu esdhc_clock_enable(host, true); 141619c3a0efSyangbo lu } 1417f4932cfdSyangbo lu 141854e08d9aSYangbo Lu static int esdhc_hs400_prepare_ddr(struct mmc_host *mmc) 141954e08d9aSYangbo Lu { 142054e08d9aSYangbo Lu esdhc_tuning_block_enable(mmc_priv(mmc), false); 142154e08d9aSYangbo Lu return 0; 142254e08d9aSYangbo Lu } 142354e08d9aSYangbo Lu 1424c3be1efdSBill Pemberton static int sdhci_esdhc_probe(struct platform_device *pdev) 142538576af1SShawn Guo { 142666b50a00SOded Gabbay struct sdhci_host *host; 142739c86b5cSLiang He struct device_node *np, *tp; 14281ef5e49eSyangbo lu struct sdhci_pltfm_host *pltfm_host; 14291ef5e49eSyangbo lu struct sdhci_esdhc *esdhc; 143066b50a00SOded Gabbay int ret; 143166b50a00SOded Gabbay 1432f4932cfdSyangbo lu np = pdev->dev.of_node; 1433f4932cfdSyangbo lu 1434150d4240SJulia Lawall if (of_property_read_bool(np, "little-endian")) 14358605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, 14368605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1437f4932cfdSyangbo lu else 14388605e7aeSJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, 14398605e7aeSJisheng Zhang sizeof(struct sdhci_esdhc)); 1440f4932cfdSyangbo lu 144166b50a00SOded Gabbay if (IS_ERR(host)) 144266b50a00SOded Gabbay return PTR_ERR(host); 144366b50a00SOded Gabbay 1444ea35645aSyangbo lu host->mmc_host_ops.start_signal_voltage_switch = 1445ea35645aSyangbo lu esdhc_signal_voltage_switch; 1446ba49cbd0Syangbo lu host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; 144754e08d9aSYangbo Lu host->mmc_host_ops.hs400_prepare_ddr = esdhc_hs400_prepare_ddr; 14486b236f37Syangbo lu host->tuning_delay = 1; 1449ea35645aSyangbo lu 1450f4932cfdSyangbo lu esdhc_init(pdev, host); 1451f4932cfdSyangbo lu 145266b50a00SOded Gabbay sdhci_get_of_property(pdev); 145366b50a00SOded Gabbay 14541ef5e49eSyangbo lu pltfm_host = sdhci_priv(host); 14558605e7aeSJisheng Zhang esdhc = sdhci_pltfm_priv(pltfm_host); 145622dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type1)) 145722dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = true; 1458b1f378abSYinbo Zhu else 145922dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type1 = false; 146022dc132dSYangbo Lu 146122dc132dSYangbo Lu if (soc_device_match(soc_tuning_erratum_type2)) 146222dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = true; 146322dc132dSYangbo Lu else 146422dc132dSYangbo Lu esdhc->quirk_tuning_erratum_type2 = false; 1465b1f378abSYinbo Zhu 14661ef5e49eSyangbo lu if (esdhc->vendor_ver == VENDOR_V_22) 14671ef5e49eSyangbo lu host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; 14681ef5e49eSyangbo lu 14691ef5e49eSyangbo lu if (esdhc->vendor_ver > VENDOR_V_22) 14701ef5e49eSyangbo lu host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; 14711ef5e49eSyangbo lu 147239c86b5cSLiang He tp = of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"); 147339c86b5cSLiang He if (tp) { 147439c86b5cSLiang He of_node_put(tp); 1475fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; 1476fe0acab4SYangbo Lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 147705cb6b2aSYinbo Zhu } 1478a46e4271SYinbo Zhu 147974fd5e30SYangbo Lu if (of_device_is_compatible(np, "fsl,p5040-esdhc") || 148074fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p5020-esdhc") || 148174fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p4080-esdhc") || 148274fd5e30SYangbo Lu of_device_is_compatible(np, "fsl,p1020-esdhc") || 1483e9acc77dSyangbo lu of_device_is_compatible(np, "fsl,t1040-esdhc")) 148474fd5e30SYangbo Lu host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; 148574fd5e30SYangbo Lu 1486a22950c8Syangbo lu if (of_device_is_compatible(np, "fsl,ls1021a-esdhc")) 1487a22950c8Syangbo lu host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; 1488a22950c8Syangbo lu 14891f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = false; 1490dcaff04dSOded Gabbay if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { 1491dcaff04dSOded Gabbay /* 1492dcaff04dSOded Gabbay * Freescale messed up with P2020 as it has a non-standard 1493dcaff04dSOded Gabbay * host control register 1494dcaff04dSOded Gabbay */ 1495dcaff04dSOded Gabbay host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; 14961f1929f3SYangbo Lu esdhc->quirk_ignore_data_inhibit = true; 1497dcaff04dSOded Gabbay } 1498dcaff04dSOded Gabbay 149966b50a00SOded Gabbay /* call to generic mmc_of_parse to support additional capabilities */ 1500f0991408SUlf Hansson ret = mmc_of_parse(host->mmc); 1501f0991408SUlf Hansson if (ret) 1502f0991408SUlf Hansson goto err; 1503f0991408SUlf Hansson 15046dab809bSAndy Shevchenko mmc_of_parse_voltage(host->mmc, &host->ocr_mask); 150566b50a00SOded Gabbay 150666b50a00SOded Gabbay ret = sdhci_add_host(host); 150766b50a00SOded Gabbay if (ret) 1508f0991408SUlf Hansson goto err; 150966b50a00SOded Gabbay 1510f0991408SUlf Hansson return 0; 1511f0991408SUlf Hansson err: 1512f0991408SUlf Hansson sdhci_pltfm_free(pdev); 151366b50a00SOded Gabbay return ret; 151438576af1SShawn Guo } 151538576af1SShawn Guo 151638576af1SShawn Guo static struct platform_driver sdhci_esdhc_driver = { 151738576af1SShawn Guo .driver = { 151838576af1SShawn Guo .name = "sdhci-esdhc", 151921b2cec6SDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS, 152038576af1SShawn Guo .of_match_table = sdhci_esdhc_of_match, 15219e48b336SUlf Hansson .pm = &esdhc_of_dev_pm_ops, 152238576af1SShawn Guo }, 152338576af1SShawn Guo .probe = sdhci_esdhc_probe, 1524*4a035a41SAdrian Hunter .remove_new = sdhci_pltfm_remove, 152538576af1SShawn Guo }; 152638576af1SShawn Guo 1527d1f81a64SAxel Lin module_platform_driver(sdhci_esdhc_driver); 152838576af1SShawn Guo 152938576af1SShawn Guo MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); 153038576af1SShawn Guo MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " 153138576af1SShawn Guo "Anton Vorontsov <avorontsov@ru.mvista.com>"); 153238576af1SShawn Guo MODULE_LICENSE("GPL v2"); 1533