1f52d9c4fSPeter Griffin /* 2f52d9c4fSPeter Griffin * Support for SDHCI on STMicroelectronics SoCs 3f52d9c4fSPeter Griffin * 4f52d9c4fSPeter Griffin * Copyright (C) 2014 STMicroelectronics Ltd 5f52d9c4fSPeter Griffin * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 6f52d9c4fSPeter Griffin * Contributors: Peter Griffin <peter.griffin@linaro.org> 7f52d9c4fSPeter Griffin * 8f52d9c4fSPeter Griffin * Based on sdhci-cns3xxx.c 9f52d9c4fSPeter Griffin * 10f52d9c4fSPeter Griffin * This program is free software; you can redistribute it and/or modify 11f52d9c4fSPeter Griffin * it under the terms of the GNU General Public License version 2 as 12f52d9c4fSPeter Griffin * published by the Free Software Foundation. 13f52d9c4fSPeter Griffin * 14f52d9c4fSPeter Griffin * This program is distributed in the hope that it will be useful, 15f52d9c4fSPeter Griffin * but WITHOUT ANY WARRANTY; without even the implied warranty of 16f52d9c4fSPeter Griffin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17f52d9c4fSPeter Griffin * GNU General Public License for more details. 18f52d9c4fSPeter Griffin * 19f52d9c4fSPeter Griffin */ 20f52d9c4fSPeter Griffin 21f52d9c4fSPeter Griffin #include <linux/io.h> 22f52d9c4fSPeter Griffin #include <linux/of.h> 23f52d9c4fSPeter Griffin #include <linux/module.h> 24f52d9c4fSPeter Griffin #include <linux/err.h> 25f52d9c4fSPeter Griffin #include <linux/mmc/host.h> 26406c2431SPeter Griffin #include <linux/reset.h> 27f52d9c4fSPeter Griffin #include "sdhci-pltfm.h" 28f52d9c4fSPeter Griffin 29406c2431SPeter Griffin struct st_mmc_platform_data { 30406c2431SPeter Griffin struct reset_control *rstc; 31406c2431SPeter Griffin void __iomem *top_ioaddr; 32406c2431SPeter Griffin }; 33406c2431SPeter Griffin 348bef7178SPeter Griffin /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */ 358bef7178SPeter Griffin 368bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_1 0x400 378bef7178SPeter Griffin #define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24) 388bef7178SPeter Griffin #define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12) 398bef7178SPeter Griffin #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT BIT(8) 408bef7178SPeter Griffin #define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0) 418bef7178SPeter Griffin #define ST_MMC_CCONFIG_1_DEFAULT \ 428bef7178SPeter Griffin ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \ 438bef7178SPeter Griffin (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \ 448bef7178SPeter Griffin (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT)) 458bef7178SPeter Griffin 468bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_2 0x404 478bef7178SPeter Griffin #define ST_MMC_CCONFIG_HIGH_SPEED BIT(28) 488bef7178SPeter Griffin #define ST_MMC_CCONFIG_ADMA2 BIT(24) 498bef7178SPeter Griffin #define ST_MMC_CCONFIG_8BIT BIT(20) 508bef7178SPeter Griffin #define ST_MMC_CCONFIG_MAX_BLK_LEN 16 518bef7178SPeter Griffin #define MAX_BLK_LEN_1024 1 528bef7178SPeter Griffin #define MAX_BLK_LEN_2048 2 538bef7178SPeter Griffin #define BASE_CLK_FREQ_200 0xc8 548bef7178SPeter Griffin #define BASE_CLK_FREQ_100 0x64 558bef7178SPeter Griffin #define BASE_CLK_FREQ_50 0x32 568bef7178SPeter Griffin #define ST_MMC_CCONFIG_2_DEFAULT \ 578bef7178SPeter Griffin (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \ 588bef7178SPeter Griffin ST_MMC_CCONFIG_8BIT | \ 598bef7178SPeter Griffin (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN)) 608bef7178SPeter Griffin 618bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_3 0x408 628bef7178SPeter Griffin #define ST_MMC_CCONFIG_EMMC_SLOT_TYPE BIT(28) 638bef7178SPeter Griffin #define ST_MMC_CCONFIG_64BIT BIT(24) 648bef7178SPeter Griffin #define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20) 658bef7178SPeter Griffin #define ST_MMC_CCONFIG_1P8_VOLT BIT(16) 668bef7178SPeter Griffin #define ST_MMC_CCONFIG_3P0_VOLT BIT(12) 678bef7178SPeter Griffin #define ST_MMC_CCONFIG_3P3_VOLT BIT(8) 688bef7178SPeter Griffin #define ST_MMC_CCONFIG_SUSP_RES_SUPPORT BIT(4) 698bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDMA BIT(0) 708bef7178SPeter Griffin #define ST_MMC_CCONFIG_3_DEFAULT \ 718bef7178SPeter Griffin (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \ 728bef7178SPeter Griffin ST_MMC_CCONFIG_3P3_VOLT | \ 738bef7178SPeter Griffin ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \ 748bef7178SPeter Griffin ST_MMC_CCONFIG_SDMA) 758bef7178SPeter Griffin 768bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_4 0x40c 778bef7178SPeter Griffin #define ST_MMC_CCONFIG_D_DRIVER BIT(20) 788bef7178SPeter Griffin #define ST_MMC_CCONFIG_C_DRIVER BIT(16) 798bef7178SPeter Griffin #define ST_MMC_CCONFIG_A_DRIVER BIT(12) 808bef7178SPeter Griffin #define ST_MMC_CCONFIG_DDR50 BIT(8) 818bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDR104 BIT(4) 828bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDR50 BIT(0) 838bef7178SPeter Griffin #define ST_MMC_CCONFIG_4_DEFAULT 0 848bef7178SPeter Griffin 858bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_5 0x410 868bef7178SPeter Griffin #define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8) 878bef7178SPeter Griffin #define RETUNING_TIMER_CNT_MAX 0xf 888bef7178SPeter Griffin #define ST_MMC_CCONFIG_5_DEFAULT 0 898bef7178SPeter Griffin 908bef7178SPeter Griffin /* I/O configuration for Arasan IP */ 918bef7178SPeter Griffin #define ST_MMC_GP_OUTPUT 0x450 928bef7178SPeter Griffin #define ST_MMC_GP_OUTPUT_CD BIT(12) 938bef7178SPeter Griffin 948bef7178SPeter Griffin #define ST_MMC_STATUS_R 0x460 958bef7178SPeter Griffin 968bef7178SPeter Griffin #define ST_TOP_MMC_DLY_FIX_OFF(x) (x - 0x8) 978bef7178SPeter Griffin 988bef7178SPeter Griffin /* TOP config registers to manage static and dynamic delay */ 998bef7178SPeter Griffin #define ST_TOP_MMC_TX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0x8) 1008bef7178SPeter Griffin #define ST_TOP_MMC_RX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0xc) 1018bef7178SPeter Griffin /* MMC delay control register */ 1028bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL ST_TOP_MMC_DLY_FIX_OFF(0x18) 1038bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD BIT(0) 1048bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL BIT(1) 1058bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE BIT(8) 1068bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE BIT(9) 1078bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY BIT(10) 1088bef7178SPeter Griffin #define ST_TOP_MMC_START_DLL_LOCK BIT(11) 1098bef7178SPeter Griffin 1108bef7178SPeter Griffin /* register to provide the phase-shift value for DLL */ 1118bef7178SPeter Griffin #define ST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c) 1128bef7178SPeter Griffin #define ST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20) 1138bef7178SPeter Griffin #define ST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24) 1148bef7178SPeter Griffin 1158bef7178SPeter Griffin /* phase shift delay on the tx clk 2.188ns */ 1168bef7178SPeter Griffin #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID 0x6 1178bef7178SPeter Griffin 1188bef7178SPeter Griffin #define ST_TOP_MMC_DLY_MAX 0xf 1198bef7178SPeter Griffin 1208bef7178SPeter Griffin #define ST_TOP_MMC_DYN_DLY_CONF \ 1218bef7178SPeter Griffin (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \ 1228bef7178SPeter Griffin ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \ 1238bef7178SPeter Griffin ST_TOP_MMC_START_DLL_LOCK) 1248bef7178SPeter Griffin 125bfa44804SPeter Griffin /* 126bfa44804SPeter Griffin * For clock speeds greater than 90MHz, we need to check that the 127bfa44804SPeter Griffin * DLL procedure has finished before switching to ultra-speed modes. 128bfa44804SPeter Griffin */ 129bfa44804SPeter Griffin #define CLK_TO_CHECK_DLL_LOCK 90000000 130bfa44804SPeter Griffin 131bfa44804SPeter Griffin static inline void st_mmcss_set_static_delay(void __iomem *ioaddr) 132bfa44804SPeter Griffin { 133bfa44804SPeter Griffin if (!ioaddr) 134bfa44804SPeter Griffin return; 135bfa44804SPeter Griffin 136bfa44804SPeter Griffin writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL); 137bfa44804SPeter Griffin writel_relaxed(ST_TOP_MMC_DLY_MAX, 138bfa44804SPeter Griffin ioaddr + ST_TOP_MMC_TX_CLK_DLY); 139bfa44804SPeter Griffin } 140bfa44804SPeter Griffin 1412053812fSPeter Griffin /** 1422053812fSPeter Griffin * st_mmcss_cconfig: configure the Arasan HC inside the flashSS. 1432053812fSPeter Griffin * @np: dt device node. 1442053812fSPeter Griffin * @host: sdhci host 1452053812fSPeter Griffin * Description: this function is to configure the Arasan host controller. 1462053812fSPeter Griffin * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated 1472053812fSPeter Griffin * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5 1482053812fSPeter Griffin * or eMMC4.3. This has to be done before registering the sdhci host. 1492053812fSPeter Griffin */ 1502053812fSPeter Griffin static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host) 1512053812fSPeter Griffin { 1522053812fSPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 1532053812fSPeter Griffin struct mmc_host *mhost = host->mmc; 1542053812fSPeter Griffin u32 cconf2, cconf3, cconf4, cconf5; 1552053812fSPeter Griffin 1562053812fSPeter Griffin if (!of_device_is_compatible(np, "st,sdhci-stih407")) 1572053812fSPeter Griffin return; 1582053812fSPeter Griffin 1592053812fSPeter Griffin cconf2 = ST_MMC_CCONFIG_2_DEFAULT; 1602053812fSPeter Griffin cconf3 = ST_MMC_CCONFIG_3_DEFAULT; 1612053812fSPeter Griffin cconf4 = ST_MMC_CCONFIG_4_DEFAULT; 1622053812fSPeter Griffin cconf5 = ST_MMC_CCONFIG_5_DEFAULT; 1632053812fSPeter Griffin 1642053812fSPeter Griffin writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT, 1652053812fSPeter Griffin host->ioaddr + ST_MMC_CCONFIG_REG_1); 1662053812fSPeter Griffin 1672053812fSPeter Griffin /* Set clock frequency, default to 50MHz if max-frequency is not 1682053812fSPeter Griffin * provided */ 1692053812fSPeter Griffin 1702053812fSPeter Griffin switch (mhost->f_max) { 1712053812fSPeter Griffin case 200000000: 1722053812fSPeter Griffin clk_set_rate(pltfm_host->clk, mhost->f_max); 1732053812fSPeter Griffin cconf2 |= BASE_CLK_FREQ_200; 1742053812fSPeter Griffin break; 1752053812fSPeter Griffin case 100000000: 1762053812fSPeter Griffin clk_set_rate(pltfm_host->clk, mhost->f_max); 1772053812fSPeter Griffin cconf2 |= BASE_CLK_FREQ_100; 1782053812fSPeter Griffin break; 1792053812fSPeter Griffin default: 1802053812fSPeter Griffin clk_set_rate(pltfm_host->clk, 50000000); 1812053812fSPeter Griffin cconf2 |= BASE_CLK_FREQ_50; 1822053812fSPeter Griffin } 1832053812fSPeter Griffin 1842053812fSPeter Griffin writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2); 1852053812fSPeter Griffin 186860951c5SJaehoon Chung if (!mmc_card_is_removable(mhost)) 1872053812fSPeter Griffin cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE; 1882053812fSPeter Griffin else 1892053812fSPeter Griffin /* CARD _D ET_CTRL */ 1902053812fSPeter Griffin writel_relaxed(ST_MMC_GP_OUTPUT_CD, 1912053812fSPeter Griffin host->ioaddr + ST_MMC_GP_OUTPUT); 1922053812fSPeter Griffin 1932053812fSPeter Griffin if (mhost->caps & MMC_CAP_UHS_SDR50) { 1942053812fSPeter Griffin /* use 1.8V */ 1952053812fSPeter Griffin cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; 1962053812fSPeter Griffin cconf4 |= ST_MMC_CCONFIG_SDR50; 1972053812fSPeter Griffin /* Use tuning */ 1982053812fSPeter Griffin cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50; 1992053812fSPeter Griffin /* Max timeout for retuning */ 2002053812fSPeter Griffin cconf5 |= RETUNING_TIMER_CNT_MAX; 2012053812fSPeter Griffin } 2022053812fSPeter Griffin 2032053812fSPeter Griffin if (mhost->caps & MMC_CAP_UHS_SDR104) { 2042053812fSPeter Griffin /* 2052053812fSPeter Griffin * SDR104 implies the HC can support HS200 mode, so 2062053812fSPeter Griffin * it's mandatory to use 1.8V 2072053812fSPeter Griffin */ 2082053812fSPeter Griffin cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; 2092053812fSPeter Griffin cconf4 |= ST_MMC_CCONFIG_SDR104; 2102053812fSPeter Griffin /* Max timeout for retuning */ 2112053812fSPeter Griffin cconf5 |= RETUNING_TIMER_CNT_MAX; 2122053812fSPeter Griffin } 2132053812fSPeter Griffin 2142053812fSPeter Griffin if (mhost->caps & MMC_CAP_UHS_DDR50) 2152053812fSPeter Griffin cconf4 |= ST_MMC_CCONFIG_DDR50; 2162053812fSPeter Griffin 2172053812fSPeter Griffin writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3); 2182053812fSPeter Griffin writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4); 2192053812fSPeter Griffin writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5); 2202053812fSPeter Griffin } 2212053812fSPeter Griffin 222bfa44804SPeter Griffin static inline void st_mmcss_set_dll(void __iomem *ioaddr) 223bfa44804SPeter Griffin { 224bfa44804SPeter Griffin if (!ioaddr) 225bfa44804SPeter Griffin return; 226bfa44804SPeter Griffin 227bfa44804SPeter Griffin writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, ioaddr + ST_TOP_MMC_DLY_CTRL); 228bfa44804SPeter Griffin writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID, 229bfa44804SPeter Griffin ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY); 230bfa44804SPeter Griffin } 231bfa44804SPeter Griffin 232bfa44804SPeter Griffin static int st_mmcss_lock_dll(void __iomem *ioaddr) 233bfa44804SPeter Griffin { 234bfa44804SPeter Griffin unsigned long curr, value; 235bfa44804SPeter Griffin unsigned long finish = jiffies + HZ; 236bfa44804SPeter Griffin 237bfa44804SPeter Griffin /* Checks if the DLL procedure is finished */ 238bfa44804SPeter Griffin do { 239bfa44804SPeter Griffin curr = jiffies; 240bfa44804SPeter Griffin value = readl(ioaddr + ST_MMC_STATUS_R); 241bfa44804SPeter Griffin if (value & 0x1) 242bfa44804SPeter Griffin return 0; 243bfa44804SPeter Griffin 244bfa44804SPeter Griffin cpu_relax(); 245bfa44804SPeter Griffin } while (!time_after_eq(curr, finish)); 246bfa44804SPeter Griffin 247bfa44804SPeter Griffin return -EBUSY; 248bfa44804SPeter Griffin } 249bfa44804SPeter Griffin 250bfa44804SPeter Griffin static int sdhci_st_set_dll_for_clock(struct sdhci_host *host) 251bfa44804SPeter Griffin { 252bfa44804SPeter Griffin int ret = 0; 253bfa44804SPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 25415316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 255bfa44804SPeter Griffin 256bfa44804SPeter Griffin if (host->clock > CLK_TO_CHECK_DLL_LOCK) { 257bfa44804SPeter Griffin st_mmcss_set_dll(pdata->top_ioaddr); 258bfa44804SPeter Griffin ret = st_mmcss_lock_dll(host->ioaddr); 259bfa44804SPeter Griffin } 260bfa44804SPeter Griffin 261bfa44804SPeter Griffin return ret; 262bfa44804SPeter Griffin } 263bfa44804SPeter Griffin 264cf48d32eSPeter Griffin static void sdhci_st_set_uhs_signaling(struct sdhci_host *host, 265cf48d32eSPeter Griffin unsigned int uhs) 266cf48d32eSPeter Griffin { 267cf48d32eSPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 26815316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 269cf48d32eSPeter Griffin u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 270cf48d32eSPeter Griffin int ret = 0; 271cf48d32eSPeter Griffin 272cf48d32eSPeter Griffin /* Select Bus Speed Mode for host */ 273cf48d32eSPeter Griffin ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 274cf48d32eSPeter Griffin switch (uhs) { 275cf48d32eSPeter Griffin /* 276cf48d32eSPeter Griffin * Set V18_EN -- UHS modes do not work without this. 277cf48d32eSPeter Griffin * does not change signaling voltage 278cf48d32eSPeter Griffin */ 279cf48d32eSPeter Griffin 280cf48d32eSPeter Griffin case MMC_TIMING_UHS_SDR12: 281cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 282cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180; 283cf48d32eSPeter Griffin break; 284cf48d32eSPeter Griffin case MMC_TIMING_UHS_SDR25: 285cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 286cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180; 287cf48d32eSPeter Griffin break; 288cf48d32eSPeter Griffin case MMC_TIMING_UHS_SDR50: 289cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 290cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180; 291cf48d32eSPeter Griffin ret = sdhci_st_set_dll_for_clock(host); 292cf48d32eSPeter Griffin break; 293cf48d32eSPeter Griffin case MMC_TIMING_UHS_SDR104: 294cf48d32eSPeter Griffin case MMC_TIMING_MMC_HS200: 295cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 296cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; 297cf48d32eSPeter Griffin ret = sdhci_st_set_dll_for_clock(host); 298cf48d32eSPeter Griffin break; 299cf48d32eSPeter Griffin case MMC_TIMING_UHS_DDR50: 300cf48d32eSPeter Griffin case MMC_TIMING_MMC_DDR52: 301cf48d32eSPeter Griffin st_mmcss_set_static_delay(pdata->top_ioaddr); 302cf48d32eSPeter Griffin ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; 303cf48d32eSPeter Griffin break; 304cf48d32eSPeter Griffin } 305cf48d32eSPeter Griffin 306cf48d32eSPeter Griffin if (ret) 307cf48d32eSPeter Griffin dev_warn(mmc_dev(host->mmc), "Error setting dll for clock " 308cf48d32eSPeter Griffin "(uhs %d)\n", uhs); 309cf48d32eSPeter Griffin 310cf48d32eSPeter Griffin dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2); 311cf48d32eSPeter Griffin 312cf48d32eSPeter Griffin sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 313cf48d32eSPeter Griffin } 314bfa44804SPeter Griffin 315f52d9c4fSPeter Griffin static u32 sdhci_st_readl(struct sdhci_host *host, int reg) 316f52d9c4fSPeter Griffin { 317f52d9c4fSPeter Griffin u32 ret; 318f52d9c4fSPeter Griffin 319f52d9c4fSPeter Griffin switch (reg) { 320f52d9c4fSPeter Griffin case SDHCI_CAPABILITIES: 321f52d9c4fSPeter Griffin ret = readl_relaxed(host->ioaddr + reg); 322f52d9c4fSPeter Griffin /* Support 3.3V and 1.8V */ 323f52d9c4fSPeter Griffin ret &= ~SDHCI_CAN_VDD_300; 324f52d9c4fSPeter Griffin break; 325f52d9c4fSPeter Griffin default: 326f52d9c4fSPeter Griffin ret = readl_relaxed(host->ioaddr + reg); 327f52d9c4fSPeter Griffin } 328f52d9c4fSPeter Griffin return ret; 329f52d9c4fSPeter Griffin } 330f52d9c4fSPeter Griffin 331f52d9c4fSPeter Griffin static const struct sdhci_ops sdhci_st_ops = { 332f52d9c4fSPeter Griffin .get_max_clock = sdhci_pltfm_clk_get_max_clock, 333f52d9c4fSPeter Griffin .set_clock = sdhci_set_clock, 334f52d9c4fSPeter Griffin .set_bus_width = sdhci_set_bus_width, 335f52d9c4fSPeter Griffin .read_l = sdhci_st_readl, 336f52d9c4fSPeter Griffin .reset = sdhci_reset, 337cf48d32eSPeter Griffin .set_uhs_signaling = sdhci_st_set_uhs_signaling, 338f52d9c4fSPeter Griffin }; 339f52d9c4fSPeter Griffin 340f52d9c4fSPeter Griffin static const struct sdhci_pltfm_data sdhci_st_pdata = { 341f52d9c4fSPeter Griffin .ops = &sdhci_st_ops, 342f52d9c4fSPeter Griffin .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 3434e187d31SPeter Griffin SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | 3444e187d31SPeter Griffin SDHCI_QUIRK_NO_HISPD_BIT, 3454e187d31SPeter Griffin .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 3464e187d31SPeter Griffin SDHCI_QUIRK2_STOP_WITH_TC, 347f52d9c4fSPeter Griffin }; 348f52d9c4fSPeter Griffin 349f52d9c4fSPeter Griffin 350f52d9c4fSPeter Griffin static int sdhci_st_probe(struct platform_device *pdev) 351f52d9c4fSPeter Griffin { 3522053812fSPeter Griffin struct device_node *np = pdev->dev.of_node; 353f52d9c4fSPeter Griffin struct sdhci_host *host; 354406c2431SPeter Griffin struct st_mmc_platform_data *pdata; 355f52d9c4fSPeter Griffin struct sdhci_pltfm_host *pltfm_host; 356f52d9c4fSPeter Griffin struct clk *clk; 357f52d9c4fSPeter Griffin int ret = 0; 358f52d9c4fSPeter Griffin u16 host_version; 359406c2431SPeter Griffin struct resource *res; 36015316752SJisheng Zhang struct reset_control *rstc; 361f52d9c4fSPeter Griffin 362f52d9c4fSPeter Griffin clk = devm_clk_get(&pdev->dev, "mmc"); 363f52d9c4fSPeter Griffin if (IS_ERR(clk)) { 364f52d9c4fSPeter Griffin dev_err(&pdev->dev, "Peripheral clk not found\n"); 365f52d9c4fSPeter Griffin return PTR_ERR(clk); 366f52d9c4fSPeter Griffin } 367f52d9c4fSPeter Griffin 36815316752SJisheng Zhang rstc = devm_reset_control_get(&pdev->dev, NULL); 36915316752SJisheng Zhang if (IS_ERR(rstc)) 37015316752SJisheng Zhang rstc = NULL; 371406c2431SPeter Griffin else 37215316752SJisheng Zhang reset_control_deassert(rstc); 373406c2431SPeter Griffin 37415316752SJisheng Zhang host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata)); 375f52d9c4fSPeter Griffin if (IS_ERR(host)) { 376f52d9c4fSPeter Griffin dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n"); 377406c2431SPeter Griffin ret = PTR_ERR(host); 378406c2431SPeter Griffin goto err_pltfm_init; 379f52d9c4fSPeter Griffin } 380f52d9c4fSPeter Griffin 38115316752SJisheng Zhang pltfm_host = sdhci_priv(host); 38215316752SJisheng Zhang pdata = sdhci_pltfm_priv(pltfm_host); 38315316752SJisheng Zhang pdata->rstc = rstc; 38415316752SJisheng Zhang 385f52d9c4fSPeter Griffin ret = mmc_of_parse(host->mmc); 386f52d9c4fSPeter Griffin if (ret) { 387f52d9c4fSPeter Griffin dev_err(&pdev->dev, "Failed mmc_of_parse\n"); 388fc702cb3SUlf Hansson goto err_of; 389f52d9c4fSPeter Griffin } 390f52d9c4fSPeter Griffin 391f52d9c4fSPeter Griffin clk_prepare_enable(clk); 392f52d9c4fSPeter Griffin 393406c2431SPeter Griffin /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */ 394406c2431SPeter Griffin res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 395406c2431SPeter Griffin "top-mmc-delay"); 396406c2431SPeter Griffin pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res); 397406c2431SPeter Griffin if (IS_ERR(pdata->top_ioaddr)) { 398406c2431SPeter Griffin dev_warn(&pdev->dev, "FlashSS Top Dly registers not available"); 399406c2431SPeter Griffin pdata->top_ioaddr = NULL; 400406c2431SPeter Griffin } 401406c2431SPeter Griffin 402f52d9c4fSPeter Griffin pltfm_host->clk = clk; 403f52d9c4fSPeter Griffin 4042053812fSPeter Griffin /* Configure the Arasan HC inside the flashSS */ 4052053812fSPeter Griffin st_mmcss_cconfig(np, host); 4062053812fSPeter Griffin 407f52d9c4fSPeter Griffin ret = sdhci_add_host(host); 408f52d9c4fSPeter Griffin if (ret) { 409f52d9c4fSPeter Griffin dev_err(&pdev->dev, "Failed sdhci_add_host\n"); 410f52d9c4fSPeter Griffin goto err_out; 411f52d9c4fSPeter Griffin } 412f52d9c4fSPeter Griffin 413f52d9c4fSPeter Griffin platform_set_drvdata(pdev, host); 414f52d9c4fSPeter Griffin 415f52d9c4fSPeter Griffin host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); 416f52d9c4fSPeter Griffin 417f52d9c4fSPeter Griffin dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n", 418f52d9c4fSPeter Griffin ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT), 419f52d9c4fSPeter Griffin ((host_version & SDHCI_VENDOR_VER_MASK) >> 420f52d9c4fSPeter Griffin SDHCI_VENDOR_VER_SHIFT)); 421f52d9c4fSPeter Griffin 422f52d9c4fSPeter Griffin return 0; 423f52d9c4fSPeter Griffin 424f52d9c4fSPeter Griffin err_out: 425f52d9c4fSPeter Griffin clk_disable_unprepare(clk); 426fc702cb3SUlf Hansson err_of: 427f52d9c4fSPeter Griffin sdhci_pltfm_free(pdev); 428406c2431SPeter Griffin err_pltfm_init: 42915316752SJisheng Zhang if (rstc) 43015316752SJisheng Zhang reset_control_assert(rstc); 431406c2431SPeter Griffin 432406c2431SPeter Griffin return ret; 433406c2431SPeter Griffin } 434406c2431SPeter Griffin 435406c2431SPeter Griffin static int sdhci_st_remove(struct platform_device *pdev) 436406c2431SPeter Griffin { 437406c2431SPeter Griffin struct sdhci_host *host = platform_get_drvdata(pdev); 438406c2431SPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 43915316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 44015316752SJisheng Zhang struct reset_control *rstc = pdata->rstc; 441406c2431SPeter Griffin int ret; 442406c2431SPeter Griffin 443406c2431SPeter Griffin ret = sdhci_pltfm_unregister(pdev); 444406c2431SPeter Griffin 44515316752SJisheng Zhang if (rstc) 44615316752SJisheng Zhang reset_control_assert(rstc); 447f52d9c4fSPeter Griffin 448f52d9c4fSPeter Griffin return ret; 449f52d9c4fSPeter Griffin } 450f52d9c4fSPeter Griffin 451f52d9c4fSPeter Griffin #ifdef CONFIG_PM_SLEEP 452f52d9c4fSPeter Griffin static int sdhci_st_suspend(struct device *dev) 453f52d9c4fSPeter Griffin { 454f52d9c4fSPeter Griffin struct sdhci_host *host = dev_get_drvdata(dev); 455f52d9c4fSPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 45615316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 457f52d9c4fSPeter Griffin int ret = sdhci_suspend_host(host); 458f52d9c4fSPeter Griffin 459f52d9c4fSPeter Griffin if (ret) 460f52d9c4fSPeter Griffin goto out; 461f52d9c4fSPeter Griffin 462406c2431SPeter Griffin if (pdata->rstc) 463406c2431SPeter Griffin reset_control_assert(pdata->rstc); 464406c2431SPeter Griffin 465f52d9c4fSPeter Griffin clk_disable_unprepare(pltfm_host->clk); 466f52d9c4fSPeter Griffin out: 467f52d9c4fSPeter Griffin return ret; 468f52d9c4fSPeter Griffin } 469f52d9c4fSPeter Griffin 470f52d9c4fSPeter Griffin static int sdhci_st_resume(struct device *dev) 471f52d9c4fSPeter Griffin { 472f52d9c4fSPeter Griffin struct sdhci_host *host = dev_get_drvdata(dev); 473f52d9c4fSPeter Griffin struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 47415316752SJisheng Zhang struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); 4752053812fSPeter Griffin struct device_node *np = dev->of_node; 476f52d9c4fSPeter Griffin 477f52d9c4fSPeter Griffin clk_prepare_enable(pltfm_host->clk); 478f52d9c4fSPeter Griffin 479406c2431SPeter Griffin if (pdata->rstc) 480406c2431SPeter Griffin reset_control_deassert(pdata->rstc); 481406c2431SPeter Griffin 4822053812fSPeter Griffin st_mmcss_cconfig(np, host); 4832053812fSPeter Griffin 484f52d9c4fSPeter Griffin return sdhci_resume_host(host); 485f52d9c4fSPeter Griffin } 486f52d9c4fSPeter Griffin #endif 487f52d9c4fSPeter Griffin 488f52d9c4fSPeter Griffin static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume); 489f52d9c4fSPeter Griffin 490f52d9c4fSPeter Griffin static const struct of_device_id st_sdhci_match[] = { 491f52d9c4fSPeter Griffin { .compatible = "st,sdhci" }, 492f52d9c4fSPeter Griffin {}, 493f52d9c4fSPeter Griffin }; 494f52d9c4fSPeter Griffin 495f52d9c4fSPeter Griffin MODULE_DEVICE_TABLE(of, st_sdhci_match); 496f52d9c4fSPeter Griffin 497f52d9c4fSPeter Griffin static struct platform_driver sdhci_st_driver = { 498f52d9c4fSPeter Griffin .probe = sdhci_st_probe, 499406c2431SPeter Griffin .remove = sdhci_st_remove, 500f52d9c4fSPeter Griffin .driver = { 501f52d9c4fSPeter Griffin .name = "sdhci-st", 502f52d9c4fSPeter Griffin .pm = &sdhci_st_pmops, 503f52d9c4fSPeter Griffin .of_match_table = of_match_ptr(st_sdhci_match), 504f52d9c4fSPeter Griffin }, 505f52d9c4fSPeter Griffin }; 506f52d9c4fSPeter Griffin 507f52d9c4fSPeter Griffin module_platform_driver(sdhci_st_driver); 508f52d9c4fSPeter Griffin 509f52d9c4fSPeter Griffin MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs"); 510f52d9c4fSPeter Griffin MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 511f52d9c4fSPeter Griffin MODULE_LICENSE("GPL v2"); 512e6ac184bSZhangfei Gao MODULE_ALIAS("platform:sdhci-st"); 513