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