1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Exynos Specific Extensions for Synopsys DW Multimedia Card Interface driver 4 * 5 * Copyright (C) 2012, Samsung Electronics Co., Ltd. 6 */ 7 8 #include <linux/module.h> 9 #include <linux/platform_device.h> 10 #include <linux/clk.h> 11 #include <linux/mmc/host.h> 12 #include <linux/mmc/mmc.h> 13 #include <linux/of.h> 14 #include <linux/pm_runtime.h> 15 #include <linux/slab.h> 16 17 #include "dw_mmc.h" 18 #include "dw_mmc-pltfm.h" 19 #include "dw_mmc-exynos.h" 20 21 /* Variations in Exynos specific dw-mshc controller */ 22 enum dw_mci_exynos_type { 23 DW_MCI_TYPE_EXYNOS4210, 24 DW_MCI_TYPE_EXYNOS4412, 25 DW_MCI_TYPE_EXYNOS5250, 26 DW_MCI_TYPE_EXYNOS5420, 27 DW_MCI_TYPE_EXYNOS5420_SMU, 28 DW_MCI_TYPE_EXYNOS7, 29 DW_MCI_TYPE_EXYNOS7_SMU, 30 DW_MCI_TYPE_EXYNOS7870, 31 DW_MCI_TYPE_EXYNOS7870_SMU, 32 DW_MCI_TYPE_ARTPEC8, 33 }; 34 35 /* Exynos implementation specific driver private data */ 36 struct dw_mci_exynos_priv_data { 37 enum dw_mci_exynos_type ctrl_type; 38 u8 ciu_div; 39 u32 sdr_timing; 40 u32 ddr_timing; 41 u32 hs400_timing; 42 u32 tuned_sample; 43 u32 cur_speed; 44 u32 dqs_delay; 45 u32 saved_dqs_en; 46 u32 saved_strobe_ctrl; 47 }; 48 49 static struct dw_mci_exynos_compatible { 50 char *compatible; 51 enum dw_mci_exynos_type ctrl_type; 52 } exynos_compat[] = { 53 { 54 .compatible = "samsung,exynos4210-dw-mshc", 55 .ctrl_type = DW_MCI_TYPE_EXYNOS4210, 56 }, { 57 .compatible = "samsung,exynos4412-dw-mshc", 58 .ctrl_type = DW_MCI_TYPE_EXYNOS4412, 59 }, { 60 .compatible = "samsung,exynos5250-dw-mshc", 61 .ctrl_type = DW_MCI_TYPE_EXYNOS5250, 62 }, { 63 .compatible = "samsung,exynos5420-dw-mshc", 64 .ctrl_type = DW_MCI_TYPE_EXYNOS5420, 65 }, { 66 .compatible = "samsung,exynos5420-dw-mshc-smu", 67 .ctrl_type = DW_MCI_TYPE_EXYNOS5420_SMU, 68 }, { 69 .compatible = "samsung,exynos7-dw-mshc", 70 .ctrl_type = DW_MCI_TYPE_EXYNOS7, 71 }, { 72 .compatible = "samsung,exynos7-dw-mshc-smu", 73 .ctrl_type = DW_MCI_TYPE_EXYNOS7_SMU, 74 }, { 75 .compatible = "samsung,exynos7870-dw-mshc", 76 .ctrl_type = DW_MCI_TYPE_EXYNOS7870, 77 }, { 78 .compatible = "samsung,exynos7870-dw-mshc-smu", 79 .ctrl_type = DW_MCI_TYPE_EXYNOS7870_SMU, 80 }, { 81 .compatible = "axis,artpec8-dw-mshc", 82 .ctrl_type = DW_MCI_TYPE_ARTPEC8, 83 }, 84 }; 85 86 static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host) 87 { 88 struct dw_mci_exynos_priv_data *priv = host->priv; 89 90 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) 91 return EXYNOS4412_FIXED_CIU_CLK_DIV; 92 else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) 93 return EXYNOS4210_FIXED_CIU_CLK_DIV; 94 else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 95 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 96 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 97 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 98 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 99 return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1; 100 else 101 return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1; 102 } 103 104 static void dw_mci_exynos_config_smu(struct dw_mci *host) 105 { 106 struct dw_mci_exynos_priv_data *priv = host->priv; 107 108 /* 109 * If Exynos is provided the Security management, 110 * set for non-ecryption mode at this time. 111 */ 112 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU || 113 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 114 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { 115 mci_writel(host, MPSBEGIN0, 0); 116 mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX); 117 mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT | 118 SDMMC_MPSCTRL_NON_SECURE_READ_BIT | 119 SDMMC_MPSCTRL_VALID | 120 SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); 121 } 122 } 123 124 static int dw_mci_exynos_priv_init(struct dw_mci *host) 125 { 126 struct dw_mci_exynos_priv_data *priv = host->priv; 127 128 dw_mci_exynos_config_smu(host); 129 130 if (priv->ctrl_type >= DW_MCI_TYPE_EXYNOS5420) { 131 priv->saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL); 132 priv->saved_dqs_en = mci_readl(host, HS400_DQS_EN); 133 priv->saved_dqs_en |= AXI_NON_BLOCKING_WR; 134 mci_writel(host, HS400_DQS_EN, priv->saved_dqs_en); 135 if (!priv->dqs_delay) 136 priv->dqs_delay = 137 DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl); 138 } 139 140 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 141 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { 142 /* Quirk needed for certain Exynos SoCs */ 143 host->quirks |= DW_MMC_QUIRK_FIFO64_32; 144 } 145 146 if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) { 147 /* Quirk needed for the ARTPEC-8 SoC */ 148 host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT; 149 } 150 151 host->bus_hz /= (priv->ciu_div + 1); 152 153 return 0; 154 } 155 156 static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) 157 { 158 struct dw_mci_exynos_priv_data *priv = host->priv; 159 u32 clksel; 160 161 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 162 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 163 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 164 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 165 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 166 clksel = mci_readl(host, CLKSEL64); 167 else 168 clksel = mci_readl(host, CLKSEL); 169 170 clksel = (clksel & ~SDMMC_CLKSEL_TIMING_MASK) | timing; 171 172 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 173 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 174 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 175 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 176 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 177 mci_writel(host, CLKSEL64, clksel); 178 else 179 mci_writel(host, CLKSEL, clksel); 180 181 /* 182 * Exynos4412 and Exynos5250 extends the use of CMD register with the 183 * use of bit 29 (which is reserved on standard MSHC controllers) for 184 * optionally bypassing the HOLD register for command and data. The 185 * HOLD register should be bypassed in case there is no phase shift 186 * applied on CMD/DATA that is sent to the card. 187 */ 188 if (!SDMMC_CLKSEL_GET_DRV_WD3(clksel) && host->slot) 189 set_bit(DW_MMC_CARD_NO_USE_HOLD, &host->slot->flags); 190 } 191 192 static int dw_mci_exynos_runtime_resume(struct device *dev) 193 { 194 struct dw_mci *host = dev_get_drvdata(dev); 195 int ret; 196 197 ret = dw_mci_runtime_resume(dev); 198 if (ret) 199 return ret; 200 201 dw_mci_exynos_config_smu(host); 202 203 return ret; 204 } 205 206 /** 207 * dw_mci_exynos_suspend_noirq - Exynos-specific suspend code 208 * @dev: Device to suspend (this device) 209 * 210 * This ensures that device will be in runtime active state in 211 * dw_mci_exynos_resume_noirq after calling pm_runtime_force_resume() 212 */ 213 static int dw_mci_exynos_suspend_noirq(struct device *dev) 214 { 215 pm_runtime_get_noresume(dev); 216 return pm_runtime_force_suspend(dev); 217 } 218 219 /** 220 * dw_mci_exynos_resume_noirq - Exynos-specific resume code 221 * @dev: Device to resume (this device) 222 * 223 * On exynos5420 there is a silicon errata that will sometimes leave the 224 * WAKEUP_INT bit in the CLKSEL register asserted. This bit is 1 to indicate 225 * that it fired and we can clear it by writing a 1 back. Clear it to prevent 226 * interrupts from going off constantly. 227 * 228 * We run this code on all exynos variants because it doesn't hurt. 229 */ 230 static int dw_mci_exynos_resume_noirq(struct device *dev) 231 { 232 struct dw_mci *host = dev_get_drvdata(dev); 233 struct dw_mci_exynos_priv_data *priv = host->priv; 234 u32 clksel; 235 int ret; 236 237 ret = pm_runtime_force_resume(dev); 238 if (ret) 239 return ret; 240 241 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 242 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 243 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 244 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 245 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 246 clksel = mci_readl(host, CLKSEL64); 247 else 248 clksel = mci_readl(host, CLKSEL); 249 250 if (clksel & SDMMC_CLKSEL_WAKEUP_INT) { 251 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 252 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 253 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 254 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 255 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 256 mci_writel(host, CLKSEL64, clksel); 257 else 258 mci_writel(host, CLKSEL, clksel); 259 } 260 261 pm_runtime_put(dev); 262 263 return 0; 264 } 265 266 static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing) 267 { 268 struct dw_mci_exynos_priv_data *priv = host->priv; 269 u32 dqs, strobe; 270 271 /* 272 * Not supported to configure register 273 * related to HS400 274 */ 275 if ((priv->ctrl_type < DW_MCI_TYPE_EXYNOS5420) || 276 (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)) { 277 if (timing == MMC_TIMING_MMC_HS400) 278 dev_warn(host->dev, 279 "cannot configure HS400, unsupported chipset\n"); 280 return; 281 } 282 283 dqs = priv->saved_dqs_en; 284 strobe = priv->saved_strobe_ctrl; 285 286 if (timing == MMC_TIMING_MMC_HS400) { 287 dqs |= DATA_STROBE_EN; 288 strobe = DQS_CTRL_RD_DELAY(strobe, priv->dqs_delay); 289 } else if (timing == MMC_TIMING_UHS_SDR104) { 290 dqs &= 0xffffff00; 291 } else { 292 dqs &= ~DATA_STROBE_EN; 293 } 294 295 mci_writel(host, HS400_DQS_EN, dqs); 296 mci_writel(host, HS400_DLINE_CTRL, strobe); 297 } 298 299 static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted) 300 { 301 struct dw_mci_exynos_priv_data *priv = host->priv; 302 unsigned long actual; 303 u8 div; 304 int ret; 305 /* 306 * Don't care if wanted clock is zero or 307 * ciu clock is unavailable 308 */ 309 if (!wanted || IS_ERR(host->ciu_clk)) 310 return; 311 312 /* Guaranteed minimum frequency for cclkin */ 313 if (wanted < EXYNOS_CCLKIN_MIN) 314 wanted = EXYNOS_CCLKIN_MIN; 315 316 if (wanted == priv->cur_speed) 317 return; 318 319 div = dw_mci_exynos_get_ciu_div(host); 320 ret = clk_set_rate(host->ciu_clk, wanted * div); 321 if (ret) 322 dev_warn(host->dev, 323 "failed to set clk-rate %u error: %d\n", 324 wanted * div, ret); 325 actual = clk_get_rate(host->ciu_clk); 326 host->bus_hz = actual / div; 327 priv->cur_speed = wanted; 328 host->current_speed = 0; 329 } 330 331 static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) 332 { 333 struct dw_mci_exynos_priv_data *priv = host->priv; 334 unsigned int wanted = ios->clock; 335 u32 timing = ios->timing, clksel; 336 337 switch (timing) { 338 case MMC_TIMING_MMC_HS400: 339 /* Update tuned sample timing */ 340 clksel = SDMMC_CLKSEL_UP_SAMPLE( 341 priv->hs400_timing, priv->tuned_sample); 342 wanted <<= 1; 343 break; 344 case MMC_TIMING_MMC_DDR52: 345 clksel = priv->ddr_timing; 346 /* Should be double rate for DDR mode */ 347 if (ios->bus_width == MMC_BUS_WIDTH_8) 348 wanted <<= 1; 349 break; 350 case MMC_TIMING_UHS_SDR104: 351 case MMC_TIMING_UHS_SDR50: 352 clksel = (priv->sdr_timing & 0xfff8ffff) | 353 (priv->ciu_div << 16); 354 break; 355 case MMC_TIMING_UHS_DDR50: 356 clksel = (priv->ddr_timing & 0xfff8ffff) | 357 (priv->ciu_div << 16); 358 break; 359 default: 360 clksel = priv->sdr_timing; 361 } 362 363 /* Set clock timing for the requested speed mode*/ 364 dw_mci_exynos_set_clksel_timing(host, clksel); 365 366 /* Configure setting for HS400 */ 367 dw_mci_exynos_config_hs400(host, timing); 368 369 /* Configure clock rate */ 370 dw_mci_exynos_adjust_clock(host, wanted); 371 } 372 373 static int dw_mci_exynos_parse_dt(struct dw_mci *host) 374 { 375 struct dw_mci_exynos_priv_data *priv; 376 struct device_node *np = host->dev->of_node; 377 u32 timing[2]; 378 u32 div = 0; 379 int idx; 380 int ret; 381 382 priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); 383 if (!priv) 384 return -ENOMEM; 385 386 for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) { 387 if (of_device_is_compatible(np, exynos_compat[idx].compatible)) 388 priv->ctrl_type = exynos_compat[idx].ctrl_type; 389 } 390 391 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) 392 priv->ciu_div = EXYNOS4412_FIXED_CIU_CLK_DIV - 1; 393 else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) 394 priv->ciu_div = EXYNOS4210_FIXED_CIU_CLK_DIV - 1; 395 else { 396 of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div); 397 priv->ciu_div = div; 398 } 399 400 ret = of_property_read_u32_array(np, 401 "samsung,dw-mshc-sdr-timing", timing, 2); 402 if (ret) 403 return ret; 404 405 priv->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); 406 407 ret = of_property_read_u32_array(np, 408 "samsung,dw-mshc-ddr-timing", timing, 2); 409 if (ret) 410 return ret; 411 412 priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); 413 414 ret = of_property_read_u32_array(np, 415 "samsung,dw-mshc-hs400-timing", timing, 2); 416 if (!ret && of_property_read_u32(np, 417 "samsung,read-strobe-delay", &priv->dqs_delay)) 418 dev_dbg(host->dev, 419 "read-strobe-delay is not found, assuming usage of default value\n"); 420 421 priv->hs400_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], 422 HS400_FIXED_CIU_CLK_DIV); 423 host->priv = priv; 424 return 0; 425 } 426 427 static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host) 428 { 429 struct dw_mci_exynos_priv_data *priv = host->priv; 430 431 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 432 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 433 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 434 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 435 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 436 return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL64)); 437 else 438 return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL)); 439 } 440 441 static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) 442 { 443 u32 clksel; 444 struct dw_mci_exynos_priv_data *priv = host->priv; 445 446 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 447 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 448 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 449 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 450 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 451 clksel = mci_readl(host, CLKSEL64); 452 else 453 clksel = mci_readl(host, CLKSEL); 454 clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); 455 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 456 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 457 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 458 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 459 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 460 mci_writel(host, CLKSEL64, clksel); 461 else 462 mci_writel(host, CLKSEL, clksel); 463 } 464 465 static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) 466 { 467 struct dw_mci_exynos_priv_data *priv = host->priv; 468 u32 clksel; 469 u8 sample; 470 471 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 472 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 473 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 474 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 475 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 476 clksel = mci_readl(host, CLKSEL64); 477 else 478 clksel = mci_readl(host, CLKSEL); 479 480 sample = (clksel + 1) & 0x7; 481 clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); 482 483 if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || 484 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || 485 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || 486 priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || 487 priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) 488 mci_writel(host, CLKSEL64, clksel); 489 else 490 mci_writel(host, CLKSEL, clksel); 491 492 return sample; 493 } 494 495 static s8 dw_mci_exynos_get_best_clksmpl(u8 candidates) 496 { 497 const u8 iter = 8; 498 u8 __c; 499 s8 i, loc = -1; 500 501 for (i = 0; i < iter; i++) { 502 __c = ror8(candidates, i); 503 if ((__c & 0xc7) == 0xc7) { 504 loc = i; 505 goto out; 506 } 507 } 508 509 for (i = 0; i < iter; i++) { 510 __c = ror8(candidates, i); 511 if ((__c & 0x83) == 0x83) { 512 loc = i; 513 goto out; 514 } 515 } 516 517 /* 518 * If there is no cadiates value, then it needs to return -EIO. 519 * If there are candidates values and don't find bset clk sample value, 520 * then use a first candidates clock sample value. 521 */ 522 for (i = 0; i < iter; i++) { 523 __c = ror8(candidates, i); 524 if ((__c & 0x1) == 0x1) { 525 loc = i; 526 goto out; 527 } 528 } 529 out: 530 return loc; 531 } 532 533 static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode) 534 { 535 struct dw_mci *host = slot->host; 536 struct dw_mci_exynos_priv_data *priv = host->priv; 537 struct mmc_host *mmc = slot->mmc; 538 u8 start_smpl, smpl, candidates = 0; 539 s8 found; 540 int ret = 0; 541 542 start_smpl = dw_mci_exynos_get_clksmpl(host); 543 544 do { 545 mci_writel(host, TMOUT, ~0); 546 smpl = dw_mci_exynos_move_next_clksmpl(host); 547 548 if (!mmc_send_tuning(mmc, opcode, NULL)) 549 candidates |= (1 << smpl); 550 551 } while (start_smpl != smpl); 552 553 found = dw_mci_exynos_get_best_clksmpl(candidates); 554 if (found >= 0) { 555 dw_mci_exynos_set_clksmpl(host, found); 556 priv->tuned_sample = found; 557 } else { 558 ret = -EIO; 559 dev_warn(&mmc->class_dev, 560 "There is no candidates value about clksmpl!\n"); 561 } 562 563 return ret; 564 } 565 566 static int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host, 567 struct mmc_ios *ios) 568 { 569 struct dw_mci_exynos_priv_data *priv = host->priv; 570 571 dw_mci_exynos_set_clksel_timing(host, priv->hs400_timing); 572 dw_mci_exynos_adjust_clock(host, (ios->clock) << 1); 573 574 return 0; 575 } 576 577 static void dw_mci_exynos_set_data_timeout(struct dw_mci *host, 578 unsigned int timeout_ns) 579 { 580 u32 clk_div, tmout; 581 u64 tmp; 582 unsigned int tmp2; 583 584 clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2; 585 if (clk_div == 0) 586 clk_div = 1; 587 588 tmp = DIV_ROUND_UP_ULL((u64)timeout_ns * host->bus_hz, NSEC_PER_SEC); 589 tmp = DIV_ROUND_UP_ULL(tmp, clk_div); 590 591 /* TMOUT[7:0] (RESPONSE_TIMEOUT) */ 592 tmout = 0xFF; /* Set maximum */ 593 594 /* 595 * Extended HW timer (max = 0x6FFFFF2): 596 * ((TMOUT[10:8] - 1) * 0xFFFFFF + TMOUT[31:11] * 8) 597 */ 598 if (!tmp || tmp > 0x6FFFFF2) 599 tmout |= (0xFFFFFF << 8); 600 else { 601 /* TMOUT[10:8] */ 602 tmp2 = (((unsigned int)tmp / 0xFFFFFF) + 1) & 0x7; 603 tmout |= tmp2 << 8; 604 605 /* TMOUT[31:11] */ 606 tmp = tmp - ((tmp2 - 1) * 0xFFFFFF); 607 tmout |= (tmp & 0xFFFFF8) << 8; 608 } 609 610 mci_writel(host, TMOUT, tmout); 611 dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: %#08x", 612 timeout_ns, tmout >> 8); 613 } 614 615 static u32 dw_mci_exynos_get_drto_clks(struct dw_mci *host) 616 { 617 u32 drto_clks; 618 619 drto_clks = mci_readl(host, TMOUT) >> 8; 620 621 return (((drto_clks & 0x7) - 1) * 0xFFFFFF) + ((drto_clks & 0xFFFFF8)); 622 } 623 624 /* Common capabilities of Exynos4/Exynos5 SoC */ 625 static unsigned long exynos_dwmmc_caps[4] = { 626 MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA, 627 0, 628 0, 629 0, 630 }; 631 632 static const struct dw_mci_drv_data exynos_drv_data = { 633 .caps = exynos_dwmmc_caps, 634 .num_caps = ARRAY_SIZE(exynos_dwmmc_caps), 635 .common_caps = MMC_CAP_CMD23, 636 .init = dw_mci_exynos_priv_init, 637 .set_ios = dw_mci_exynos_set_ios, 638 .parse_dt = dw_mci_exynos_parse_dt, 639 .execute_tuning = dw_mci_exynos_execute_tuning, 640 .prepare_hs400_tuning = dw_mci_exynos_prepare_hs400_tuning, 641 }; 642 643 static const struct dw_mci_drv_data artpec_drv_data = { 644 .common_caps = MMC_CAP_CMD23, 645 .init = dw_mci_exynos_priv_init, 646 .set_ios = dw_mci_exynos_set_ios, 647 .parse_dt = dw_mci_exynos_parse_dt, 648 .execute_tuning = dw_mci_exynos_execute_tuning, 649 .set_data_timeout = dw_mci_exynos_set_data_timeout, 650 .get_drto_clks = dw_mci_exynos_get_drto_clks, 651 }; 652 653 static const struct of_device_id dw_mci_exynos_match[] = { 654 { .compatible = "samsung,exynos4412-dw-mshc", 655 .data = &exynos_drv_data, }, 656 { .compatible = "samsung,exynos5250-dw-mshc", 657 .data = &exynos_drv_data, }, 658 { .compatible = "samsung,exynos5420-dw-mshc", 659 .data = &exynos_drv_data, }, 660 { .compatible = "samsung,exynos5420-dw-mshc-smu", 661 .data = &exynos_drv_data, }, 662 { .compatible = "samsung,exynos7-dw-mshc", 663 .data = &exynos_drv_data, }, 664 { .compatible = "samsung,exynos7-dw-mshc-smu", 665 .data = &exynos_drv_data, }, 666 { .compatible = "samsung,exynos7870-dw-mshc", 667 .data = &exynos_drv_data, }, 668 { .compatible = "samsung,exynos7870-dw-mshc-smu", 669 .data = &exynos_drv_data, }, 670 { .compatible = "axis,artpec8-dw-mshc", 671 .data = &artpec_drv_data, }, 672 {}, 673 }; 674 MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); 675 676 static int dw_mci_exynos_probe(struct platform_device *pdev) 677 { 678 const struct dw_mci_drv_data *drv_data; 679 const struct of_device_id *match; 680 int ret; 681 682 match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); 683 drv_data = match->data; 684 685 pm_runtime_get_noresume(&pdev->dev); 686 pm_runtime_set_active(&pdev->dev); 687 pm_runtime_enable(&pdev->dev); 688 689 ret = dw_mci_pltfm_register(pdev, drv_data); 690 if (ret) { 691 pm_runtime_disable(&pdev->dev); 692 pm_runtime_set_suspended(&pdev->dev); 693 pm_runtime_put_noidle(&pdev->dev); 694 695 return ret; 696 } 697 698 return 0; 699 } 700 701 static void dw_mci_exynos_remove(struct platform_device *pdev) 702 { 703 pm_runtime_disable(&pdev->dev); 704 pm_runtime_set_suspended(&pdev->dev); 705 pm_runtime_put_noidle(&pdev->dev); 706 707 dw_mci_pltfm_remove(pdev); 708 } 709 710 static const struct dev_pm_ops dw_mci_exynos_pmops = { 711 NOIRQ_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend_noirq, dw_mci_exynos_resume_noirq) 712 RUNTIME_PM_OPS(dw_mci_runtime_suspend, dw_mci_exynos_runtime_resume, NULL) 713 }; 714 715 static struct platform_driver dw_mci_exynos_pltfm_driver = { 716 .probe = dw_mci_exynos_probe, 717 .remove = dw_mci_exynos_remove, 718 .driver = { 719 .name = "dwmmc_exynos", 720 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 721 .of_match_table = dw_mci_exynos_match, 722 .pm = pm_ptr(&dw_mci_exynos_pmops), 723 }, 724 }; 725 726 module_platform_driver(dw_mci_exynos_pltfm_driver); 727 728 MODULE_DESCRIPTION("Samsung Specific DW-MSHC Driver Extension"); 729 MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com"); 730 MODULE_LICENSE("GPL v2"); 731 MODULE_ALIAS("platform:dwmmc_exynos"); 732