1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2016 Socionext Inc. 4 * Author: Masahiro Yamada <yamada.masahiro@socionext.com> 5 */ 6 7 #include <linux/bitfield.h> 8 #include <linux/bits.h> 9 #include <linux/iopoll.h> 10 #include <linux/module.h> 11 #include <linux/mmc/host.h> 12 #include <linux/mmc/mmc.h> 13 #include <linux/of.h> 14 #include <linux/platform_device.h> 15 #include <linux/reset.h> 16 17 #include "sdhci-pltfm.h" 18 19 /* HRS - Host Register Set (specific to Cadence) */ 20 #define SDHCI_CDNS_HRS04 0x10 /* PHY access port */ 21 #define SDHCI_CDNS_HRS04_ACK BIT(26) 22 #define SDHCI_CDNS_HRS04_RD BIT(25) 23 #define SDHCI_CDNS_HRS04_WR BIT(24) 24 #define SDHCI_CDNS_HRS04_RDATA GENMASK(23, 16) 25 #define SDHCI_CDNS_HRS04_WDATA GENMASK(15, 8) 26 #define SDHCI_CDNS_HRS04_ADDR GENMASK(5, 0) 27 28 #define SDHCI_CDNS_HRS06 0x18 /* eMMC control */ 29 #define SDHCI_CDNS_HRS06_TUNE_UP BIT(15) 30 #define SDHCI_CDNS_HRS06_TUNE GENMASK(13, 8) 31 #define SDHCI_CDNS_HRS06_MODE GENMASK(2, 0) 32 #define SDHCI_CDNS_HRS06_MODE_SD 0x0 33 #define SDHCI_CDNS_HRS06_MODE_MMC_SDR 0x2 34 #define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3 35 #define SDHCI_CDNS_HRS06_MODE_MMC_HS200 0x4 36 #define SDHCI_CDNS_HRS06_MODE_MMC_HS400 0x5 37 #define SDHCI_CDNS_HRS06_MODE_MMC_HS400ES 0x6 38 39 /* SRS - Slot Register Set (SDHCI-compatible) */ 40 #define SDHCI_CDNS_SRS_BASE 0x200 41 42 /* PHY */ 43 #define SDHCI_CDNS_PHY_DLY_SD_HS 0x00 44 #define SDHCI_CDNS_PHY_DLY_SD_DEFAULT 0x01 45 #define SDHCI_CDNS_PHY_DLY_UHS_SDR12 0x02 46 #define SDHCI_CDNS_PHY_DLY_UHS_SDR25 0x03 47 #define SDHCI_CDNS_PHY_DLY_UHS_SDR50 0x04 48 #define SDHCI_CDNS_PHY_DLY_UHS_DDR50 0x05 49 #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06 50 #define SDHCI_CDNS_PHY_DLY_EMMC_SDR 0x07 51 #define SDHCI_CDNS_PHY_DLY_EMMC_DDR 0x08 52 #define SDHCI_CDNS_PHY_DLY_SDCLK 0x0b 53 #define SDHCI_CDNS_PHY_DLY_HSMMC 0x0c 54 #define SDHCI_CDNS_PHY_DLY_STROBE 0x0d 55 56 /* 57 * The tuned val register is 6 bit-wide, but not the whole of the range is 58 * available. The range 0-42 seems to be available (then 43 wraps around to 0) 59 * but I am not quite sure if it is official. Use only 0 to 39 for safety. 60 */ 61 #define SDHCI_CDNS_MAX_TUNING_LOOP 40 62 63 struct sdhci_cdns_phy_param { 64 u8 addr; 65 u8 data; 66 }; 67 68 struct sdhci_cdns_priv { 69 void __iomem *hrs_addr; 70 void __iomem *ctl_addr; /* write control */ 71 spinlock_t wrlock; /* write lock */ 72 bool enhanced_strobe; 73 void (*priv_writel)(struct sdhci_cdns_priv *priv, u32 val, void __iomem *reg); 74 struct reset_control *rst_hw; 75 unsigned int nr_phy_params; 76 struct sdhci_cdns_phy_param phy_params[]; 77 }; 78 79 struct sdhci_cdns_phy_cfg { 80 const char *property; 81 u8 addr; 82 }; 83 84 struct sdhci_cdns_drv_data { 85 int (*init)(struct platform_device *pdev); 86 const struct sdhci_pltfm_data pltfm_data; 87 }; 88 89 static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = { 90 { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, }, 91 { "cdns,phy-input-delay-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, }, 92 { "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, }, 93 { "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, }, 94 { "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, }, 95 { "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, }, 96 { "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, }, 97 { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, }, 98 { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, }, 99 { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, }, 100 { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, }, 101 }; 102 103 static inline void cdns_writel(struct sdhci_cdns_priv *priv, u32 val, 104 void __iomem *reg) 105 { 106 writel(val, reg); 107 } 108 109 static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv, 110 u8 addr, u8 data) 111 { 112 void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04; 113 u32 tmp; 114 int ret; 115 116 ret = readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS04_ACK), 117 0, 10); 118 if (ret) 119 return ret; 120 121 tmp = FIELD_PREP(SDHCI_CDNS_HRS04_WDATA, data) | 122 FIELD_PREP(SDHCI_CDNS_HRS04_ADDR, addr); 123 priv->priv_writel(priv, tmp, reg); 124 125 tmp |= SDHCI_CDNS_HRS04_WR; 126 priv->priv_writel(priv, tmp, reg); 127 128 ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10); 129 if (ret) 130 return ret; 131 132 tmp &= ~SDHCI_CDNS_HRS04_WR; 133 priv->priv_writel(priv, tmp, reg); 134 135 ret = readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS04_ACK), 136 0, 10); 137 138 return ret; 139 } 140 141 static unsigned int sdhci_cdns_phy_param_count(struct device_node *np) 142 { 143 unsigned int count = 0; 144 int i; 145 146 for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) 147 if (of_property_read_bool(np, sdhci_cdns_phy_cfgs[i].property)) 148 count++; 149 150 return count; 151 } 152 153 static void sdhci_cdns_phy_param_parse(struct device_node *np, 154 struct sdhci_cdns_priv *priv) 155 { 156 struct sdhci_cdns_phy_param *p = priv->phy_params; 157 u32 val; 158 int ret, i; 159 160 for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) { 161 ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property, 162 &val); 163 if (ret) 164 continue; 165 166 p->addr = sdhci_cdns_phy_cfgs[i].addr; 167 p->data = val; 168 p++; 169 } 170 } 171 172 static int sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv) 173 { 174 int ret, i; 175 176 for (i = 0; i < priv->nr_phy_params; i++) { 177 ret = sdhci_cdns_write_phy_reg(priv, priv->phy_params[i].addr, 178 priv->phy_params[i].data); 179 if (ret) 180 return ret; 181 } 182 183 return 0; 184 } 185 186 static void *sdhci_cdns_priv(struct sdhci_host *host) 187 { 188 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 189 190 return sdhci_pltfm_priv(pltfm_host); 191 } 192 193 static unsigned int sdhci_cdns_get_timeout_clock(struct sdhci_host *host) 194 { 195 /* 196 * Cadence's spec says the Timeout Clock Frequency is the same as the 197 * Base Clock Frequency. 198 */ 199 return host->max_clk; 200 } 201 202 static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_priv *priv, u32 mode) 203 { 204 u32 tmp; 205 206 /* The speed mode for eMMC is selected by HRS06 register */ 207 tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06); 208 tmp &= ~SDHCI_CDNS_HRS06_MODE; 209 tmp |= FIELD_PREP(SDHCI_CDNS_HRS06_MODE, mode); 210 priv->priv_writel(priv, tmp, priv->hrs_addr + SDHCI_CDNS_HRS06); 211 } 212 213 static u32 sdhci_cdns_get_emmc_mode(struct sdhci_cdns_priv *priv) 214 { 215 u32 tmp; 216 217 tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06); 218 return FIELD_GET(SDHCI_CDNS_HRS06_MODE, tmp); 219 } 220 221 static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val) 222 { 223 struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); 224 void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS06; 225 u32 tmp; 226 int i, ret; 227 228 if (WARN_ON(!FIELD_FIT(SDHCI_CDNS_HRS06_TUNE, val))) 229 return -EINVAL; 230 231 tmp = readl(reg); 232 tmp &= ~SDHCI_CDNS_HRS06_TUNE; 233 tmp |= FIELD_PREP(SDHCI_CDNS_HRS06_TUNE, val); 234 235 /* 236 * Workaround for IP errata: 237 * The IP6116 SD/eMMC PHY design has a timing issue on receive data 238 * path. Send tune request twice. 239 */ 240 for (i = 0; i < 2; i++) { 241 tmp |= SDHCI_CDNS_HRS06_TUNE_UP; 242 priv->priv_writel(priv, tmp, reg); 243 244 ret = readl_poll_timeout(reg, tmp, 245 !(tmp & SDHCI_CDNS_HRS06_TUNE_UP), 246 0, 1); 247 if (ret) 248 return ret; 249 } 250 251 return 0; 252 } 253 254 /* 255 * In SD mode, software must not use the hardware tuning and instead perform 256 * an almost identical procedure to eMMC. 257 */ 258 static int sdhci_cdns_execute_tuning(struct sdhci_host *host, u32 opcode) 259 { 260 int cur_streak = 0; 261 int max_streak = 0; 262 int end_of_streak = 0; 263 int i; 264 265 /* 266 * Do not execute tuning for UHS_SDR50 or UHS_DDR50. 267 * The delay is set by probe, based on the DT properties. 268 */ 269 if (host->timing != MMC_TIMING_MMC_HS200 && 270 host->timing != MMC_TIMING_UHS_SDR104) 271 return 0; 272 273 for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) { 274 if (sdhci_cdns_set_tune_val(host, i) || 275 mmc_send_tuning(host->mmc, opcode, NULL)) { /* bad */ 276 cur_streak = 0; 277 } else { /* good */ 278 cur_streak++; 279 if (cur_streak > max_streak) { 280 max_streak = cur_streak; 281 end_of_streak = i; 282 } 283 } 284 } 285 286 if (!max_streak) { 287 dev_err(mmc_dev(host->mmc), "no tuning point found\n"); 288 return -EIO; 289 } 290 291 return sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2); 292 } 293 294 static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host, 295 unsigned int timing) 296 { 297 struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); 298 u32 mode; 299 300 switch (timing) { 301 case MMC_TIMING_MMC_HS: 302 mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR; 303 break; 304 case MMC_TIMING_MMC_DDR52: 305 mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR; 306 break; 307 case MMC_TIMING_MMC_HS200: 308 mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200; 309 break; 310 case MMC_TIMING_MMC_HS400: 311 if (priv->enhanced_strobe) 312 mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES; 313 else 314 mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400; 315 break; 316 default: 317 mode = SDHCI_CDNS_HRS06_MODE_SD; 318 break; 319 } 320 321 sdhci_cdns_set_emmc_mode(priv, mode); 322 323 /* For SD, fall back to the default handler */ 324 if (mode == SDHCI_CDNS_HRS06_MODE_SD) 325 sdhci_set_uhs_signaling(host, timing); 326 } 327 328 /* Elba control register bits [6:3] are byte-lane enables */ 329 #define ELBA_BYTE_ENABLE_MASK(x) ((x) << 3) 330 331 /* 332 * The Pensando Elba SoC explicitly controls byte-lane enabling on writes 333 * which includes writes to the HRS registers. The write lock (wrlock) 334 * is used to ensure byte-lane enable, using write control (ctl_addr), 335 * occurs before the data write. 336 */ 337 static void elba_priv_writel(struct sdhci_cdns_priv *priv, u32 val, 338 void __iomem *reg) 339 { 340 unsigned long flags; 341 342 spin_lock_irqsave(&priv->wrlock, flags); 343 writel(GENMASK(7, 3), priv->ctl_addr); 344 writel(val, reg); 345 spin_unlock_irqrestore(&priv->wrlock, flags); 346 } 347 348 static void elba_write_l(struct sdhci_host *host, u32 val, int reg) 349 { 350 elba_priv_writel(sdhci_cdns_priv(host), val, host->ioaddr + reg); 351 } 352 353 static void elba_write_w(struct sdhci_host *host, u16 val, int reg) 354 { 355 struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); 356 u32 shift = reg & GENMASK(1, 0); 357 unsigned long flags; 358 u32 byte_enables; 359 360 byte_enables = GENMASK(1, 0) << shift; 361 spin_lock_irqsave(&priv->wrlock, flags); 362 writel(ELBA_BYTE_ENABLE_MASK(byte_enables), priv->ctl_addr); 363 writew(val, host->ioaddr + reg); 364 spin_unlock_irqrestore(&priv->wrlock, flags); 365 } 366 367 static void elba_write_b(struct sdhci_host *host, u8 val, int reg) 368 { 369 struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); 370 u32 shift = reg & GENMASK(1, 0); 371 unsigned long flags; 372 u32 byte_enables; 373 374 byte_enables = BIT(0) << shift; 375 spin_lock_irqsave(&priv->wrlock, flags); 376 writel(ELBA_BYTE_ENABLE_MASK(byte_enables), priv->ctl_addr); 377 writeb(val, host->ioaddr + reg); 378 spin_unlock_irqrestore(&priv->wrlock, flags); 379 } 380 381 static const struct sdhci_ops sdhci_elba_ops = { 382 .write_l = elba_write_l, 383 .write_w = elba_write_w, 384 .write_b = elba_write_b, 385 .set_clock = sdhci_set_clock, 386 .get_timeout_clock = sdhci_cdns_get_timeout_clock, 387 .set_bus_width = sdhci_set_bus_width, 388 .reset = sdhci_reset, 389 .set_uhs_signaling = sdhci_cdns_set_uhs_signaling, 390 }; 391 392 static int elba_drv_init(struct platform_device *pdev) 393 { 394 struct sdhci_host *host = platform_get_drvdata(pdev); 395 struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); 396 void __iomem *ioaddr; 397 398 host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA; 399 spin_lock_init(&priv->wrlock); 400 401 /* Byte-lane control register */ 402 ioaddr = devm_platform_ioremap_resource(pdev, 1); 403 if (IS_ERR(ioaddr)) 404 return PTR_ERR(ioaddr); 405 406 priv->ctl_addr = ioaddr; 407 priv->priv_writel = elba_priv_writel; 408 writel(ELBA_BYTE_ENABLE_MASK(0xf), priv->ctl_addr); 409 410 return 0; 411 } 412 413 static const struct sdhci_ops sdhci_cdns_ops = { 414 .set_clock = sdhci_set_clock, 415 .get_timeout_clock = sdhci_cdns_get_timeout_clock, 416 .set_bus_width = sdhci_set_bus_width, 417 .reset = sdhci_reset, 418 .platform_execute_tuning = sdhci_cdns_execute_tuning, 419 .set_uhs_signaling = sdhci_cdns_set_uhs_signaling, 420 }; 421 422 static const struct sdhci_cdns_drv_data sdhci_cdns_uniphier_drv_data = { 423 .pltfm_data = { 424 .ops = &sdhci_cdns_ops, 425 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, 426 }, 427 }; 428 429 static const struct sdhci_cdns_drv_data sdhci_elba_drv_data = { 430 .init = elba_drv_init, 431 .pltfm_data = { 432 .ops = &sdhci_elba_ops, 433 }, 434 }; 435 436 static const struct sdhci_cdns_drv_data sdhci_cdns_drv_data = { 437 .pltfm_data = { 438 .ops = &sdhci_cdns_ops, 439 }, 440 }; 441 442 static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc, 443 struct mmc_ios *ios) 444 { 445 struct sdhci_host *host = mmc_priv(mmc); 446 struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); 447 u32 mode; 448 449 priv->enhanced_strobe = ios->enhanced_strobe; 450 451 mode = sdhci_cdns_get_emmc_mode(priv); 452 453 if (mode == SDHCI_CDNS_HRS06_MODE_MMC_HS400 && ios->enhanced_strobe) 454 sdhci_cdns_set_emmc_mode(priv, 455 SDHCI_CDNS_HRS06_MODE_MMC_HS400ES); 456 457 if (mode == SDHCI_CDNS_HRS06_MODE_MMC_HS400ES && !ios->enhanced_strobe) 458 sdhci_cdns_set_emmc_mode(priv, 459 SDHCI_CDNS_HRS06_MODE_MMC_HS400); 460 } 461 462 static void sdhci_cdns_mmc_hw_reset(struct mmc_host *mmc) 463 { 464 struct sdhci_host *host = mmc_priv(mmc); 465 struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); 466 467 dev_dbg(mmc_dev(host->mmc), "emmc hardware reset\n"); 468 469 reset_control_assert(priv->rst_hw); 470 /* For eMMC, minimum is 1us but give it 3us for good measure */ 471 udelay(3); 472 473 reset_control_deassert(priv->rst_hw); 474 /* For eMMC, minimum is 200us but give it 300us for good measure */ 475 usleep_range(300, 1000); 476 } 477 478 static int sdhci_cdns_probe(struct platform_device *pdev) 479 { 480 struct sdhci_host *host; 481 const struct sdhci_cdns_drv_data *data; 482 struct sdhci_pltfm_host *pltfm_host; 483 struct sdhci_cdns_priv *priv; 484 struct clk *clk; 485 unsigned int nr_phy_params; 486 int ret; 487 struct device *dev = &pdev->dev; 488 static const u16 version = SDHCI_SPEC_400 << SDHCI_SPEC_VER_SHIFT; 489 490 clk = devm_clk_get_enabled(dev, NULL); 491 if (IS_ERR(clk)) 492 return PTR_ERR(clk); 493 494 data = of_device_get_match_data(dev); 495 if (!data) 496 data = &sdhci_cdns_drv_data; 497 498 nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node); 499 host = sdhci_pltfm_init(pdev, &data->pltfm_data, 500 struct_size(priv, phy_params, nr_phy_params)); 501 if (IS_ERR(host)) 502 return PTR_ERR(host); 503 504 pltfm_host = sdhci_priv(host); 505 pltfm_host->clk = clk; 506 507 priv = sdhci_pltfm_priv(pltfm_host); 508 priv->nr_phy_params = nr_phy_params; 509 priv->hrs_addr = host->ioaddr; 510 priv->enhanced_strobe = false; 511 priv->priv_writel = cdns_writel; 512 host->ioaddr += SDHCI_CDNS_SRS_BASE; 513 host->mmc_host_ops.hs400_enhanced_strobe = 514 sdhci_cdns_hs400_enhanced_strobe; 515 if (data->init) { 516 ret = data->init(pdev); 517 if (ret) 518 goto free; 519 } 520 sdhci_enable_v4_mode(host); 521 __sdhci_read_caps(host, &version, NULL, NULL); 522 523 sdhci_get_of_property(pdev); 524 525 ret = mmc_of_parse(host->mmc); 526 if (ret) 527 goto free; 528 529 sdhci_cdns_phy_param_parse(dev->of_node, priv); 530 531 ret = sdhci_cdns_phy_init(priv); 532 if (ret) 533 goto free; 534 535 if (host->mmc->caps & MMC_CAP_HW_RESET) { 536 priv->rst_hw = devm_reset_control_get_optional_exclusive(dev, NULL); 537 if (IS_ERR(priv->rst_hw)) { 538 ret = dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw), 539 "reset controller error\n"); 540 goto free; 541 } 542 if (priv->rst_hw) 543 host->mmc_host_ops.card_hw_reset = sdhci_cdns_mmc_hw_reset; 544 } 545 546 ret = sdhci_add_host(host); 547 if (ret) 548 goto free; 549 550 return 0; 551 free: 552 sdhci_pltfm_free(pdev); 553 return ret; 554 } 555 556 #ifdef CONFIG_PM_SLEEP 557 static int sdhci_cdns_resume(struct device *dev) 558 { 559 struct sdhci_host *host = dev_get_drvdata(dev); 560 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 561 struct sdhci_cdns_priv *priv = sdhci_pltfm_priv(pltfm_host); 562 int ret; 563 564 ret = clk_prepare_enable(pltfm_host->clk); 565 if (ret) 566 return ret; 567 568 ret = sdhci_cdns_phy_init(priv); 569 if (ret) 570 goto disable_clk; 571 572 ret = sdhci_resume_host(host); 573 if (ret) 574 goto disable_clk; 575 576 return 0; 577 578 disable_clk: 579 clk_disable_unprepare(pltfm_host->clk); 580 581 return ret; 582 } 583 #endif 584 585 static const struct dev_pm_ops sdhci_cdns_pm_ops = { 586 SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_cdns_resume) 587 }; 588 589 static const struct of_device_id sdhci_cdns_match[] = { 590 { 591 .compatible = "socionext,uniphier-sd4hc", 592 .data = &sdhci_cdns_uniphier_drv_data, 593 }, 594 { 595 .compatible = "amd,pensando-elba-sd4hc", 596 .data = &sdhci_elba_drv_data, 597 }, 598 { .compatible = "cdns,sd4hc" }, 599 { /* sentinel */ } 600 }; 601 MODULE_DEVICE_TABLE(of, sdhci_cdns_match); 602 603 static struct platform_driver sdhci_cdns_driver = { 604 .driver = { 605 .name = "sdhci-cdns", 606 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 607 .pm = &sdhci_cdns_pm_ops, 608 .of_match_table = sdhci_cdns_match, 609 }, 610 .probe = sdhci_cdns_probe, 611 .remove_new = sdhci_pltfm_remove, 612 }; 613 module_platform_driver(sdhci_cdns_driver); 614 615 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>"); 616 MODULE_DESCRIPTION("Cadence SD/SDIO/eMMC Host Controller Driver"); 617 MODULE_LICENSE("GPL"); 618