1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Copyright (C) 2019 ASPEED Technology Inc. */ 3 /* Copyright (C) 2019 IBM Corp. */ 4 5 #include <linux/clk.h> 6 #include <linux/delay.h> 7 #include <linux/device.h> 8 #include <linux/io.h> 9 #include <linux/math64.h> 10 #include <linux/mmc/host.h> 11 #include <linux/module.h> 12 #include <linux/of_address.h> 13 #include <linux/of.h> 14 #include <linux/of_platform.h> 15 #include <linux/platform_device.h> 16 #include <linux/spinlock.h> 17 18 #include "sdhci-pltfm.h" 19 20 #define ASPEED_SDC_INFO 0x00 21 #define ASPEED_SDC_S1_MMC8 BIT(25) 22 #define ASPEED_SDC_S0_MMC8 BIT(24) 23 #define ASPEED_SDC_PHASE 0xf4 24 #define ASPEED_SDC_S1_PHASE_IN GENMASK(25, 21) 25 #define ASPEED_SDC_S0_PHASE_IN GENMASK(20, 16) 26 #define ASPEED_SDC_S1_PHASE_OUT GENMASK(15, 11) 27 #define ASPEED_SDC_S1_PHASE_IN_EN BIT(10) 28 #define ASPEED_SDC_S1_PHASE_OUT_EN GENMASK(9, 8) 29 #define ASPEED_SDC_S0_PHASE_OUT GENMASK(7, 3) 30 #define ASPEED_SDC_S0_PHASE_IN_EN BIT(2) 31 #define ASPEED_SDC_S0_PHASE_OUT_EN GENMASK(1, 0) 32 #define ASPEED_SDC_PHASE_MAX 31 33 34 struct aspeed_sdc { 35 struct clk *clk; 36 struct resource *res; 37 38 spinlock_t lock; 39 void __iomem *regs; 40 }; 41 42 struct aspeed_sdhci_tap_param { 43 bool valid; 44 45 #define ASPEED_SDHCI_TAP_PARAM_INVERT_CLK BIT(4) 46 u8 in; 47 u8 out; 48 }; 49 50 struct aspeed_sdhci_tap_desc { 51 u32 tap_mask; 52 u32 enable_mask; 53 u8 enable_value; 54 }; 55 56 struct aspeed_sdhci_phase_desc { 57 struct aspeed_sdhci_tap_desc in; 58 struct aspeed_sdhci_tap_desc out; 59 }; 60 61 struct aspeed_sdhci_pdata { 62 unsigned int clk_div_start; 63 const struct aspeed_sdhci_phase_desc *phase_desc; 64 size_t nr_phase_descs; 65 }; 66 67 struct aspeed_sdhci { 68 const struct aspeed_sdhci_pdata *pdata; 69 struct aspeed_sdc *parent; 70 u32 width_mask; 71 struct mmc_clk_phase_map phase_map; 72 const struct aspeed_sdhci_phase_desc *phase_desc; 73 }; 74 75 static void aspeed_sdc_configure_8bit_mode(struct aspeed_sdc *sdc, 76 struct aspeed_sdhci *sdhci, 77 bool bus8) 78 { 79 u32 info; 80 81 /* Set/clear 8 bit mode */ 82 spin_lock(&sdc->lock); 83 info = readl(sdc->regs + ASPEED_SDC_INFO); 84 if (bus8) 85 info |= sdhci->width_mask; 86 else 87 info &= ~sdhci->width_mask; 88 writel(info, sdc->regs + ASPEED_SDC_INFO); 89 spin_unlock(&sdc->lock); 90 } 91 92 static u32 93 aspeed_sdc_set_phase_tap(const struct aspeed_sdhci_tap_desc *desc, 94 u8 tap, bool enable, u32 reg) 95 { 96 reg &= ~(desc->enable_mask | desc->tap_mask); 97 if (enable) { 98 reg |= tap << __ffs(desc->tap_mask); 99 reg |= desc->enable_value << __ffs(desc->enable_mask); 100 } 101 102 return reg; 103 } 104 105 static void 106 aspeed_sdc_set_phase_taps(struct aspeed_sdc *sdc, 107 const struct aspeed_sdhci_phase_desc *desc, 108 const struct aspeed_sdhci_tap_param *taps) 109 { 110 u32 reg; 111 112 spin_lock(&sdc->lock); 113 reg = readl(sdc->regs + ASPEED_SDC_PHASE); 114 115 reg = aspeed_sdc_set_phase_tap(&desc->in, taps->in, taps->valid, reg); 116 reg = aspeed_sdc_set_phase_tap(&desc->out, taps->out, taps->valid, reg); 117 118 writel(reg, sdc->regs + ASPEED_SDC_PHASE); 119 spin_unlock(&sdc->lock); 120 } 121 122 #define PICOSECONDS_PER_SECOND 1000000000000ULL 123 #define ASPEED_SDHCI_NR_TAPS 15 124 /* Measured value with *handwave* environmentals and static loading */ 125 #define ASPEED_SDHCI_MAX_TAP_DELAY_PS 1253 126 static int aspeed_sdhci_phase_to_tap(struct device *dev, unsigned long rate_hz, 127 int phase_deg) 128 { 129 u64 phase_period_ps; 130 u64 prop_delay_ps; 131 u64 clk_period_ps; 132 unsigned int tap; 133 u8 inverted; 134 135 phase_deg %= 360; 136 137 if (phase_deg >= 180) { 138 inverted = ASPEED_SDHCI_TAP_PARAM_INVERT_CLK; 139 phase_deg -= 180; 140 dev_dbg(dev, 141 "Inverting clock to reduce phase correction from %d to %d degrees\n", 142 phase_deg + 180, phase_deg); 143 } else { 144 inverted = 0; 145 } 146 147 prop_delay_ps = ASPEED_SDHCI_MAX_TAP_DELAY_PS / ASPEED_SDHCI_NR_TAPS; 148 clk_period_ps = div_u64(PICOSECONDS_PER_SECOND, (u64)rate_hz); 149 phase_period_ps = div_u64((u64)phase_deg * clk_period_ps, 360ULL); 150 151 tap = div_u64(phase_period_ps, prop_delay_ps); 152 if (tap > ASPEED_SDHCI_NR_TAPS) { 153 dev_warn(dev, 154 "Requested out of range phase tap %d for %d degrees of phase compensation at %luHz, clamping to tap %d\n", 155 tap, phase_deg, rate_hz, ASPEED_SDHCI_NR_TAPS); 156 tap = ASPEED_SDHCI_NR_TAPS; 157 } 158 159 return inverted | tap; 160 } 161 162 static void 163 aspeed_sdhci_phases_to_taps(struct device *dev, unsigned long rate, 164 const struct mmc_clk_phase *phases, 165 struct aspeed_sdhci_tap_param *taps) 166 { 167 taps->valid = phases->valid; 168 169 if (!phases->valid) 170 return; 171 172 taps->in = aspeed_sdhci_phase_to_tap(dev, rate, phases->in_deg); 173 taps->out = aspeed_sdhci_phase_to_tap(dev, rate, phases->out_deg); 174 } 175 176 static void 177 aspeed_sdhci_configure_phase(struct sdhci_host *host, unsigned long rate) 178 { 179 struct aspeed_sdhci_tap_param _taps = {0}, *taps = &_taps; 180 struct mmc_clk_phase *params; 181 struct aspeed_sdhci *sdhci; 182 struct device *dev; 183 184 dev = host->mmc->parent; 185 sdhci = sdhci_pltfm_priv(sdhci_priv(host)); 186 187 if (!sdhci->phase_desc) 188 return; 189 190 params = &sdhci->phase_map.phase[host->timing]; 191 aspeed_sdhci_phases_to_taps(dev, rate, params, taps); 192 aspeed_sdc_set_phase_taps(sdhci->parent, sdhci->phase_desc, taps); 193 dev_dbg(dev, 194 "Using taps [%d, %d] for [%d, %d] degrees of phase correction at %luHz (%d)\n", 195 taps->in & ASPEED_SDHCI_NR_TAPS, 196 taps->out & ASPEED_SDHCI_NR_TAPS, 197 params->in_deg, params->out_deg, rate, host->timing); 198 } 199 200 static void aspeed_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 201 { 202 struct sdhci_pltfm_host *pltfm_host; 203 unsigned long parent, bus; 204 struct aspeed_sdhci *sdhci; 205 int div; 206 u16 clk; 207 208 pltfm_host = sdhci_priv(host); 209 sdhci = sdhci_pltfm_priv(pltfm_host); 210 211 parent = clk_get_rate(pltfm_host->clk); 212 213 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 214 215 if (clock == 0) 216 return; 217 218 if (WARN_ON(clock > host->max_clk)) 219 clock = host->max_clk; 220 221 /* 222 * Regarding the AST2600: 223 * 224 * If (EMMC12C[7:6], EMMC12C[15:8] == 0) then 225 * period of SDCLK = period of SDMCLK. 226 * 227 * If (EMMC12C[7:6], EMMC12C[15:8] != 0) then 228 * period of SDCLK = period of SDMCLK * 2 * (EMMC12C[7:6], EMMC[15:8]) 229 * 230 * If you keep EMMC12C[7:6] = 0 and EMMC12C[15:8] as one-hot, 231 * 0x1/0x2/0x4/etc, you will find it is compatible to AST2400 or AST2500 232 * 233 * Keep the one-hot behaviour for backwards compatibility except for 234 * supporting the value 0 in (EMMC12C[7:6], EMMC12C[15:8]), and capture 235 * the 0-value capability in clk_div_start. 236 */ 237 for (div = sdhci->pdata->clk_div_start; div < 256; div *= 2) { 238 bus = parent / div; 239 if (bus <= clock) 240 break; 241 } 242 243 div >>= 1; 244 245 clk = div << SDHCI_DIVIDER_SHIFT; 246 247 aspeed_sdhci_configure_phase(host, bus); 248 249 sdhci_enable_clk(host, clk); 250 } 251 252 static unsigned int aspeed_sdhci_get_max_clock(struct sdhci_host *host) 253 { 254 if (host->mmc->f_max) 255 return host->mmc->f_max; 256 257 return sdhci_pltfm_clk_get_max_clock(host); 258 } 259 260 static void aspeed_sdhci_set_bus_width(struct sdhci_host *host, int width) 261 { 262 struct sdhci_pltfm_host *pltfm_priv; 263 struct aspeed_sdhci *aspeed_sdhci; 264 struct aspeed_sdc *aspeed_sdc; 265 u8 ctrl; 266 267 pltfm_priv = sdhci_priv(host); 268 aspeed_sdhci = sdhci_pltfm_priv(pltfm_priv); 269 aspeed_sdc = aspeed_sdhci->parent; 270 271 /* Set/clear 8-bit mode */ 272 aspeed_sdc_configure_8bit_mode(aspeed_sdc, aspeed_sdhci, 273 width == MMC_BUS_WIDTH_8); 274 275 /* Set/clear 1 or 4 bit mode */ 276 ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 277 if (width == MMC_BUS_WIDTH_4) 278 ctrl |= SDHCI_CTRL_4BITBUS; 279 else 280 ctrl &= ~SDHCI_CTRL_4BITBUS; 281 sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 282 } 283 284 static u32 aspeed_sdhci_readl(struct sdhci_host *host, int reg) 285 { 286 u32 val = readl(host->ioaddr + reg); 287 288 if (unlikely(reg == SDHCI_PRESENT_STATE) && 289 (host->mmc->caps2 & MMC_CAP2_CD_ACTIVE_HIGH)) 290 val ^= SDHCI_CARD_PRESENT; 291 292 return val; 293 } 294 295 static const struct sdhci_ops aspeed_sdhci_ops = { 296 .read_l = aspeed_sdhci_readl, 297 .set_clock = aspeed_sdhci_set_clock, 298 .get_max_clock = aspeed_sdhci_get_max_clock, 299 .set_bus_width = aspeed_sdhci_set_bus_width, 300 .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, 301 .reset = sdhci_reset, 302 .set_uhs_signaling = sdhci_set_uhs_signaling, 303 }; 304 305 static const struct sdhci_pltfm_data aspeed_sdhci_pdata = { 306 .ops = &aspeed_sdhci_ops, 307 .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 308 }; 309 310 static inline int aspeed_sdhci_calculate_slot(struct aspeed_sdhci *dev, 311 struct resource *res) 312 { 313 resource_size_t delta; 314 315 if (!res || resource_type(res) != IORESOURCE_MEM) 316 return -EINVAL; 317 318 if (res->start < dev->parent->res->start) 319 return -EINVAL; 320 321 delta = res->start - dev->parent->res->start; 322 if (delta & (0x100 - 1)) 323 return -EINVAL; 324 325 return (delta / 0x100) - 1; 326 } 327 328 static int aspeed_sdhci_probe(struct platform_device *pdev) 329 { 330 const struct aspeed_sdhci_pdata *aspeed_pdata; 331 struct sdhci_pltfm_host *pltfm_host; 332 struct aspeed_sdhci *dev; 333 struct sdhci_host *host; 334 struct resource *res; 335 int slot; 336 int ret; 337 338 aspeed_pdata = of_device_get_match_data(&pdev->dev); 339 if (!aspeed_pdata) { 340 dev_err(&pdev->dev, "Missing platform configuration data\n"); 341 return -EINVAL; 342 } 343 344 host = sdhci_pltfm_init(pdev, &aspeed_sdhci_pdata, sizeof(*dev)); 345 if (IS_ERR(host)) 346 return PTR_ERR(host); 347 348 pltfm_host = sdhci_priv(host); 349 dev = sdhci_pltfm_priv(pltfm_host); 350 dev->pdata = aspeed_pdata; 351 dev->parent = dev_get_drvdata(pdev->dev.parent); 352 353 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 354 slot = aspeed_sdhci_calculate_slot(dev, res); 355 356 if (slot < 0) 357 return slot; 358 else if (slot >= 2) 359 return -EINVAL; 360 361 if (slot < dev->pdata->nr_phase_descs) { 362 dev->phase_desc = &dev->pdata->phase_desc[slot]; 363 } else { 364 dev_info(&pdev->dev, 365 "Phase control not supported for slot %d\n", slot); 366 dev->phase_desc = NULL; 367 } 368 369 dev->width_mask = !slot ? ASPEED_SDC_S0_MMC8 : ASPEED_SDC_S1_MMC8; 370 371 dev_info(&pdev->dev, "Configured for slot %d\n", slot); 372 373 sdhci_get_of_property(pdev); 374 375 pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); 376 if (IS_ERR(pltfm_host->clk)) 377 return PTR_ERR(pltfm_host->clk); 378 379 ret = clk_prepare_enable(pltfm_host->clk); 380 if (ret) { 381 dev_err(&pdev->dev, "Unable to enable SDIO clock\n"); 382 goto err_pltfm_free; 383 } 384 385 ret = mmc_of_parse(host->mmc); 386 if (ret) 387 goto err_sdhci_add; 388 389 if (dev->phase_desc) 390 mmc_of_parse_clk_phase(host->mmc, &dev->phase_map); 391 392 ret = sdhci_add_host(host); 393 if (ret) 394 goto err_sdhci_add; 395 396 return 0; 397 398 err_sdhci_add: 399 clk_disable_unprepare(pltfm_host->clk); 400 err_pltfm_free: 401 sdhci_pltfm_free(pdev); 402 return ret; 403 } 404 405 static int aspeed_sdhci_remove(struct platform_device *pdev) 406 { 407 struct sdhci_pltfm_host *pltfm_host; 408 struct sdhci_host *host; 409 int dead = 0; 410 411 host = platform_get_drvdata(pdev); 412 pltfm_host = sdhci_priv(host); 413 414 sdhci_remove_host(host, dead); 415 416 clk_disable_unprepare(pltfm_host->clk); 417 418 sdhci_pltfm_free(pdev); 419 420 return 0; 421 } 422 423 static const struct aspeed_sdhci_pdata ast2400_sdhci_pdata = { 424 .clk_div_start = 2, 425 }; 426 427 static const struct aspeed_sdhci_phase_desc ast2600_sdhci_phase[] = { 428 /* SDHCI/Slot 0 */ 429 [0] = { 430 .in = { 431 .tap_mask = ASPEED_SDC_S0_PHASE_IN, 432 .enable_mask = ASPEED_SDC_S0_PHASE_IN_EN, 433 .enable_value = 1, 434 }, 435 .out = { 436 .tap_mask = ASPEED_SDC_S0_PHASE_OUT, 437 .enable_mask = ASPEED_SDC_S0_PHASE_OUT_EN, 438 .enable_value = 3, 439 }, 440 }, 441 /* SDHCI/Slot 1 */ 442 [1] = { 443 .in = { 444 .tap_mask = ASPEED_SDC_S1_PHASE_IN, 445 .enable_mask = ASPEED_SDC_S1_PHASE_IN_EN, 446 .enable_value = 1, 447 }, 448 .out = { 449 .tap_mask = ASPEED_SDC_S1_PHASE_OUT, 450 .enable_mask = ASPEED_SDC_S1_PHASE_OUT_EN, 451 .enable_value = 3, 452 }, 453 }, 454 }; 455 456 static const struct aspeed_sdhci_pdata ast2600_sdhci_pdata = { 457 .clk_div_start = 1, 458 .phase_desc = ast2600_sdhci_phase, 459 .nr_phase_descs = ARRAY_SIZE(ast2600_sdhci_phase), 460 }; 461 462 static const struct of_device_id aspeed_sdhci_of_match[] = { 463 { .compatible = "aspeed,ast2400-sdhci", .data = &ast2400_sdhci_pdata, }, 464 { .compatible = "aspeed,ast2500-sdhci", .data = &ast2400_sdhci_pdata, }, 465 { .compatible = "aspeed,ast2600-sdhci", .data = &ast2600_sdhci_pdata, }, 466 { } 467 }; 468 469 static struct platform_driver aspeed_sdhci_driver = { 470 .driver = { 471 .name = "sdhci-aspeed", 472 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 473 .of_match_table = aspeed_sdhci_of_match, 474 }, 475 .probe = aspeed_sdhci_probe, 476 .remove = aspeed_sdhci_remove, 477 }; 478 479 static int aspeed_sdc_probe(struct platform_device *pdev) 480 481 { 482 struct device_node *parent, *child; 483 struct aspeed_sdc *sdc; 484 int ret; 485 486 sdc = devm_kzalloc(&pdev->dev, sizeof(*sdc), GFP_KERNEL); 487 if (!sdc) 488 return -ENOMEM; 489 490 spin_lock_init(&sdc->lock); 491 492 sdc->clk = devm_clk_get(&pdev->dev, NULL); 493 if (IS_ERR(sdc->clk)) 494 return PTR_ERR(sdc->clk); 495 496 ret = clk_prepare_enable(sdc->clk); 497 if (ret) { 498 dev_err(&pdev->dev, "Unable to enable SDCLK\n"); 499 return ret; 500 } 501 502 sdc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 503 sdc->regs = devm_ioremap_resource(&pdev->dev, sdc->res); 504 if (IS_ERR(sdc->regs)) { 505 ret = PTR_ERR(sdc->regs); 506 goto err_clk; 507 } 508 509 dev_set_drvdata(&pdev->dev, sdc); 510 511 parent = pdev->dev.of_node; 512 for_each_available_child_of_node(parent, child) { 513 struct platform_device *cpdev; 514 515 cpdev = of_platform_device_create(child, NULL, &pdev->dev); 516 if (!cpdev) { 517 of_node_put(child); 518 ret = -ENODEV; 519 goto err_clk; 520 } 521 } 522 523 return 0; 524 525 err_clk: 526 clk_disable_unprepare(sdc->clk); 527 return ret; 528 } 529 530 static int aspeed_sdc_remove(struct platform_device *pdev) 531 { 532 struct aspeed_sdc *sdc = dev_get_drvdata(&pdev->dev); 533 534 clk_disable_unprepare(sdc->clk); 535 536 return 0; 537 } 538 539 static const struct of_device_id aspeed_sdc_of_match[] = { 540 { .compatible = "aspeed,ast2400-sd-controller", }, 541 { .compatible = "aspeed,ast2500-sd-controller", }, 542 { .compatible = "aspeed,ast2600-sd-controller", }, 543 { } 544 }; 545 546 MODULE_DEVICE_TABLE(of, aspeed_sdc_of_match); 547 548 static struct platform_driver aspeed_sdc_driver = { 549 .driver = { 550 .name = "sd-controller-aspeed", 551 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 552 .pm = &sdhci_pltfm_pmops, 553 .of_match_table = aspeed_sdc_of_match, 554 }, 555 .probe = aspeed_sdc_probe, 556 .remove = aspeed_sdc_remove, 557 }; 558 559 #if defined(CONFIG_MMC_SDHCI_OF_ASPEED_TEST) 560 #include "sdhci-of-aspeed-test.c" 561 562 static inline int aspeed_sdc_tests_init(void) 563 { 564 return __kunit_test_suites_init(aspeed_sdc_test_suites); 565 } 566 567 static inline void aspeed_sdc_tests_exit(void) 568 { 569 __kunit_test_suites_exit(aspeed_sdc_test_suites); 570 } 571 #else 572 static inline int aspeed_sdc_tests_init(void) 573 { 574 return 0; 575 } 576 577 static inline void aspeed_sdc_tests_exit(void) 578 { 579 } 580 #endif 581 582 static int __init aspeed_sdc_init(void) 583 { 584 int rc; 585 586 rc = platform_driver_register(&aspeed_sdhci_driver); 587 if (rc < 0) 588 return rc; 589 590 rc = platform_driver_register(&aspeed_sdc_driver); 591 if (rc < 0) 592 goto cleanup_sdhci; 593 594 rc = aspeed_sdc_tests_init(); 595 if (rc < 0) { 596 platform_driver_unregister(&aspeed_sdc_driver); 597 goto cleanup_sdhci; 598 } 599 600 return 0; 601 602 cleanup_sdhci: 603 platform_driver_unregister(&aspeed_sdhci_driver); 604 605 return rc; 606 } 607 module_init(aspeed_sdc_init); 608 609 static void __exit aspeed_sdc_exit(void) 610 { 611 aspeed_sdc_tests_exit(); 612 613 platform_driver_unregister(&aspeed_sdc_driver); 614 platform_driver_unregister(&aspeed_sdhci_driver); 615 } 616 module_exit(aspeed_sdc_exit); 617 618 MODULE_DESCRIPTION("Driver for the ASPEED SD/SDIO/SDHCI Controllers"); 619 MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>"); 620 MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>"); 621 MODULE_LICENSE("GPL"); 622