525 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Support for SDHCI on STMicroelectronics SoCs4 *5 * Copyright (C) 2014 STMicroelectronics Ltd6 * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>7 * Contributors: Peter Griffin <peter.griffin@linaro.org>8 *9 * Based on sdhci-cns3xxx.c10 */11 12#include <linux/io.h>13#include <linux/of.h>14#include <linux/module.h>15#include <linux/err.h>16#include <linux/mmc/host.h>17#include <linux/reset.h>18#include "sdhci-pltfm.h"19 20struct st_mmc_platform_data {21 struct reset_control *rstc;22 struct clk *icnclk;23 void __iomem *top_ioaddr;24};25 26/* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */27 28#define ST_MMC_CCONFIG_REG_1 0x40029#define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24)30#define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12)31#define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT BIT(8)32#define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0)33#define ST_MMC_CCONFIG_1_DEFAULT \34 ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \35 (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \36 (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT))37 38#define ST_MMC_CCONFIG_REG_2 0x40439#define ST_MMC_CCONFIG_HIGH_SPEED BIT(28)40#define ST_MMC_CCONFIG_ADMA2 BIT(24)41#define ST_MMC_CCONFIG_8BIT BIT(20)42#define ST_MMC_CCONFIG_MAX_BLK_LEN 1643#define MAX_BLK_LEN_1024 144#define MAX_BLK_LEN_2048 245#define BASE_CLK_FREQ_200 0xc846#define BASE_CLK_FREQ_100 0x6447#define BASE_CLK_FREQ_50 0x3248#define ST_MMC_CCONFIG_2_DEFAULT \49 (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \50 ST_MMC_CCONFIG_8BIT | \51 (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN))52 53#define ST_MMC_CCONFIG_REG_3 0x40854#define ST_MMC_CCONFIG_EMMC_SLOT_TYPE BIT(28)55#define ST_MMC_CCONFIG_64BIT BIT(24)56#define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20)57#define ST_MMC_CCONFIG_1P8_VOLT BIT(16)58#define ST_MMC_CCONFIG_3P0_VOLT BIT(12)59#define ST_MMC_CCONFIG_3P3_VOLT BIT(8)60#define ST_MMC_CCONFIG_SUSP_RES_SUPPORT BIT(4)61#define ST_MMC_CCONFIG_SDMA BIT(0)62#define ST_MMC_CCONFIG_3_DEFAULT \63 (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \64 ST_MMC_CCONFIG_3P3_VOLT | \65 ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \66 ST_MMC_CCONFIG_SDMA)67 68#define ST_MMC_CCONFIG_REG_4 0x40c69#define ST_MMC_CCONFIG_D_DRIVER BIT(20)70#define ST_MMC_CCONFIG_C_DRIVER BIT(16)71#define ST_MMC_CCONFIG_A_DRIVER BIT(12)72#define ST_MMC_CCONFIG_DDR50 BIT(8)73#define ST_MMC_CCONFIG_SDR104 BIT(4)74#define ST_MMC_CCONFIG_SDR50 BIT(0)75#define ST_MMC_CCONFIG_4_DEFAULT 076 77#define ST_MMC_CCONFIG_REG_5 0x41078#define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8)79#define RETUNING_TIMER_CNT_MAX 0xf80#define ST_MMC_CCONFIG_5_DEFAULT 081 82/* I/O configuration for Arasan IP */83#define ST_MMC_GP_OUTPUT 0x45084#define ST_MMC_GP_OUTPUT_CD BIT(12)85 86#define ST_MMC_STATUS_R 0x46087 88#define ST_TOP_MMC_DLY_FIX_OFF(x) (x - 0x8)89 90/* TOP config registers to manage static and dynamic delay */91#define ST_TOP_MMC_TX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0x8)92#define ST_TOP_MMC_RX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0xc)93/* MMC delay control register */94#define ST_TOP_MMC_DLY_CTRL ST_TOP_MMC_DLY_FIX_OFF(0x18)95#define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD BIT(0)96#define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL BIT(1)97#define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE BIT(8)98#define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE BIT(9)99#define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY BIT(10)100#define ST_TOP_MMC_START_DLL_LOCK BIT(11)101 102/* register to provide the phase-shift value for DLL */103#define ST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c)104#define ST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20)105#define ST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24)106 107/* phase shift delay on the tx clk 2.188ns */108#define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID 0x6109 110#define ST_TOP_MMC_DLY_MAX 0xf111 112#define ST_TOP_MMC_DYN_DLY_CONF \113 (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \114 ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \115 ST_TOP_MMC_START_DLL_LOCK)116 117/*118 * For clock speeds greater than 90MHz, we need to check that the119 * DLL procedure has finished before switching to ultra-speed modes.120 */121#define CLK_TO_CHECK_DLL_LOCK 90000000122 123static inline void st_mmcss_set_static_delay(void __iomem *ioaddr)124{125 if (!ioaddr)126 return;127 128 writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL);129 writel_relaxed(ST_TOP_MMC_DLY_MAX,130 ioaddr + ST_TOP_MMC_TX_CLK_DLY);131}132 133/**134 * st_mmcss_cconfig: configure the Arasan HC inside the flashSS.135 * @np: dt device node.136 * @host: sdhci host137 * Description: this function is to configure the Arasan host controller.138 * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated139 * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5140 * or eMMC4.3. This has to be done before registering the sdhci host.141 */142static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host)143{144 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);145 struct mmc_host *mhost = host->mmc;146 u32 cconf2, cconf3, cconf4, cconf5;147 148 if (!of_device_is_compatible(np, "st,sdhci-stih407"))149 return;150 151 cconf2 = ST_MMC_CCONFIG_2_DEFAULT;152 cconf3 = ST_MMC_CCONFIG_3_DEFAULT;153 cconf4 = ST_MMC_CCONFIG_4_DEFAULT;154 cconf5 = ST_MMC_CCONFIG_5_DEFAULT;155 156 writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT,157 host->ioaddr + ST_MMC_CCONFIG_REG_1);158 159 /* Set clock frequency, default to 50MHz if max-frequency is not160 * provided */161 162 switch (mhost->f_max) {163 case 200000000:164 clk_set_rate(pltfm_host->clk, mhost->f_max);165 cconf2 |= BASE_CLK_FREQ_200;166 break;167 case 100000000:168 clk_set_rate(pltfm_host->clk, mhost->f_max);169 cconf2 |= BASE_CLK_FREQ_100;170 break;171 default:172 clk_set_rate(pltfm_host->clk, 50000000);173 cconf2 |= BASE_CLK_FREQ_50;174 }175 176 writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2);177 178 if (!mmc_card_is_removable(mhost))179 cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE;180 else181 /* CARD _D ET_CTRL */182 writel_relaxed(ST_MMC_GP_OUTPUT_CD,183 host->ioaddr + ST_MMC_GP_OUTPUT);184 185 if (mhost->caps & MMC_CAP_UHS_SDR50) {186 /* use 1.8V */187 cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;188 cconf4 |= ST_MMC_CCONFIG_SDR50;189 /* Use tuning */190 cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50;191 /* Max timeout for retuning */192 cconf5 |= RETUNING_TIMER_CNT_MAX;193 }194 195 if (mhost->caps & MMC_CAP_UHS_SDR104) {196 /*197 * SDR104 implies the HC can support HS200 mode, so198 * it's mandatory to use 1.8V199 */200 cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;201 cconf4 |= ST_MMC_CCONFIG_SDR104;202 /* Max timeout for retuning */203 cconf5 |= RETUNING_TIMER_CNT_MAX;204 }205 206 if (mhost->caps & MMC_CAP_UHS_DDR50)207 cconf4 |= ST_MMC_CCONFIG_DDR50;208 209 writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3);210 writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4);211 writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5);212}213 214static inline void st_mmcss_set_dll(void __iomem *ioaddr)215{216 if (!ioaddr)217 return;218 219 writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, ioaddr + ST_TOP_MMC_DLY_CTRL);220 writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID,221 ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY);222}223 224static int st_mmcss_lock_dll(void __iomem *ioaddr)225{226 unsigned long curr, value;227 unsigned long finish = jiffies + HZ;228 229 /* Checks if the DLL procedure is finished */230 do {231 curr = jiffies;232 value = readl(ioaddr + ST_MMC_STATUS_R);233 if (value & 0x1)234 return 0;235 236 cpu_relax();237 } while (!time_after_eq(curr, finish));238 239 return -EBUSY;240}241 242static int sdhci_st_set_dll_for_clock(struct sdhci_host *host)243{244 int ret = 0;245 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);246 struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);247 248 if (host->clock > CLK_TO_CHECK_DLL_LOCK) {249 st_mmcss_set_dll(pdata->top_ioaddr);250 ret = st_mmcss_lock_dll(host->ioaddr);251 }252 253 return ret;254}255 256static void sdhci_st_set_uhs_signaling(struct sdhci_host *host,257 unsigned int uhs)258{259 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);260 struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);261 u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);262 int ret = 0;263 264 /* Select Bus Speed Mode for host */265 ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;266 switch (uhs) {267 /*268 * Set V18_EN -- UHS modes do not work without this.269 * does not change signaling voltage270 */271 272 case MMC_TIMING_UHS_SDR12:273 st_mmcss_set_static_delay(pdata->top_ioaddr);274 ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180;275 break;276 case MMC_TIMING_UHS_SDR25:277 st_mmcss_set_static_delay(pdata->top_ioaddr);278 ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180;279 break;280 case MMC_TIMING_UHS_SDR50:281 st_mmcss_set_static_delay(pdata->top_ioaddr);282 ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;283 ret = sdhci_st_set_dll_for_clock(host);284 break;285 case MMC_TIMING_UHS_SDR104:286 case MMC_TIMING_MMC_HS200:287 st_mmcss_set_static_delay(pdata->top_ioaddr);288 ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;289 ret = sdhci_st_set_dll_for_clock(host);290 break;291 case MMC_TIMING_UHS_DDR50:292 case MMC_TIMING_MMC_DDR52:293 st_mmcss_set_static_delay(pdata->top_ioaddr);294 ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;295 break;296 }297 298 if (ret)299 dev_warn(mmc_dev(host->mmc), "Error setting dll for clock "300 "(uhs %d)\n", uhs);301 302 dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2);303 304 sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);305}306 307static u32 sdhci_st_readl(struct sdhci_host *host, int reg)308{309 u32 ret;310 311 switch (reg) {312 case SDHCI_CAPABILITIES:313 ret = readl_relaxed(host->ioaddr + reg);314 /* Support 3.3V and 1.8V */315 ret &= ~SDHCI_CAN_VDD_300;316 break;317 default:318 ret = readl_relaxed(host->ioaddr + reg);319 }320 return ret;321}322 323static const struct sdhci_ops sdhci_st_ops = {324 .get_max_clock = sdhci_pltfm_clk_get_max_clock,325 .set_clock = sdhci_set_clock,326 .set_bus_width = sdhci_set_bus_width,327 .read_l = sdhci_st_readl,328 .reset = sdhci_reset,329 .set_uhs_signaling = sdhci_st_set_uhs_signaling,330};331 332static const struct sdhci_pltfm_data sdhci_st_pdata = {333 .ops = &sdhci_st_ops,334 .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |335 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |336 SDHCI_QUIRK_NO_HISPD_BIT,337 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |338 SDHCI_QUIRK2_STOP_WITH_TC,339};340 341 342static int sdhci_st_probe(struct platform_device *pdev)343{344 struct device_node *np = pdev->dev.of_node;345 struct sdhci_host *host;346 struct st_mmc_platform_data *pdata;347 struct sdhci_pltfm_host *pltfm_host;348 struct clk *clk, *icnclk;349 int ret = 0;350 u16 host_version;351 struct reset_control *rstc;352 353 clk = devm_clk_get(&pdev->dev, "mmc");354 if (IS_ERR(clk)) {355 dev_err(&pdev->dev, "Peripheral clk not found\n");356 return PTR_ERR(clk);357 }358 359 /* ICN clock isn't compulsory, but use it if it's provided. */360 icnclk = devm_clk_get(&pdev->dev, "icn");361 if (IS_ERR(icnclk))362 icnclk = NULL;363 364 rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);365 if (IS_ERR(rstc))366 return PTR_ERR(rstc);367 reset_control_deassert(rstc);368 369 host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata));370 if (IS_ERR(host)) {371 dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");372 ret = PTR_ERR(host);373 goto err_pltfm_init;374 }375 376 pltfm_host = sdhci_priv(host);377 pdata = sdhci_pltfm_priv(pltfm_host);378 pdata->rstc = rstc;379 380 ret = mmc_of_parse(host->mmc);381 if (ret) {382 dev_err(&pdev->dev, "Failed mmc_of_parse\n");383 goto err_of;384 }385 386 ret = clk_prepare_enable(clk);387 if (ret) {388 dev_err(&pdev->dev, "Failed to prepare clock\n");389 goto err_of;390 }391 392 ret = clk_prepare_enable(icnclk);393 if (ret) {394 dev_err(&pdev->dev, "Failed to prepare icn clock\n");395 goto err_icnclk;396 }397 398 /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */399 pdata->top_ioaddr = devm_platform_ioremap_resource_byname(pdev, "top-mmc-delay");400 if (IS_ERR(pdata->top_ioaddr))401 pdata->top_ioaddr = NULL;402 403 pltfm_host->clk = clk;404 pdata->icnclk = icnclk;405 406 /* Configure the Arasan HC inside the flashSS */407 st_mmcss_cconfig(np, host);408 409 ret = sdhci_add_host(host);410 if (ret)411 goto err_out;412 413 host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));414 415 dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n",416 ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT),417 ((host_version & SDHCI_VENDOR_VER_MASK) >>418 SDHCI_VENDOR_VER_SHIFT));419 420 return 0;421 422err_out:423 clk_disable_unprepare(icnclk);424err_icnclk:425 clk_disable_unprepare(clk);426err_of:427 sdhci_pltfm_free(pdev);428err_pltfm_init:429 reset_control_assert(rstc);430 431 return ret;432}433 434static void sdhci_st_remove(struct platform_device *pdev)435{436 struct sdhci_host *host = platform_get_drvdata(pdev);437 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);438 struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);439 struct reset_control *rstc = pdata->rstc;440 struct clk *clk = pltfm_host->clk;441 442 sdhci_pltfm_remove(pdev);443 444 clk_disable_unprepare(pdata->icnclk);445 clk_disable_unprepare(clk);446 447 reset_control_assert(rstc);448}449 450#ifdef CONFIG_PM_SLEEP451static int sdhci_st_suspend(struct device *dev)452{453 struct sdhci_host *host = dev_get_drvdata(dev);454 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);455 struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);456 int ret;457 458 if (host->tuning_mode != SDHCI_TUNING_MODE_3)459 mmc_retune_needed(host->mmc);460 461 ret = sdhci_suspend_host(host);462 if (ret)463 goto out;464 465 reset_control_assert(pdata->rstc);466 467 clk_disable_unprepare(pdata->icnclk);468 clk_disable_unprepare(pltfm_host->clk);469out:470 return ret;471}472 473static int sdhci_st_resume(struct device *dev)474{475 struct sdhci_host *host = dev_get_drvdata(dev);476 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);477 struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);478 struct device_node *np = dev->of_node;479 int ret;480 481 ret = clk_prepare_enable(pltfm_host->clk);482 if (ret)483 return ret;484 485 ret = clk_prepare_enable(pdata->icnclk);486 if (ret) {487 clk_disable_unprepare(pltfm_host->clk);488 return ret;489 }490 491 reset_control_deassert(pdata->rstc);492 493 st_mmcss_cconfig(np, host);494 495 return sdhci_resume_host(host);496}497#endif498 499static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume);500 501static const struct of_device_id st_sdhci_match[] = {502 { .compatible = "st,sdhci" },503 {},504};505 506MODULE_DEVICE_TABLE(of, st_sdhci_match);507 508static struct platform_driver sdhci_st_driver = {509 .probe = sdhci_st_probe,510 .remove_new = sdhci_st_remove,511 .driver = {512 .name = "sdhci-st",513 .probe_type = PROBE_PREFER_ASYNCHRONOUS,514 .pm = &sdhci_st_pmops,515 .of_match_table = st_sdhci_match,516 },517};518 519module_platform_driver(sdhci_st_driver);520 521MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs");522MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");523MODULE_LICENSE("GPL v2");524MODULE_ALIAS("platform:sdhci-st");525