1 /* 2 * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd 3 * 4 * Rockchip SD Host Controller Interface 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <asm/arch/hardware.h> 10 #include <common.h> 11 #include <dm.h> 12 #include <dt-structs.h> 13 #include <linux/libfdt.h> 14 #include <malloc.h> 15 #include <mapmem.h> 16 #include <sdhci.h> 17 #include <clk.h> 18 #include <syscon.h> 19 #include <dm/ofnode.h> 20 #include <asm/arch/clock.h> 21 22 DECLARE_GLOBAL_DATA_PTR; 23 /* 400KHz is max freq for card ID etc. Use that as min */ 24 #define EMMC_MIN_FREQ 400000 25 #define KHz (1000) 26 #define MHz (1000 * KHz) 27 28 #define PHYCTRL_CALDONE_MASK 0x1 29 #define PHYCTRL_CALDONE_SHIFT 0x6 30 #define PHYCTRL_CALDONE_DONE 0x1 31 #define PHYCTRL_DLLRDY_MASK 0x1 32 #define PHYCTRL_DLLRDY_SHIFT 0x5 33 #define PHYCTRL_DLLRDY_DONE 0x1 34 #define PHYCTRL_FREQSEL_200M 0x0 35 #define PHYCTRL_FREQSEL_50M 0x1 36 #define PHYCTRL_FREQSEL_100M 0x2 37 #define PHYCTRL_FREQSEL_150M 0x3 38 #define PHYCTRL_DLL_LOCK_WO_TMOUT(x) \ 39 ((((x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\ 40 PHYCTRL_DLLRDY_DONE) 41 42 /* Rockchip specific Registers */ 43 #define DWCMSHC_CTRL_HS400 0x7 44 #define DWCMSHC_CARD_IS_EMMC BIT(0) 45 #define DWCMSHC_ENHANCED_STROBE BIT(8) 46 47 #define DWCMSHC_HOST_CTRL3 0x508 48 #define DWCMSHC_EMMC_CONTROL 0x52c 49 #define DWCMSHC_EMMC_DLL_CTRL 0x800 50 #define DWCMSHC_EMMC_DLL_CTRL_RESET BIT(1) 51 #define DWCMSHC_EMMC_DLL_RXCLK 0x804 52 #define DWCMSHC_EMMC_DLL_TXCLK 0x808 53 #define DWCMSHC_EMMC_DLL_STRBIN 0x80c 54 #define DECMSHC_EMMC_DLL_CMDOUT 0x810 55 #define DWCMSHC_EMMC_DLL_STATUS0 0x840 56 #define DWCMSHC_EMMC_DLL_STATUS1 0x844 57 #define DWCMSHC_EMMC_DLL_START BIT(0) 58 #define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29 59 #define DWCMSHC_EMMC_DLL_START_POINT 16 60 #define DWCMSHC_EMMC_DLL_START_DEFAULT 5 61 #define DWCMSHC_EMMC_DLL_INC_VALUE 2 62 #define DWCMSHC_EMMC_DLL_INC 8 63 #define DWCMSHC_EMMC_DLL_DLYENA BIT(27) 64 #define DLL_TXCLK_TAPNUM_DEFAULT 0x10 65 #define DLL_TXCLK_TAPNUM_90_DEGREES 0x8 66 #define DLL_STRBIN_TAPNUM_DEFAULT 0x3 67 #define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) 68 #define DLL_TXCLK_NO_INVERTER BIT(29) 69 #define DWCMSHC_EMMC_DLL_LOCKED BIT(8) 70 #define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9) 71 #define DLL_RXCLK_NO_INVERTER 1 72 #define DLL_RXCLK_INVERTER 0 73 #define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8 74 #define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24) 75 #define DLL_CMDOUT_SRC_CLK_NEG BIT(28) 76 #define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29) 77 78 #define DWCMSHC_ENHANCED_STROBE BIT(8) 79 #define DLL_LOCK_WO_TMOUT(x) \ 80 ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ 81 (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) 82 #define ROCKCHIP_MAX_CLKS 3 83 84 struct rockchip_sdhc_plat { 85 #if CONFIG_IS_ENABLED(OF_PLATDATA) 86 struct dtd_rockchip_rk3399_sdhci_5_1 dtplat; 87 #endif 88 struct mmc_config cfg; 89 struct mmc mmc; 90 }; 91 92 struct rockchip_emmc_phy { 93 u32 emmcphy_con[7]; 94 u32 reserved; 95 u32 emmcphy_status; 96 }; 97 98 struct rockchip_sdhc { 99 struct sdhci_host host; 100 struct udevice *dev; 101 void *base; 102 struct rockchip_emmc_phy *phy; 103 struct clk emmc_clk; 104 }; 105 106 struct sdhci_data { 107 int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock); 108 void (*set_ios_post)(struct sdhci_host *host); 109 int (*get_phy)(struct udevice *dev); 110 u32 flags; 111 #define RK_DLL_CMD_OUT BIT(1) 112 #define RK_RXCLK_NO_INVERTER BIT(2) 113 }; 114 115 static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock) 116 { 117 u32 caldone, dllrdy, freqsel; 118 uint start; 119 120 writel(RK_CLRSETBITS(7 << 4, 0), &phy->emmcphy_con[6]); 121 writel(RK_CLRSETBITS(1 << 11, 1 << 11), &phy->emmcphy_con[0]); 122 writel(RK_CLRSETBITS(0xf << 7, 6 << 7), &phy->emmcphy_con[0]); 123 124 /* 125 * According to the user manual, calpad calibration 126 * cycle takes more than 2us without the minimal recommended 127 * value, so we may need a little margin here 128 */ 129 udelay(3); 130 writel(RK_CLRSETBITS(1, 1), &phy->emmcphy_con[6]); 131 132 /* 133 * According to the user manual, it asks driver to 134 * wait 5us for calpad busy trimming. But it seems that 135 * 5us of caldone isn't enough for all cases. 136 */ 137 udelay(500); 138 caldone = readl(&phy->emmcphy_status); 139 caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK; 140 if (caldone != PHYCTRL_CALDONE_DONE) { 141 printf("%s: caldone timeout.\n", __func__); 142 return; 143 } 144 145 /* Set the frequency of the DLL operation */ 146 if (clock < 75 * MHz) 147 freqsel = PHYCTRL_FREQSEL_50M; 148 else if (clock < 125 * MHz) 149 freqsel = PHYCTRL_FREQSEL_100M; 150 else if (clock < 175 * MHz) 151 freqsel = PHYCTRL_FREQSEL_150M; 152 else 153 freqsel = PHYCTRL_FREQSEL_200M; 154 155 /* Set the frequency of the DLL operation */ 156 writel(RK_CLRSETBITS(3 << 12, freqsel << 12), &phy->emmcphy_con[0]); 157 writel(RK_CLRSETBITS(1 << 1, 1 << 1), &phy->emmcphy_con[6]); 158 159 /* REN Enable on STRB Line for HS400 */ 160 writel(RK_CLRSETBITS(0, 1 << 9), &phy->emmcphy_con[2]); 161 162 start = get_timer(0); 163 164 do { 165 udelay(1); 166 dllrdy = readl(&phy->emmcphy_status); 167 dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK; 168 if (dllrdy == PHYCTRL_DLLRDY_DONE) 169 break; 170 } while (get_timer(start) < 50000); 171 172 if (dllrdy != PHYCTRL_DLLRDY_DONE) 173 printf("%s: dllrdy timeout.\n", __func__); 174 } 175 176 static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy) 177 { 178 writel(RK_CLRSETBITS(1, 0), &phy->emmcphy_con[6]); 179 writel(RK_CLRSETBITS(1 << 1, 0), &phy->emmcphy_con[6]); 180 } 181 182 static int rockchip_emmc_set_clock(struct sdhci_host *host, unsigned int clock) 183 { 184 unsigned int div, clk = 0, timeout; 185 unsigned int input_clk; 186 struct rockchip_sdhc *priv = 187 container_of(host, struct rockchip_sdhc, host); 188 189 /* Wait max 20 ms */ 190 timeout = 200; 191 while (sdhci_readl(host, SDHCI_PRESENT_STATE) & 192 (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) { 193 if (timeout == 0) { 194 printf("%s: Timeout to wait cmd & data inhibit\n", 195 __func__); 196 return -EBUSY; 197 } 198 199 timeout--; 200 udelay(100); 201 } 202 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 203 204 if (clock == 0) 205 return 0; 206 207 input_clk = clk_set_rate(&priv->emmc_clk, clock); 208 if (IS_ERR_VALUE(input_clk)) 209 input_clk = host->max_clk; 210 211 if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { 212 /* 213 * Check if the Host Controller supports Programmable Clock 214 * Mode. 215 */ 216 if (host->clk_mul) { 217 for (div = 1; div <= 1024; div++) { 218 if ((input_clk / div) <= clock) 219 break; 220 } 221 222 /* 223 * Set Programmable Clock Mode in the Clock 224 * Control register. 225 */ 226 clk = SDHCI_PROG_CLOCK_MODE; 227 div--; 228 } else { 229 /* Version 3.00 divisors must be a multiple of 2. */ 230 if (input_clk <= clock) { 231 div = 1; 232 } else { 233 for (div = 2; 234 div < SDHCI_MAX_DIV_SPEC_300; 235 div += 2) { 236 if ((input_clk / div) <= clock) 237 break; 238 } 239 } 240 div >>= 1; 241 } 242 } else { 243 /* Version 2.00 divisors must be a power of 2. */ 244 for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 245 if ((input_clk / div) <= clock) 246 break; 247 } 248 div >>= 1; 249 } 250 251 clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 252 clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 253 << SDHCI_DIVIDER_HI_SHIFT; 254 clk |= SDHCI_CLOCK_INT_EN; 255 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 256 257 /* Wait max 20 ms */ 258 timeout = 20; 259 while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 260 & SDHCI_CLOCK_INT_STABLE)) { 261 if (timeout == 0) { 262 printf("%s: Internal clock never stabilised.\n", 263 __func__); 264 return -EBUSY; 265 } 266 timeout--; 267 udelay(1000); 268 } 269 clk |= SDHCI_CLOCK_CARD_EN; 270 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 271 host->clock = clock; 272 273 return 0; 274 } 275 276 static int rk3399_emmc_get_phy(struct udevice *dev) 277 { 278 struct rockchip_sdhc *priv = dev_get_priv(dev); 279 280 #if CONFIG_IS_ENABLED(OF_PLATDATA) 281 priv->phy = (struct rockchip_emmc_phy *)0xff77f780; 282 #else 283 ofnode phy_node; 284 void *grf_base; 285 u32 grf_phy_offset, phandle; 286 287 phandle = dev_read_u32_default(dev, "phys", 0); 288 phy_node = ofnode_get_by_phandle(phandle); 289 if (!ofnode_valid(phy_node)) { 290 debug("Not found emmc phy device\n"); 291 return -ENODEV; 292 } 293 294 grf_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 295 if (IS_ERR(grf_base)) 296 printf("%s Get syscon grf failed", __func__); 297 grf_phy_offset = ofnode_read_u32_default(phy_node, "reg", 0); 298 299 priv->phy = (struct rockchip_emmc_phy *)(grf_base + grf_phy_offset); 300 #endif 301 return 0; 302 } 303 304 static int rk3399_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock) 305 { 306 struct rockchip_sdhc *priv = 307 container_of(host, struct rockchip_sdhc, host); 308 int cycle_phy = host->clock != clock && 309 clock > EMMC_MIN_FREQ; 310 311 if (cycle_phy) 312 rk3399_emmc_phy_power_off(priv->phy); 313 314 rockchip_emmc_set_clock(host, clock); 315 316 if (cycle_phy) 317 rk3399_emmc_phy_power_on(priv->phy, clock); 318 319 return 0; 320 } 321 322 static int dwcmshc_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock) 323 { 324 struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); 325 struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); 326 u32 extra; 327 int timeout = 500, ret; 328 329 ret = rockchip_emmc_set_clock(host, clock); 330 331 if (clock >= 100 * MHz) { 332 /* reset DLL */ 333 sdhci_writel(host, DWCMSHC_EMMC_DLL_CTRL_RESET, DWCMSHC_EMMC_DLL_CTRL); 334 udelay(1); 335 sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); 336 337 /* Init DLL settings */ 338 extra = DWCMSHC_EMMC_DLL_START_DEFAULT << DWCMSHC_EMMC_DLL_START_POINT | 339 DWCMSHC_EMMC_DLL_INC_VALUE << DWCMSHC_EMMC_DLL_INC | 340 DWCMSHC_EMMC_DLL_START; 341 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL); 342 343 while (1) { 344 if (timeout < 0) 345 return -ETIMEDOUT; 346 if (DLL_LOCK_WO_TMOUT((sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS0)))) 347 break; 348 udelay(1); 349 timeout--; 350 } 351 extra = DWCMSHC_EMMC_DLL_DLYENA; 352 if (data->flags & RK_RXCLK_NO_INVERTER) 353 extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; 354 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); 355 356 extra = DWCMSHC_EMMC_DLL_DLYENA | 357 DLL_TXCLK_TAPNUM_FROM_SW | 358 DLL_TXCLK_NO_INVERTER| 359 DLL_TXCLK_TAPNUM_DEFAULT; 360 361 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); 362 363 extra = DWCMSHC_EMMC_DLL_DLYENA | 364 DLL_STRBIN_TAPNUM_DEFAULT; 365 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); 366 } else { 367 /* Disable cmd conflict check */ 368 extra = sdhci_readl(host, DWCMSHC_HOST_CTRL3); 369 extra &= ~BIT(0); 370 sdhci_writel(host, extra, DWCMSHC_HOST_CTRL3); 371 372 /* reset the clock phase when the frequency is lower than 100MHz */ 373 sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); 374 sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK); 375 sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK); 376 sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN); 377 sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT); 378 } 379 return ret; 380 } 381 382 static void dwcmshc_sdhci_set_ios_post(struct sdhci_host *host) 383 { 384 u16 ctrl; 385 u32 extra; 386 u32 timing = host->mmc->timing; 387 388 if (timing == MMC_TIMING_MMC_HS400 || timing == MMC_TIMING_MMC_HS400ES) { 389 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 390 ctrl &= ~SDHCI_CTRL_UHS_MASK; 391 ctrl |= DWCMSHC_CTRL_HS400; 392 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 393 394 /* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */ 395 ctrl = sdhci_readw(host, DWCMSHC_EMMC_CONTROL); 396 ctrl |= DWCMSHC_CARD_IS_EMMC; 397 sdhci_writew(host, ctrl, DWCMSHC_EMMC_CONTROL); 398 399 extra = DLL_CMDOUT_SRC_CLK_NEG | 400 DLL_CMDOUT_EN_SRC_CLK_NEG; 401 sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT); 402 403 extra = DWCMSHC_EMMC_DLL_DLYENA | 404 DLL_TXCLK_TAPNUM_FROM_SW | 405 DLL_TXCLK_NO_INVERTER| 406 DLL_TXCLK_TAPNUM_90_DEGREES; 407 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); 408 } 409 } 410 411 static int dwcmshc_emmc_get_phy(struct udevice *dev) 412 { 413 return 0; 414 } 415 416 static int rockchip_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 417 { 418 struct rockchip_sdhc *priv = 419 container_of(host, struct rockchip_sdhc, host); 420 struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); 421 if (!data) 422 return -EINVAL; 423 424 return data->emmc_set_clock(host, clock); 425 } 426 427 static void rockchip_sdhci_set_ios_post(struct sdhci_host *host) 428 { 429 struct rockchip_sdhc *priv = 430 container_of(host, struct rockchip_sdhc, host); 431 struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); 432 433 if (data && data->set_ios_post) 434 data->set_ios_post(host); 435 } 436 437 static struct sdhci_ops rockchip_sdhci_ops = { 438 .set_clock = rockchip_sdhci_set_clock, 439 .set_ios_post = rockchip_sdhci_set_ios_post, 440 }; 441 442 static int rockchip_sdhci_probe(struct udevice *dev) 443 { 444 struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(dev); 445 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 446 struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); 447 struct rockchip_sdhc *prv = dev_get_priv(dev); 448 struct sdhci_host *host = &prv->host; 449 int max_frequency, ret; 450 struct clk clk; 451 452 #if CONFIG_IS_ENABLED(OF_PLATDATA) 453 struct dtd_rockchip_rk3399_sdhci_5_1 *dtplat = &plat->dtplat; 454 455 host->name = dev->name; 456 host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); 457 host->host_caps |= MMC_MODE_8BIT; 458 max_frequency = dtplat->max_frequency; 459 ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk); 460 #else 461 max_frequency = dev_read_u32_default(dev, "max-frequency", 0); 462 switch (dev_read_u32_default(dev, "bus-width", 4)) { 463 case 8: 464 host->host_caps |= MMC_MODE_8BIT; 465 break; 466 case 4: 467 host->host_caps |= MMC_MODE_4BIT; 468 break; 469 case 1: 470 break; 471 default: 472 printf("Invalid \"bus-width\" value\n"); 473 return -EINVAL; 474 } 475 ret = clk_get_by_index(dev, 0, &clk); 476 #endif 477 if (!ret) { 478 ret = clk_set_rate(&clk, max_frequency); 479 if (IS_ERR_VALUE(ret)) 480 printf("%s clk set rate fail!\n", __func__); 481 } else { 482 printf("%s fail to get clk\n", __func__); 483 } 484 485 prv->emmc_clk = clk; 486 prv->dev = dev; 487 ret = data->get_phy(dev); 488 if (ret) 489 return ret; 490 491 host->ops = &rockchip_sdhci_ops; 492 493 host->max_clk = max_frequency; 494 495 if (dev_read_bool(dev, "mmc-hs200-1_8v")) 496 host->host_caps |= MMC_MODE_HS200; 497 else if (dev_read_bool(dev, "mmc-hs400-1_8v")) 498 host->host_caps |= MMC_MODE_HS400; 499 ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ); 500 501 host->mmc = &plat->mmc; 502 if (ret) 503 return ret; 504 host->mmc->priv = &prv->host; 505 host->mmc->dev = dev; 506 upriv->mmc = host->mmc; 507 508 return sdhci_probe(dev); 509 } 510 511 static int rockchip_sdhci_of_to_plat(struct udevice *dev) 512 { 513 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 514 struct sdhci_host *host = dev_get_priv(dev); 515 516 host->name = dev->name; 517 host->ioaddr = dev_read_addr_ptr(dev); 518 #endif 519 520 return 0; 521 } 522 523 static int rockchip_sdhci_bind(struct udevice *dev) 524 { 525 struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); 526 527 return sdhci_bind(dev, &plat->mmc, &plat->cfg); 528 } 529 530 static const struct sdhci_data arasan_data = { 531 .emmc_set_clock = rk3399_sdhci_emmc_set_clock, 532 .get_phy = rk3399_emmc_get_phy, 533 }; 534 535 static const struct sdhci_data rk3568_data = { 536 .emmc_set_clock = dwcmshc_sdhci_emmc_set_clock, 537 .get_phy = dwcmshc_emmc_get_phy, 538 .flags = RK_RXCLK_NO_INVERTER, 539 }; 540 541 static const struct sdhci_data rk3588_data = { 542 .emmc_set_clock = dwcmshc_sdhci_emmc_set_clock, 543 .get_phy = dwcmshc_emmc_get_phy, 544 .set_ios_post = dwcmshc_sdhci_set_ios_post, 545 .flags = RK_DLL_CMD_OUT | RK_RXCLK_NO_INVERTER, 546 }; 547 548 static const struct udevice_id sdhci_ids[] = { 549 { 550 .compatible = "arasan,sdhci-5.1", 551 .data = (ulong)&arasan_data, 552 }, 553 { 554 .compatible = "snps,dwcmshc-sdhci", 555 .data = (ulong)&rk3568_data, 556 }, 557 { 558 .compatible = "rockchip,rk3588-dwcmshc", 559 .data = (ulong)&rk3588_data, 560 }, 561 { } 562 }; 563 564 U_BOOT_DRIVER(arasan_sdhci_drv) = { 565 .name = "rockchip_sdhci_5_1", 566 .id = UCLASS_MMC, 567 .of_match = sdhci_ids, 568 .ofdata_to_platdata = rockchip_sdhci_of_to_plat, 569 .ops = &sdhci_ops, 570 .bind = rockchip_sdhci_bind, 571 .probe = rockchip_sdhci_probe, 572 .priv_auto_alloc_size = sizeof(struct rockchip_sdhc), 573 .platdata_auto_alloc_size = sizeof(struct rockchip_sdhc_plat), 574 }; 575