11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2f52d9c4fSPeter Griffin /* 3f52d9c4fSPeter Griffin * Support for SDHCI on STMicroelectronics SoCs 4f52d9c4fSPeter Griffin * 5f52d9c4fSPeter Griffin * Copyright (C) 2014 STMicroelectronics Ltd 6f52d9c4fSPeter Griffin * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 7f52d9c4fSPeter Griffin * Contributors: Peter Griffin <peter.griffin@linaro.org> 8f52d9c4fSPeter Griffin * 9f52d9c4fSPeter Griffin * Based on sdhci-cns3xxx.c 10f52d9c4fSPeter Griffin */ 11f52d9c4fSPeter Griffin 12f52d9c4fSPeter Griffin #include <linux/io.h> 13f52d9c4fSPeter Griffin #include <linux/of.h> 14f52d9c4fSPeter Griffin #include <linux/module.h> 15f52d9c4fSPeter Griffin #include <linux/err.h> 16f52d9c4fSPeter Griffin #include <linux/mmc/host.h> 17406c2431SPeter Griffin #include <linux/reset.h> 18f52d9c4fSPeter Griffin #include "sdhci-pltfm.h" 19f52d9c4fSPeter Griffin 20406c2431SPeter Griffin struct st_mmc_platform_data { 21406c2431SPeter Griffin struct reset_control *rstc; 223ae50f45SLee Jones struct clk *icnclk; 23406c2431SPeter Griffin void __iomem *top_ioaddr; 24406c2431SPeter Griffin }; 25406c2431SPeter Griffin 268bef7178SPeter Griffin /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */ 278bef7178SPeter Griffin 288bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_1 0x400 298bef7178SPeter Griffin #define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24) 308bef7178SPeter Griffin #define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12) 318bef7178SPeter Griffin #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT BIT(8) 328bef7178SPeter Griffin #define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0) 338bef7178SPeter Griffin #define ST_MMC_CCONFIG_1_DEFAULT \ 348bef7178SPeter Griffin ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \ 358bef7178SPeter Griffin (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \ 368bef7178SPeter Griffin (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT)) 378bef7178SPeter Griffin 388bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_2 0x404 398bef7178SPeter Griffin #define ST_MMC_CCONFIG_HIGH_SPEED BIT(28) 408bef7178SPeter Griffin #define ST_MMC_CCONFIG_ADMA2 BIT(24) 418bef7178SPeter Griffin #define ST_MMC_CCONFIG_8BIT BIT(20) 428bef7178SPeter Griffin #define ST_MMC_CCONFIG_MAX_BLK_LEN 16 438bef7178SPeter Griffin #define MAX_BLK_LEN_1024 1 448bef7178SPeter Griffin #define MAX_BLK_LEN_2048 2 458bef7178SPeter Griffin #define BASE_CLK_FREQ_200 0xc8 468bef7178SPeter Griffin #define BASE_CLK_FREQ_100 0x64 478bef7178SPeter Griffin #define BASE_CLK_FREQ_50 0x32 488bef7178SPeter Griffin #define ST_MMC_CCONFIG_2_DEFAULT \ 498bef7178SPeter Griffin (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \ 508bef7178SPeter Griffin ST_MMC_CCONFIG_8BIT | \ 518bef7178SPeter Griffin (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN)) 528bef7178SPeter Griffin 538bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_3 0x408 548bef7178SPeter Griffin #define ST_MMC_CCONFIG_EMMC_SLOT_TYPE BIT(28) 558bef7178SPeter Griffin #define ST_MMC_CCONFIG_64BIT BIT(24) 568bef7178SPeter Griffin #define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20) 578bef7178SPeter Griffin #define ST_MMC_CCONFIG_1P8_VOLT BIT(16) 588bef7178SPeter Griffin #define ST_MMC_CCONFIG_3P0_VOLT BIT(12) 598bef7178SPeter Griffin #define ST_MMC_CCONFIG_3P3_VOLT BIT(8) 608bef7178SPeter Griffin #define ST_MMC_CCONFIG_SUSP_RES_SUPPORT BIT(4) 618bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDMA BIT(0) 628bef7178SPeter Griffin #define ST_MMC_CCONFIG_3_DEFAULT \ 638bef7178SPeter Griffin (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \ 648bef7178SPeter Griffin ST_MMC_CCONFIG_3P3_VOLT | \ 658bef7178SPeter Griffin ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \ 668bef7178SPeter Griffin ST_MMC_CCONFIG_SDMA) 678bef7178SPeter Griffin 688bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_4 0x40c 698bef7178SPeter Griffin #define ST_MMC_CCONFIG_D_DRIVER BIT(20) 708bef7178SPeter Griffin #define ST_MMC_CCONFIG_C_DRIVER BIT(16) 718bef7178SPeter Griffin #define ST_MMC_CCONFIG_A_DRIVER BIT(12) 728bef7178SPeter Griffin #define ST_MMC_CCONFIG_DDR50 BIT(8) 738bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDR104 BIT(4) 748bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDR50 BIT(0) 758bef7178SPeter Griffin #define ST_MMC_CCONFIG_4_DEFAULT 0 768bef7178SPeter Griffin 778bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_5 0x410 788bef7178SPeter Griffin #define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8) 798bef7178SPeter Griffin #define RETUNING_TIMER_CNT_MAX 0xf 808bef7178SPeter Griffin #define ST_MMC_CCONFIG_5_DEFAULT 0 818bef7178SPeter Griffin 828bef7178SPeter Griffin /* I/O configuration for Arasan IP */ 838bef7178SPeter Griffin #define ST_MMC_GP_OUTPUT 0x450 848bef7178SPeter Griffin #define ST_MMC_GP_OUTPUT_CD BIT(12) 858bef7178SPeter Griffin 868bef7178SPeter Griffin #define ST_MMC_STATUS_R 0x460 878bef7178SPeter Griffin 888bef7178SPeter Griffin #define ST_TOP_MMC_DLY_FIX_OFF(x) (x - 0x8) 898bef7178SPeter Griffin 908bef7178SPeter Griffin /* TOP config registers to manage static and dynamic delay */ 918bef7178SPeter Griffin #define ST_TOP_MMC_TX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0x8) 928bef7178SPeter Griffin #define ST_TOP_MMC_RX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0xc) 938bef7178SPeter Griffin /* MMC delay control register */ 948bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL ST_TOP_MMC_DLY_FIX_OFF(0x18) 958bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD BIT(0) 968bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL BIT(1) 978bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE BIT(8) 988bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE BIT(9) 998bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY BIT(10) 1008bef7178SPeter Griffin #define ST_TOP_MMC_START_DLL_LOCK BIT(11) 1018bef7178SPeter Griffin 1028bef7178SPeter Griffin /* register to provide the phase-shift value for DLL */ 1038bef7178SPeter Griffin #define ST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c) 1048bef7178SPeter Griffin #define ST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20) 1058bef7178SPeter Griffin #define ST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24) 1068bef7178SPeter Griffin 1078bef7178SPeter Griffin /* phase shift delay on the tx clk 2.188ns */ 1088bef7178SPeter Griffin #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID 0x6 1098bef7178SPeter Griffin 1108bef7178SPeter Griffin #define ST_TOP_MMC_DLY_MAX 0xf 1118bef7178SPeter Griffin 1128bef7178SPeter Griffin #define ST_TOP_MMC_DYN_DLY_CONF \ 1138bef7178SPeter Griffin (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \ 1148bef7178SPeter Griffin ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \ 1158bef7178SPeter Griffin ST_TOP_MMC_START_DLL_LOCK) 1168bef7178SPeter Griffin 117bfa44804SPeter Griffin /* 118bfa44804SPeter Griffin * For clock speeds greater than 90MHz, we need to check that the 119bfa44804SPeter Griffin * DLL procedure has finished before switching to ultra-speed modes. 120bfa44804SPeter Griffin */ 121bfa44804SPeter Griffin #define CLK_TO_CHECK_DLL_LOCK 90000000 122bfa44804SPeter Griffin 123bfa44804SPeter Griffin static inline void st_mmcss_set_static_delay(void __iomem *ioaddr) 124bfa44804SPeter Griffin { 125bfa44804SPeter Griffin if (!ioaddr) 126bfa44804SPeter Griffin return; 127bfa44804SPeter Griffin 128bfa44804SPeter Griffin writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL); 129bfa44804SPeter Griffin writel_relaxed(ST_TOP_MMC_DLY_MAX, 130bfa44804SPeter Griffin ioaddr + ST_TOP_MMC_TX_CLK_DLY); 131bfa44804SPeter Griffin } 132bfa44804SPeter Griffin 1332053812fSPeter Griffin /** 1342053812fSPeter Griffin * st_mmcss_cconfig: configure the Arasan HC inside the flashSS. 1352053812fSPeter Griffin * @np: dt device node. 1362053812fSPeter Griffin * @host: sdhci host 1372053812fSPeter Griffin * Description: this function is to configure the Arasan host controller. 1382053812fSPeter Griffin * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated 1392053812fSPeter Griffin * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5 1402053812fSPeter Griffin * or eMMC4.3. This has to be done before registering the sdhci host. 1412053812fSPeter Griffin */ 1422053812fSPeter Griffin static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host) 1432053812fSPeter Griffin { 1442053812fSPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1452053812fSPeter Griffin struct mmc_host *mhost = host->mmc; 1462053812fSPeter Griffin u32 cconf2, cconf3, cconf4, cconf5; 1472053812fSPeter Griffin 1482053812fSPeter Griffin if (!of_device_is_compatible(np, "st,sdhci-stih407")) 1492053812fSPeter Griffin return; 1502053812fSPeter Griffin 1512053812fSPeter Griffin cconf2 = ST_MMC_CCONFIG_2_DEFAULT; 1522053812fSPeter Griffin cconf3 = ST_MMC_CCONFIG_3_DEFAULT; 1532053812fSPeter Griffin cconf4 = ST_MMC_CCONFIG_4_DEFAULT; 1542053812fSPeter Griffin cconf5 = ST_MMC_CCONFIG_5_DEFAULT; 1552053812fSPeter Griffin 1562053812fSPeter Griffin writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT, 1572053812fSPeter Griffin host->ioaddr + ST_MMC_CCONFIG_REG_1); 1582053812fSPeter Griffin 1592053812fSPeter Griffin /* Set clock frequency, default to 50MHz if max-frequency is not 1602053812fSPeter Griffin * provided */ 1612053812fSPeter Griffin 1622053812fSPeter Griffin switch (mhost->f_max) { 1632053812fSPeter Griffin case 200000000: 1642053812fSPeter Griffin clk_set_rate(pltfm_host->clk, mhost->f_max); 1652053812fSPeter Griffin cconf2 |= BASE_CLK_FREQ_200; 1662053812fSPeter Griffin break; 1672053812fSPeter Griffin case 100000000: 1682053812fSPeter Griffin clk_set_rate(pltfm_host->clk, mhost->f_max); 1692053812fSPeter Griffin cconf2 |= BASE_CLK_FREQ_100; 1702053812fSPeter Griffin break; 1712053812fSPeter Griffin default: 1722053812fSPeter Griffin clk_set_rate(pltfm_host->clk, 50000000); 1732053812fSPeter Griffin cconf2 |= BASE_CLK_FREQ_50; 1742053812fSPeter Griffin } 1752053812fSPeter Griffin 1762053812fSPeter Griffin writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2); 1772053812fSPeter Griffin 178860951c5SJaehoon Chung if (!mmc_card_is_removable(mhost)) 1792053812fSPeter Griffin cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE; 1802053812fSPeter Griffin else 1812053812fSPeter Griffin /* CARD _D ET_CTRL */ 1822053812fSPeter Griffin writel_relaxed(ST_MMC_GP_OUTPUT_CD, 1832053812fSPeter Griffin host->ioaddr + ST_MMC_GP_OUTPUT); 1842053812fSPeter Griffin 1852053812fSPeter Griffin if (mhost->caps & MMC_CAP_UHS_SDR50) { 1862053812fSPeter Griffin /* use 1.8V */ 1872053812fSPeter Griffin cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; 1882053812fSPeter Griffin cconf4 |= ST_MMC_CCONFIG_SDR50; 1892053812fSPeter Griffin /* Use tuning */ 1902053812fSPeter Griffin cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50; 1912053812fSPeter Griffin /* Max timeout for retuning */ 1922053812fSPeter Griffin cconf5 |= RETUNING_TIMER_CNT_MAX; 1932053812fSPeter Griffin } 1942053812fSPeter Griffin 1952053812fSPeter Griffin if (mhost->caps & MMC_CAP_UHS_SDR104) { 1962053812fSPeter Griffin /* 1972053812fSPeter Griffin * SDR104 implies the HC can support HS200 mode, so 1982053812fSPeter Griffin * it's mandatory to use 1.8V 1992053812fSPeter Griffin */ 2002053812fSPeter Griffin cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; 2012053812fSPeter Griffin cconf4 |= ST_MMC_CCONFIG_SDR104; 2022053812fSPeter Griffin /* Max timeout for retuning */ 2032053812fSPeter Griffin cconf5 |= RETUNING_TIMER_CNT_MAX; 2042053812fSPeter Griffin } 2052053812fSPeter Griffin 2062053812fSPeter Griffin if (mhost->caps & MMC_CAP_UHS_DDR50) 2072053812fSPeter Griffin cconf4 |= ST_MMC_CCONFIG_DDR50; 2082053812fSPeter Griffin 2092053812fSPeter Griffin writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3); 2102053812fSPeter Griffin writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4); 2112053812fSPeter Griffin writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5); 2122053812fSPeter Griffin } 2132053812fSPeter Griffin 214bfa44804SPeter Griffin static inline void st_mmcss_set_dll(void __iomem *ioaddr) 215bfa44804SPeter Griffin { 216bfa44804SPeter Griffin if (!ioaddr) 217bfa44804SPeter Griffin return; 218bfa44804SPeter Griffin 219bfa44804SPeter Griffin writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, ioaddr + ST_TOP_MMC_DLY_CTRL); 220bfa44804SPeter Griffin writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID, 221bfa44804SPeter Griffin ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY); 222bfa44804SPeter Griffin } 223bfa44804SPeter Griffin 224bfa44804SPeter Griffin static int st_mmcss_lock_dll(void __iomem *ioaddr) 225bfa44804SPeter Griffin { 226bfa44804SPeter Griffin unsigned long curr, value; 227bfa44804SPeter Griffin unsigned long finish = jiffies + HZ; 228bfa44804SPeter Griffin 229bfa44804SPeter Griffin /* Checks if the DLL procedure is finished */ 230bfa44804SPeter Griffin do { 231bfa44804SPeter Griffin curr = jiffies; 232bfa44804SPeter Griffin value = readl(ioaddr + ST_MMC_STATUS_R); 233bfa44804SPeter Griffin if (value & 0x1) 234bfa44804SPeter Griffin return 0; 235bfa44804SPeter Griffin 236bfa44804SPeter Griffin cpu_relax(); 237bfa44804SPeter Griffin } while (!time_after_eq(curr, finish)); 238bfa44804SPeter Griffin 239bfa44804SPeter Griffin return -EBUSY; 240bfa44804SPeter Griffin } 241bfa44804SPeter Griffin 242bfa44804SPeter Griffin static int sdhci_st_set_dll_for_clock(struct sdhci_host *host) 243bfa44804SPeter Griffin { 244bfa44804SPeter Griffin int ret = 0; 245bfa44804SPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 24615316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 247bfa44804SPeter Griffin 248bfa44804SPeter Griffin if (host->clock > CLK_TO_CHECK_DLL_LOCK) { 249bfa44804SPeter Griffin st_mmcss_set_dll(pdata->top_ioaddr); 250bfa44804SPeter Griffin ret = st_mmcss_lock_dll(host->ioaddr); 251bfa44804SPeter Griffin } 252bfa44804SPeter Griffin 253bfa44804SPeter Griffin return ret; 254bfa44804SPeter Griffin } 255bfa44804SPeter Griffin 256cf48d32eSPeter Griffin static void sdhci_st_set_uhs_signaling(struct sdhci_host *host, 257cf48d32eSPeter Griffin unsigned int uhs) 258cf48d32eSPeter Griffin { 259cf48d32eSPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 26015316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 261cf48d32eSPeter Griffin u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 262cf48d32eSPeter Griffin int ret = 0; 263cf48d32eSPeter Griffin 264cf48d32eSPeter Griffin /* Select Bus Speed Mode for host */ 265cf48d32eSPeter Griffin ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 266cf48d32eSPeter Griffin switch (uhs) { 267cf48d32eSPeter Griffin /* 268cf48d32eSPeter Griffin * Set V18_EN -- UHS modes do not work without this. 269cf48d32eSPeter Griffin * does not change signaling voltage 270cf48d32eSPeter Griffin */ 271cf48d32eSPeter Griffin 272cf48d32eSPeter Griffin case MMC_TIMING_UHS_SDR12: 273cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 274cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180; 275cf48d32eSPeter Griffin break; 276cf48d32eSPeter Griffin case MMC_TIMING_UHS_SDR25: 277cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 278cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180; 279cf48d32eSPeter Griffin break; 280cf48d32eSPeter Griffin case MMC_TIMING_UHS_SDR50: 281cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 282cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180; 283cf48d32eSPeter Griffin ret = sdhci_st_set_dll_for_clock(host); 284cf48d32eSPeter Griffin break; 285cf48d32eSPeter Griffin case MMC_TIMING_UHS_SDR104: 286cf48d32eSPeter Griffin case MMC_TIMING_MMC_HS200: 287cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 288cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; 289cf48d32eSPeter Griffin ret = sdhci_st_set_dll_for_clock(host); 290cf48d32eSPeter Griffin break; 291cf48d32eSPeter Griffin case MMC_TIMING_UHS_DDR50: 292cf48d32eSPeter Griffin case MMC_TIMING_MMC_DDR52: 293cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 294cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; 295cf48d32eSPeter Griffin break; 296cf48d32eSPeter Griffin } 297cf48d32eSPeter Griffin 298cf48d32eSPeter Griffin if (ret) 299cf48d32eSPeter Griffin dev_warn(mmc_dev(host->mmc), "Error setting dll for clock " 300cf48d32eSPeter Griffin "(uhs %d)\n", uhs); 301cf48d32eSPeter Griffin 302cf48d32eSPeter Griffin dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2); 303cf48d32eSPeter Griffin 304cf48d32eSPeter Griffin sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 305cf48d32eSPeter Griffin } 306bfa44804SPeter Griffin 307f52d9c4fSPeter Griffin static u32 sdhci_st_readl(struct sdhci_host *host, int reg) 308f52d9c4fSPeter Griffin { 309f52d9c4fSPeter Griffin u32 ret; 310f52d9c4fSPeter Griffin 311f52d9c4fSPeter Griffin switch (reg) { 312f52d9c4fSPeter Griffin case SDHCI_CAPABILITIES: 313f52d9c4fSPeter Griffin ret = readl_relaxed(host->ioaddr + reg); 314f52d9c4fSPeter Griffin /* Support 3.3V and 1.8V */ 315f52d9c4fSPeter Griffin ret &= ~SDHCI_CAN_VDD_300; 316f52d9c4fSPeter Griffin break; 317f52d9c4fSPeter Griffin default: 318f52d9c4fSPeter Griffin ret = readl_relaxed(host->ioaddr + reg); 319f52d9c4fSPeter Griffin } 320f52d9c4fSPeter Griffin return ret; 321f52d9c4fSPeter Griffin } 322f52d9c4fSPeter Griffin 323f52d9c4fSPeter Griffin static const struct sdhci_ops sdhci_st_ops = { 324f52d9c4fSPeter Griffin .get_max_clock = sdhci_pltfm_clk_get_max_clock, 325f52d9c4fSPeter Griffin .set_clock = sdhci_set_clock, 326f52d9c4fSPeter Griffin .set_bus_width = sdhci_set_bus_width, 327f52d9c4fSPeter Griffin .read_l = sdhci_st_readl, 328f52d9c4fSPeter Griffin .reset = sdhci_reset, 329cf48d32eSPeter Griffin .set_uhs_signaling = sdhci_st_set_uhs_signaling, 330f52d9c4fSPeter Griffin }; 331f52d9c4fSPeter Griffin 332f52d9c4fSPeter Griffin static const struct sdhci_pltfm_data sdhci_st_pdata = { 333f52d9c4fSPeter Griffin .ops = &sdhci_st_ops, 334f52d9c4fSPeter Griffin .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 3354e187d31SPeter Griffin SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | 3364e187d31SPeter Griffin SDHCI_QUIRK_NO_HISPD_BIT, 3374e187d31SPeter Griffin .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 3384e187d31SPeter Griffin SDHCI_QUIRK2_STOP_WITH_TC, 339f52d9c4fSPeter Griffin }; 340f52d9c4fSPeter Griffin 341f52d9c4fSPeter Griffin 342f52d9c4fSPeter Griffin static int sdhci_st_probe(struct platform_device *pdev) 343f52d9c4fSPeter Griffin { 3442053812fSPeter Griffin struct device_node *np = pdev->dev.of_node; 345f52d9c4fSPeter Griffin struct sdhci_host *host; 346406c2431SPeter Griffin struct st_mmc_platform_data *pdata; 347f52d9c4fSPeter Griffin struct sdhci_pltfm_host *pltfm_host; 3483ae50f45SLee Jones struct clk *clk, *icnclk; 349f52d9c4fSPeter Griffin int ret = 0; 350f52d9c4fSPeter Griffin u16 host_version; 35115316752SJisheng Zhang struct reset_control *rstc; 352f52d9c4fSPeter Griffin 353f52d9c4fSPeter Griffin clk = devm_clk_get(&pdev->dev, "mmc"); 354f52d9c4fSPeter Griffin if (IS_ERR(clk)) { 355f52d9c4fSPeter Griffin dev_err(&pdev->dev, "Peripheral clk not found\n"); 356f52d9c4fSPeter Griffin return PTR_ERR(clk); 357f52d9c4fSPeter Griffin } 358f52d9c4fSPeter Griffin 3593ae50f45SLee Jones /* ICN clock isn't compulsory, but use it if it's provided. */ 3603ae50f45SLee Jones icnclk = devm_clk_get(&pdev->dev, "icn"); 3613ae50f45SLee Jones if (IS_ERR(icnclk)) 3623ae50f45SLee Jones icnclk = NULL; 3633ae50f45SLee Jones 36495211a98SPhilipp Zabel rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); 36515316752SJisheng Zhang if (IS_ERR(rstc)) 36695211a98SPhilipp Zabel return PTR_ERR(rstc); 36715316752SJisheng Zhang reset_control_deassert(rstc); 368406c2431SPeter Griffin 36915316752SJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata)); 370f52d9c4fSPeter Griffin if (IS_ERR(host)) { 371f52d9c4fSPeter Griffin dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n"); 372406c2431SPeter Griffin ret = PTR_ERR(host); 373406c2431SPeter Griffin goto err_pltfm_init; 374f52d9c4fSPeter Griffin } 375f52d9c4fSPeter Griffin 37615316752SJisheng Zhang pltfm_host = sdhci_priv(host); 37715316752SJisheng Zhang pdata = sdhci_pltfm_priv(pltfm_host); 37815316752SJisheng Zhang pdata->rstc = rstc; 37915316752SJisheng Zhang 380f52d9c4fSPeter Griffin ret = mmc_of_parse(host->mmc); 381f52d9c4fSPeter Griffin if (ret) { 382f52d9c4fSPeter Griffin dev_err(&pdev->dev, "Failed mmc_of_parse\n"); 383fc702cb3SUlf Hansson goto err_of; 384f52d9c4fSPeter Griffin } 385f52d9c4fSPeter Griffin 3867f55eb10SArvind Yadav ret = clk_prepare_enable(clk); 3877f55eb10SArvind Yadav if (ret) { 3887f55eb10SArvind Yadav dev_err(&pdev->dev, "Failed to prepare clock\n"); 3897f55eb10SArvind Yadav goto err_of; 3907f55eb10SArvind Yadav } 3917f55eb10SArvind Yadav 3927f55eb10SArvind Yadav ret = clk_prepare_enable(icnclk); 3937f55eb10SArvind Yadav if (ret) { 3947f55eb10SArvind Yadav dev_err(&pdev->dev, "Failed to prepare icn clock\n"); 3957f55eb10SArvind Yadav goto err_icnclk; 3967f55eb10SArvind Yadav } 397f52d9c4fSPeter Griffin 398406c2431SPeter Griffin /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */ 399*aa857326SLi Zetao pdata->top_ioaddr = devm_platform_ioremap_resource_byname(pdev, "top-mmc-delay"); 40050eae6baSLaibin Qiu if (IS_ERR(pdata->top_ioaddr)) 401406c2431SPeter Griffin pdata->top_ioaddr = NULL; 402406c2431SPeter Griffin 403f52d9c4fSPeter Griffin pltfm_host->clk = clk; 4043ae50f45SLee Jones pdata->icnclk = icnclk; 405f52d9c4fSPeter Griffin 4062053812fSPeter Griffin /* Configure the Arasan HC inside the flashSS */ 4072053812fSPeter Griffin st_mmcss_cconfig(np, host); 4082053812fSPeter Griffin 409f52d9c4fSPeter Griffin ret = sdhci_add_host(host); 410fb8617e1SJisheng Zhang if (ret) 411f52d9c4fSPeter Griffin goto err_out; 412f52d9c4fSPeter Griffin 413f52d9c4fSPeter Griffin host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); 414f52d9c4fSPeter Griffin 415f52d9c4fSPeter Griffin dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n", 416f52d9c4fSPeter Griffin ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT), 417f52d9c4fSPeter Griffin ((host_version & SDHCI_VENDOR_VER_MASK) >> 418f52d9c4fSPeter Griffin SDHCI_VENDOR_VER_SHIFT)); 419f52d9c4fSPeter Griffin 420f52d9c4fSPeter Griffin return 0; 421f52d9c4fSPeter Griffin 422f52d9c4fSPeter Griffin err_out: 4233ae50f45SLee Jones clk_disable_unprepare(icnclk); 4247f55eb10SArvind Yadav err_icnclk: 425f52d9c4fSPeter Griffin clk_disable_unprepare(clk); 426fc702cb3SUlf Hansson err_of: 427f52d9c4fSPeter Griffin sdhci_pltfm_free(pdev); 428406c2431SPeter Griffin err_pltfm_init: 42915316752SJisheng Zhang reset_control_assert(rstc); 430406c2431SPeter Griffin 431406c2431SPeter Griffin return ret; 432406c2431SPeter Griffin } 433406c2431SPeter Griffin 434406c2431SPeter Griffin static int sdhci_st_remove(struct platform_device *pdev) 435406c2431SPeter Griffin { 436406c2431SPeter Griffin struct sdhci_host *host = platform_get_drvdata(pdev); 437406c2431SPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 43815316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 43915316752SJisheng Zhang struct reset_control *rstc = pdata->rstc; 440406c2431SPeter Griffin 441f6c3397dSUwe Kleine-König sdhci_pltfm_unregister(pdev); 442406c2431SPeter Griffin 4433ae50f45SLee Jones clk_disable_unprepare(pdata->icnclk); 4443ae50f45SLee Jones 44515316752SJisheng Zhang reset_control_assert(rstc); 446f52d9c4fSPeter Griffin 447f6c3397dSUwe Kleine-König return 0; 448f52d9c4fSPeter Griffin } 449f52d9c4fSPeter Griffin 450f52d9c4fSPeter Griffin #ifdef CONFIG_PM_SLEEP 451f52d9c4fSPeter Griffin static int sdhci_st_suspend(struct device *dev) 452f52d9c4fSPeter Griffin { 453f52d9c4fSPeter Griffin struct sdhci_host *host = dev_get_drvdata(dev); 454f52d9c4fSPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 45515316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 456d38dcad4SAdrian Hunter int ret; 457f52d9c4fSPeter Griffin 458d38dcad4SAdrian Hunter if (host->tuning_mode != SDHCI_TUNING_MODE_3) 459d38dcad4SAdrian Hunter mmc_retune_needed(host->mmc); 460d38dcad4SAdrian Hunter 461d38dcad4SAdrian Hunter ret = sdhci_suspend_host(host); 462f52d9c4fSPeter Griffin if (ret) 463f52d9c4fSPeter Griffin goto out; 464f52d9c4fSPeter Griffin 465406c2431SPeter Griffin reset_control_assert(pdata->rstc); 466406c2431SPeter Griffin 4673ae50f45SLee Jones clk_disable_unprepare(pdata->icnclk); 468f52d9c4fSPeter Griffin clk_disable_unprepare(pltfm_host->clk); 469f52d9c4fSPeter Griffin out: 470f52d9c4fSPeter Griffin return ret; 471f52d9c4fSPeter Griffin } 472f52d9c4fSPeter Griffin 473f52d9c4fSPeter Griffin static int sdhci_st_resume(struct device *dev) 474f52d9c4fSPeter Griffin { 475f52d9c4fSPeter Griffin struct sdhci_host *host = dev_get_drvdata(dev); 476f52d9c4fSPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 47715316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 4782053812fSPeter Griffin struct device_node *np = dev->of_node; 4797f55eb10SArvind Yadav int ret; 480f52d9c4fSPeter Griffin 4817f55eb10SArvind Yadav ret = clk_prepare_enable(pltfm_host->clk); 4827f55eb10SArvind Yadav if (ret) 4837f55eb10SArvind Yadav return ret; 4847f55eb10SArvind Yadav 4857f55eb10SArvind Yadav ret = clk_prepare_enable(pdata->icnclk); 4867f55eb10SArvind Yadav if (ret) { 4877f55eb10SArvind Yadav clk_disable_unprepare(pltfm_host->clk); 4887f55eb10SArvind Yadav return ret; 4897f55eb10SArvind Yadav } 490f52d9c4fSPeter Griffin 491406c2431SPeter Griffin reset_control_deassert(pdata->rstc); 492406c2431SPeter Griffin 4932053812fSPeter Griffin st_mmcss_cconfig(np, host); 4942053812fSPeter Griffin 495f52d9c4fSPeter Griffin return sdhci_resume_host(host); 496f52d9c4fSPeter Griffin } 497f52d9c4fSPeter Griffin #endif 498f52d9c4fSPeter Griffin 499f52d9c4fSPeter Griffin static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume); 500f52d9c4fSPeter Griffin 501f52d9c4fSPeter Griffin static const struct of_device_id st_sdhci_match[] = { 502f52d9c4fSPeter Griffin { .compatible = "st,sdhci" }, 503f52d9c4fSPeter Griffin {}, 504f52d9c4fSPeter Griffin }; 505f52d9c4fSPeter Griffin 506f52d9c4fSPeter Griffin MODULE_DEVICE_TABLE(of, st_sdhci_match); 507f52d9c4fSPeter Griffin 508f52d9c4fSPeter Griffin static struct platform_driver sdhci_st_driver = { 509f52d9c4fSPeter Griffin .probe = sdhci_st_probe, 510406c2431SPeter Griffin .remove = sdhci_st_remove, 511f52d9c4fSPeter Griffin .driver = { 512f52d9c4fSPeter Griffin .name = "sdhci-st", 51321b2cec6SDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS, 514f52d9c4fSPeter Griffin .pm = &sdhci_st_pmops, 515bf3023e6SKrzysztof Kozlowski .of_match_table = st_sdhci_match, 516f52d9c4fSPeter Griffin }, 517f52d9c4fSPeter Griffin }; 518f52d9c4fSPeter Griffin 519f52d9c4fSPeter Griffin module_platform_driver(sdhci_st_driver); 520f52d9c4fSPeter Griffin 521f52d9c4fSPeter Griffin MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs"); 522f52d9c4fSPeter Griffin MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 523f52d9c4fSPeter Griffin MODULE_LICENSE("GPL v2"); 524e6ac184bSZhangfei Gao MODULE_ALIAS("platform:sdhci-st"); 525