1 /* 2 * Driver for Marvell Xenon SDHC as a platform device 3 * 4 * Copyright (C) 2016 Marvell, All Rights Reserved. 5 * 6 * Author: Hu Ziji <huziji@marvell.com> 7 * Date: 2016-8-24 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation version 2. 12 * 13 * Inspired by Jisheng Zhang <jszhang@marvell.com> 14 * Special thanks to Video BG4 project team. 15 */ 16 17 #include <linux/delay.h> 18 #include <linux/ktime.h> 19 #include <linux/module.h> 20 #include <linux/of.h> 21 22 #include "sdhci-pltfm.h" 23 #include "sdhci-xenon.h" 24 25 static int xenon_enable_internal_clk(struct sdhci_host *host) 26 { 27 u32 reg; 28 ktime_t timeout; 29 30 reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL); 31 reg |= SDHCI_CLOCK_INT_EN; 32 sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL); 33 /* Wait max 20 ms */ 34 timeout = ktime_add_ms(ktime_get(), 20); 35 while (!((reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 36 & SDHCI_CLOCK_INT_STABLE)) { 37 if (ktime_after(ktime_get(), timeout)) { 38 dev_err(mmc_dev(host->mmc), "Internal clock never stabilised.\n"); 39 return -ETIMEDOUT; 40 } 41 usleep_range(900, 1100); 42 } 43 44 return 0; 45 } 46 47 /* Set SDCLK-off-while-idle */ 48 static void xenon_set_sdclk_off_idle(struct sdhci_host *host, 49 unsigned char sdhc_id, bool enable) 50 { 51 u32 reg; 52 u32 mask; 53 54 reg = sdhci_readl(host, XENON_SYS_OP_CTRL); 55 /* Get the bit shift basing on the SDHC index */ 56 mask = (0x1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sdhc_id)); 57 if (enable) 58 reg |= mask; 59 else 60 reg &= ~mask; 61 62 sdhci_writel(host, reg, XENON_SYS_OP_CTRL); 63 } 64 65 /* Enable/Disable the Auto Clock Gating function */ 66 static void xenon_set_acg(struct sdhci_host *host, bool enable) 67 { 68 u32 reg; 69 70 reg = sdhci_readl(host, XENON_SYS_OP_CTRL); 71 if (enable) 72 reg &= ~XENON_AUTO_CLKGATE_DISABLE_MASK; 73 else 74 reg |= XENON_AUTO_CLKGATE_DISABLE_MASK; 75 sdhci_writel(host, reg, XENON_SYS_OP_CTRL); 76 } 77 78 /* Enable this SDHC */ 79 static void xenon_enable_sdhc(struct sdhci_host *host, 80 unsigned char sdhc_id) 81 { 82 u32 reg; 83 84 reg = sdhci_readl(host, XENON_SYS_OP_CTRL); 85 reg |= (BIT(sdhc_id) << XENON_SLOT_ENABLE_SHIFT); 86 sdhci_writel(host, reg, XENON_SYS_OP_CTRL); 87 88 host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; 89 /* 90 * Force to clear BUS_TEST to 91 * skip bus_test_pre and bus_test_post 92 */ 93 host->mmc->caps &= ~MMC_CAP_BUS_WIDTH_TEST; 94 } 95 96 /* Disable this SDHC */ 97 static void xenon_disable_sdhc(struct sdhci_host *host, 98 unsigned char sdhc_id) 99 { 100 u32 reg; 101 102 reg = sdhci_readl(host, XENON_SYS_OP_CTRL); 103 reg &= ~(BIT(sdhc_id) << XENON_SLOT_ENABLE_SHIFT); 104 sdhci_writel(host, reg, XENON_SYS_OP_CTRL); 105 } 106 107 /* Enable Parallel Transfer Mode */ 108 static void xenon_enable_sdhc_parallel_tran(struct sdhci_host *host, 109 unsigned char sdhc_id) 110 { 111 u32 reg; 112 113 reg = sdhci_readl(host, XENON_SYS_EXT_OP_CTRL); 114 reg |= BIT(sdhc_id); 115 sdhci_writel(host, reg, XENON_SYS_EXT_OP_CTRL); 116 } 117 118 /* Mask command conflict error */ 119 static void xenon_mask_cmd_conflict_err(struct sdhci_host *host) 120 { 121 u32 reg; 122 123 reg = sdhci_readl(host, XENON_SYS_EXT_OP_CTRL); 124 reg |= XENON_MASK_CMD_CONFLICT_ERR; 125 sdhci_writel(host, reg, XENON_SYS_EXT_OP_CTRL); 126 } 127 128 static void xenon_retune_setup(struct sdhci_host *host) 129 { 130 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 131 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); 132 u32 reg; 133 134 /* Disable the Re-Tuning Request functionality */ 135 reg = sdhci_readl(host, XENON_SLOT_RETUNING_REQ_CTRL); 136 reg &= ~XENON_RETUNING_COMPATIBLE; 137 sdhci_writel(host, reg, XENON_SLOT_RETUNING_REQ_CTRL); 138 139 /* Disable the Re-tuning Interrupt */ 140 reg = sdhci_readl(host, SDHCI_SIGNAL_ENABLE); 141 reg &= ~SDHCI_INT_RETUNE; 142 sdhci_writel(host, reg, SDHCI_SIGNAL_ENABLE); 143 reg = sdhci_readl(host, SDHCI_INT_ENABLE); 144 reg &= ~SDHCI_INT_RETUNE; 145 sdhci_writel(host, reg, SDHCI_INT_ENABLE); 146 147 /* Force to use Tuning Mode 1 */ 148 host->tuning_mode = SDHCI_TUNING_MODE_1; 149 /* Set re-tuning period */ 150 host->tuning_count = 1 << (priv->tuning_count - 1); 151 } 152 153 /* 154 * Operations inside struct sdhci_ops 155 */ 156 /* Recover the Register Setting cleared during SOFTWARE_RESET_ALL */ 157 static void xenon_reset_exit(struct sdhci_host *host, 158 unsigned char sdhc_id, u8 mask) 159 { 160 /* Only SOFTWARE RESET ALL will clear the register setting */ 161 if (!(mask & SDHCI_RESET_ALL)) 162 return; 163 164 /* Disable tuning request and auto-retuning again */ 165 xenon_retune_setup(host); 166 167 xenon_set_acg(host, true); 168 169 xenon_set_sdclk_off_idle(host, sdhc_id, false); 170 171 xenon_mask_cmd_conflict_err(host); 172 } 173 174 static void xenon_reset(struct sdhci_host *host, u8 mask) 175 { 176 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 177 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); 178 179 sdhci_reset(host, mask); 180 xenon_reset_exit(host, priv->sdhc_id, mask); 181 } 182 183 /* 184 * Xenon defines different values for HS200 and HS400 185 * in Host_Control_2 186 */ 187 static void xenon_set_uhs_signaling(struct sdhci_host *host, 188 unsigned int timing) 189 { 190 u16 ctrl_2; 191 192 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 193 /* Select Bus Speed Mode for host */ 194 ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 195 if (timing == MMC_TIMING_MMC_HS200) 196 ctrl_2 |= XENON_CTRL_HS200; 197 else if (timing == MMC_TIMING_UHS_SDR104) 198 ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 199 else if (timing == MMC_TIMING_UHS_SDR12) 200 ctrl_2 |= SDHCI_CTRL_UHS_SDR12; 201 else if (timing == MMC_TIMING_UHS_SDR25) 202 ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 203 else if (timing == MMC_TIMING_UHS_SDR50) 204 ctrl_2 |= SDHCI_CTRL_UHS_SDR50; 205 else if ((timing == MMC_TIMING_UHS_DDR50) || 206 (timing == MMC_TIMING_MMC_DDR52)) 207 ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 208 else if (timing == MMC_TIMING_MMC_HS400) 209 ctrl_2 |= XENON_CTRL_HS400; 210 sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 211 } 212 213 static const struct sdhci_ops sdhci_xenon_ops = { 214 .set_clock = sdhci_set_clock, 215 .set_bus_width = sdhci_set_bus_width, 216 .reset = xenon_reset, 217 .set_uhs_signaling = xenon_set_uhs_signaling, 218 .get_max_clock = sdhci_pltfm_clk_get_max_clock, 219 }; 220 221 static const struct sdhci_pltfm_data sdhci_xenon_pdata = { 222 .ops = &sdhci_xenon_ops, 223 .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 224 SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | 225 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 226 }; 227 228 /* 229 * Xenon Specific Operations in mmc_host_ops 230 */ 231 static void xenon_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 232 { 233 struct sdhci_host *host = mmc_priv(mmc); 234 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 235 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); 236 u32 reg; 237 238 /* 239 * HS400/HS200/eMMC HS doesn't have Preset Value register. 240 * However, sdhci_set_ios will read HS400/HS200 Preset register. 241 * Disable Preset Value register for HS400/HS200. 242 * eMMC HS with preset_enabled set will trigger a bug in 243 * get_preset_value(). 244 */ 245 if ((ios->timing == MMC_TIMING_MMC_HS400) || 246 (ios->timing == MMC_TIMING_MMC_HS200) || 247 (ios->timing == MMC_TIMING_MMC_HS)) { 248 host->preset_enabled = false; 249 host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; 250 host->flags &= ~SDHCI_PV_ENABLED; 251 252 reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); 253 reg &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; 254 sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); 255 } else { 256 host->quirks2 &= ~SDHCI_QUIRK2_PRESET_VALUE_BROKEN; 257 } 258 259 sdhci_set_ios(mmc, ios); 260 xenon_phy_adj(host, ios); 261 262 if (host->clock > XENON_DEFAULT_SDCLK_FREQ) 263 xenon_set_sdclk_off_idle(host, priv->sdhc_id, true); 264 } 265 266 static int xenon_start_signal_voltage_switch(struct mmc_host *mmc, 267 struct mmc_ios *ios) 268 { 269 struct sdhci_host *host = mmc_priv(mmc); 270 271 /* 272 * Before SD/SDIO set signal voltage, SD bus clock should be 273 * disabled. However, sdhci_set_clock will also disable the Internal 274 * clock in mmc_set_signal_voltage(). 275 * If Internal clock is disabled, the 3.3V/1.8V bit can not be updated. 276 * Thus here manually enable internal clock. 277 * 278 * After switch completes, it is unnecessary to disable internal clock, 279 * since keeping internal clock active obeys SD spec. 280 */ 281 xenon_enable_internal_clk(host); 282 283 xenon_soc_pad_ctrl(host, ios->signal_voltage); 284 285 /* 286 * If Vqmmc is fixed on platform, vqmmc regulator should be unavailable. 287 * Thus SDHCI_CTRL_VDD_180 bit might not work then. 288 * Skip the standard voltage switch to avoid any issue. 289 */ 290 if (PTR_ERR(mmc->supply.vqmmc) == -ENODEV) 291 return 0; 292 293 return sdhci_start_signal_voltage_switch(mmc, ios); 294 } 295 296 /* 297 * Update card type. 298 * priv->init_card_type will be used in PHY timing adjustment. 299 */ 300 static void xenon_init_card(struct mmc_host *mmc, struct mmc_card *card) 301 { 302 struct sdhci_host *host = mmc_priv(mmc); 303 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 304 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); 305 306 /* Update card type*/ 307 priv->init_card_type = card->type; 308 } 309 310 static int xenon_execute_tuning(struct mmc_host *mmc, u32 opcode) 311 { 312 struct sdhci_host *host = mmc_priv(mmc); 313 314 if (host->timing == MMC_TIMING_UHS_DDR50) 315 return 0; 316 317 /* 318 * Currently force Xenon driver back to support mode 1 only, 319 * even though Xenon might claim to support mode 2 or mode 3. 320 * It requires more time to test mode 2/mode 3 on more platforms. 321 */ 322 if (host->tuning_mode != SDHCI_TUNING_MODE_1) 323 xenon_retune_setup(host); 324 325 return sdhci_execute_tuning(mmc, opcode); 326 } 327 328 static void xenon_enable_sdio_irq(struct mmc_host *mmc, int enable) 329 { 330 struct sdhci_host *host = mmc_priv(mmc); 331 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 332 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); 333 u32 reg; 334 u8 sdhc_id = priv->sdhc_id; 335 336 sdhci_enable_sdio_irq(mmc, enable); 337 338 if (enable) { 339 /* 340 * Set SDIO Card Inserted indication 341 * to enable detecting SDIO async irq. 342 */ 343 reg = sdhci_readl(host, XENON_SYS_CFG_INFO); 344 reg |= (1 << (sdhc_id + XENON_SLOT_TYPE_SDIO_SHIFT)); 345 sdhci_writel(host, reg, XENON_SYS_CFG_INFO); 346 } else { 347 /* Clear SDIO Card Inserted indication */ 348 reg = sdhci_readl(host, XENON_SYS_CFG_INFO); 349 reg &= ~(1 << (sdhc_id + XENON_SLOT_TYPE_SDIO_SHIFT)); 350 sdhci_writel(host, reg, XENON_SYS_CFG_INFO); 351 } 352 } 353 354 static void xenon_replace_mmc_host_ops(struct sdhci_host *host) 355 { 356 host->mmc_host_ops.set_ios = xenon_set_ios; 357 host->mmc_host_ops.start_signal_voltage_switch = 358 xenon_start_signal_voltage_switch; 359 host->mmc_host_ops.init_card = xenon_init_card; 360 host->mmc_host_ops.execute_tuning = xenon_execute_tuning; 361 host->mmc_host_ops.enable_sdio_irq = xenon_enable_sdio_irq; 362 } 363 364 /* 365 * Parse Xenon specific DT properties: 366 * sdhc-id: the index of current SDHC. 367 * Refer to XENON_SYS_CFG_INFO register 368 * tun-count: the interval between re-tuning 369 */ 370 static int xenon_probe_dt(struct platform_device *pdev) 371 { 372 struct device_node *np = pdev->dev.of_node; 373 struct sdhci_host *host = platform_get_drvdata(pdev); 374 struct mmc_host *mmc = host->mmc; 375 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 376 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); 377 u32 sdhc_id, nr_sdhc; 378 u32 tuning_count; 379 380 /* Disable HS200 on Armada AP806 */ 381 if (of_device_is_compatible(np, "marvell,armada-ap806-sdhci")) 382 host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; 383 384 sdhc_id = 0x0; 385 if (!of_property_read_u32(np, "marvell,xenon-sdhc-id", &sdhc_id)) { 386 nr_sdhc = sdhci_readl(host, XENON_SYS_CFG_INFO); 387 nr_sdhc &= XENON_NR_SUPPORTED_SLOT_MASK; 388 if (unlikely(sdhc_id > nr_sdhc)) { 389 dev_err(mmc_dev(mmc), "SDHC Index %d exceeds Number of SDHCs %d\n", 390 sdhc_id, nr_sdhc); 391 return -EINVAL; 392 } 393 } 394 priv->sdhc_id = sdhc_id; 395 396 tuning_count = XENON_DEF_TUNING_COUNT; 397 if (!of_property_read_u32(np, "marvell,xenon-tun-count", 398 &tuning_count)) { 399 if (unlikely(tuning_count >= XENON_TMR_RETUN_NO_PRESENT)) { 400 dev_err(mmc_dev(mmc), "Wrong Re-tuning Count. Set default value %d\n", 401 XENON_DEF_TUNING_COUNT); 402 tuning_count = XENON_DEF_TUNING_COUNT; 403 } 404 } 405 priv->tuning_count = tuning_count; 406 407 return xenon_phy_parse_dt(np, host); 408 } 409 410 static int xenon_sdhc_prepare(struct sdhci_host *host) 411 { 412 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 413 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); 414 u8 sdhc_id = priv->sdhc_id; 415 416 /* Enable SDHC */ 417 xenon_enable_sdhc(host, sdhc_id); 418 419 /* Enable ACG */ 420 xenon_set_acg(host, true); 421 422 /* Enable Parallel Transfer Mode */ 423 xenon_enable_sdhc_parallel_tran(host, sdhc_id); 424 425 /* Disable SDCLK-Off-While-Idle before card init */ 426 xenon_set_sdclk_off_idle(host, sdhc_id, false); 427 428 xenon_mask_cmd_conflict_err(host); 429 430 return 0; 431 } 432 433 static void xenon_sdhc_unprepare(struct sdhci_host *host) 434 { 435 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 436 struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); 437 u8 sdhc_id = priv->sdhc_id; 438 439 /* disable SDHC */ 440 xenon_disable_sdhc(host, sdhc_id); 441 } 442 443 static int xenon_probe(struct platform_device *pdev) 444 { 445 struct sdhci_pltfm_host *pltfm_host; 446 struct sdhci_host *host; 447 struct xenon_priv *priv; 448 int err; 449 450 host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata, 451 sizeof(struct xenon_priv)); 452 if (IS_ERR(host)) 453 return PTR_ERR(host); 454 455 pltfm_host = sdhci_priv(host); 456 priv = sdhci_pltfm_priv(pltfm_host); 457 458 /* 459 * Link Xenon specific mmc_host_ops function, 460 * to replace standard ones in sdhci_ops. 461 */ 462 xenon_replace_mmc_host_ops(host); 463 464 pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); 465 if (IS_ERR(pltfm_host->clk)) { 466 err = PTR_ERR(pltfm_host->clk); 467 dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err); 468 goto free_pltfm; 469 } 470 err = clk_prepare_enable(pltfm_host->clk); 471 if (err) 472 goto free_pltfm; 473 474 err = mmc_of_parse(host->mmc); 475 if (err) 476 goto err_clk; 477 478 sdhci_get_of_property(pdev); 479 480 xenon_set_acg(host, false); 481 482 /* Xenon specific dt parse */ 483 err = xenon_probe_dt(pdev); 484 if (err) 485 goto err_clk; 486 487 err = xenon_sdhc_prepare(host); 488 if (err) 489 goto err_clk; 490 491 err = sdhci_add_host(host); 492 if (err) 493 goto remove_sdhc; 494 495 return 0; 496 497 remove_sdhc: 498 xenon_sdhc_unprepare(host); 499 err_clk: 500 clk_disable_unprepare(pltfm_host->clk); 501 free_pltfm: 502 sdhci_pltfm_free(pdev); 503 return err; 504 } 505 506 static int xenon_remove(struct platform_device *pdev) 507 { 508 struct sdhci_host *host = platform_get_drvdata(pdev); 509 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 510 511 sdhci_remove_host(host, 0); 512 513 xenon_sdhc_unprepare(host); 514 515 clk_disable_unprepare(pltfm_host->clk); 516 517 sdhci_pltfm_free(pdev); 518 519 return 0; 520 } 521 522 static const struct of_device_id sdhci_xenon_dt_ids[] = { 523 { .compatible = "marvell,armada-ap806-sdhci",}, 524 { .compatible = "marvell,armada-cp110-sdhci",}, 525 { .compatible = "marvell,armada-3700-sdhci",}, 526 {} 527 }; 528 MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids); 529 530 static struct platform_driver sdhci_xenon_driver = { 531 .driver = { 532 .name = "xenon-sdhci", 533 .of_match_table = sdhci_xenon_dt_ids, 534 .pm = &sdhci_pltfm_pmops, 535 }, 536 .probe = xenon_probe, 537 .remove = xenon_remove, 538 }; 539 540 module_platform_driver(sdhci_xenon_driver); 541 542 MODULE_DESCRIPTION("SDHCI platform driver for Marvell Xenon SDHC"); 543 MODULE_AUTHOR("Hu Ziji <huziji@marvell.com>"); 544 MODULE_LICENSE("GPL v2"); 545