// SPDX-License-Identifier: GPL-2.0-only /* * Support for SDHCI on STMicroelectronics SoCs * * Copyright (C) 2014 STMicroelectronics Ltd * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> * Contributors: Peter Griffin <peter.griffin@linaro.org> * * Based on sdhci-cns3xxx.c
*/
/* register to provide the phase-shift value for DLL */ #define ST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c) #define ST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20) #define ST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24)
/* phase shift delay on the tx clk 2.188ns */ #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID 0x6
/* * For clock speeds greater than 90MHz, we need to check that the * DLL procedure has finished before switching to ultra-speed modes.
*/ #define CLK_TO_CHECK_DLL_LOCK 90000000
staticinlinevoid st_mmcss_set_static_delay(void __iomem *ioaddr)
{ if (!ioaddr) return;
/** * st_mmcss_cconfig: configure the Arasan HC inside the flashSS. * @np: dt device node. * @host: sdhci host * Description: this function is to configure the Arasan host controller. * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5 * or eMMC4.3. This has to be done before registering the sdhci host.
*/ staticvoid st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host)
{ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct mmc_host *mhost = host->mmc;
u32 cconf2, cconf3, cconf4, cconf5;
if (!of_device_is_compatible(np, "st,sdhci-stih407")) return;
if (mhost->caps & MMC_CAP_UHS_SDR50) { /* use 1.8V */
cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
cconf4 |= ST_MMC_CCONFIG_SDR50; /* Use tuning */
cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50; /* Max timeout for retuning */
cconf5 |= RETUNING_TIMER_CNT_MAX;
}
if (mhost->caps & MMC_CAP_UHS_SDR104) { /* * SDR104 implies the HC can support HS200 mode, so * it's mandatory to use 1.8V
*/
cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
cconf4 |= ST_MMC_CCONFIG_SDR104; /* Max timeout for retuning */
cconf5 |= RETUNING_TIMER_CNT_MAX;
}
if (mhost->caps & MMC_CAP_UHS_DDR50)
cconf4 |= ST_MMC_CCONFIG_DDR50;
/* Select Bus Speed Mode for host */
ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; switch (uhs) { /* * Set V18_EN -- UHS modes do not work without this. * does not change signaling voltage
*/
case MMC_TIMING_UHS_SDR12:
st_mmcss_set_static_delay(pdata->top_ioaddr);
ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180; break; case MMC_TIMING_UHS_SDR25:
st_mmcss_set_static_delay(pdata->top_ioaddr);
ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180; break; case MMC_TIMING_UHS_SDR50:
st_mmcss_set_static_delay(pdata->top_ioaddr);
ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
ret = sdhci_st_set_dll_for_clock(host); break; case MMC_TIMING_UHS_SDR104: case MMC_TIMING_MMC_HS200:
st_mmcss_set_static_delay(pdata->top_ioaddr);
ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
ret = sdhci_st_set_dll_for_clock(host); break; case MMC_TIMING_UHS_DDR50: case MMC_TIMING_MMC_DDR52:
st_mmcss_set_static_delay(pdata->top_ioaddr);
ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; break;
}
if (ret)
dev_warn(mmc_dev(host->mmc), "Error setting dll for clock " "(uhs %d)\n", uhs);
static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
{
u32 ret;
switch (reg) { case SDHCI_CAPABILITIES:
ret = readl_relaxed(host->ioaddr + reg); /* Support 3.3V and 1.8V */
ret &= ~SDHCI_CAN_VDD_300; break; default:
ret = readl_relaxed(host->ioaddr + reg);
} return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.