1 /* 2 * (C) Copyright 2007-2011 3 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> 4 * Aaron <leafy.myeh@allwinnertech.com> 5 * 6 * MMC driver for allwinner sunxi platform. 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <dm.h> 13 #include <errno.h> 14 #include <malloc.h> 15 #include <mmc.h> 16 #include <asm/io.h> 17 #include <asm/arch/clock.h> 18 #include <asm/arch/cpu.h> 19 #include <asm/arch/gpio.h> 20 #include <asm/arch/mmc.h> 21 #include <asm-generic/gpio.h> 22 23 struct sunxi_mmc_plat { 24 struct mmc_config cfg; 25 struct mmc mmc; 26 }; 27 28 struct sunxi_mmc_priv { 29 unsigned mmc_no; 30 uint32_t *mclkreg; 31 unsigned fatal_err; 32 struct gpio_desc cd_gpio; /* Change Detect GPIO */ 33 int cd_inverted; /* Inverted Card Detect */ 34 struct sunxi_mmc *reg; 35 struct mmc_config cfg; 36 }; 37 38 #if !CONFIG_IS_ENABLED(DM_MMC) 39 /* support 4 mmc hosts */ 40 struct sunxi_mmc_priv mmc_host[4]; 41 42 static int sunxi_mmc_getcd_gpio(int sdc_no) 43 { 44 switch (sdc_no) { 45 case 0: return sunxi_name_to_gpio(CONFIG_MMC0_CD_PIN); 46 case 1: return sunxi_name_to_gpio(CONFIG_MMC1_CD_PIN); 47 case 2: return sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN); 48 case 3: return sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN); 49 } 50 return -EINVAL; 51 } 52 53 static int mmc_resource_init(int sdc_no) 54 { 55 struct sunxi_mmc_priv *priv = &mmc_host[sdc_no]; 56 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 57 int cd_pin, ret = 0; 58 59 debug("init mmc %d resource\n", sdc_no); 60 61 switch (sdc_no) { 62 case 0: 63 priv->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE; 64 priv->mclkreg = &ccm->sd0_clk_cfg; 65 break; 66 case 1: 67 priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE; 68 priv->mclkreg = &ccm->sd1_clk_cfg; 69 break; 70 case 2: 71 priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE; 72 priv->mclkreg = &ccm->sd2_clk_cfg; 73 break; 74 case 3: 75 priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE; 76 priv->mclkreg = &ccm->sd3_clk_cfg; 77 break; 78 default: 79 printf("Wrong mmc number %d\n", sdc_no); 80 return -1; 81 } 82 priv->mmc_no = sdc_no; 83 84 cd_pin = sunxi_mmc_getcd_gpio(sdc_no); 85 if (cd_pin >= 0) { 86 ret = gpio_request(cd_pin, "mmc_cd"); 87 if (!ret) { 88 sunxi_gpio_set_pull(cd_pin, SUNXI_GPIO_PULL_UP); 89 ret = gpio_direction_input(cd_pin); 90 } 91 } 92 93 return ret; 94 } 95 #endif 96 97 static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) 98 { 99 unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly; 100 bool new_mode = false; 101 u32 val = 0; 102 103 if (IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE) && (priv->mmc_no == 2)) 104 new_mode = true; 105 106 /* 107 * The MMC clock has an extra /2 post-divider when operating in the new 108 * mode. 109 */ 110 if (new_mode) 111 hz = hz * 2; 112 113 if (hz <= 24000000) { 114 pll = CCM_MMC_CTRL_OSCM24; 115 pll_hz = 24000000; 116 } else { 117 #ifdef CONFIG_MACH_SUN9I 118 pll = CCM_MMC_CTRL_PLL_PERIPH0; 119 pll_hz = clock_get_pll4_periph0(); 120 #else 121 pll = CCM_MMC_CTRL_PLL6; 122 pll_hz = clock_get_pll6(); 123 #endif 124 } 125 126 div = pll_hz / hz; 127 if (pll_hz % hz) 128 div++; 129 130 n = 0; 131 while (div > 16) { 132 n++; 133 div = (div + 1) / 2; 134 } 135 136 if (n > 3) { 137 printf("mmc %u error cannot set clock to %u\n", priv->mmc_no, 138 hz); 139 return -1; 140 } 141 142 /* determine delays */ 143 if (hz <= 400000) { 144 oclk_dly = 0; 145 sclk_dly = 0; 146 } else if (hz <= 25000000) { 147 oclk_dly = 0; 148 sclk_dly = 5; 149 #ifdef CONFIG_MACH_SUN9I 150 } else if (hz <= 50000000) { 151 oclk_dly = 5; 152 sclk_dly = 4; 153 } else { 154 /* hz > 50000000 */ 155 oclk_dly = 2; 156 sclk_dly = 4; 157 #else 158 } else if (hz <= 50000000) { 159 oclk_dly = 3; 160 sclk_dly = 4; 161 } else { 162 /* hz > 50000000 */ 163 oclk_dly = 1; 164 sclk_dly = 4; 165 #endif 166 } 167 168 if (new_mode) { 169 #ifdef CONFIG_MMC_SUNXI_HAS_NEW_MODE 170 val = CCM_MMC_CTRL_MODE_SEL_NEW; 171 setbits_le32(&priv->reg->ntsr, SUNXI_MMC_NTSR_MODE_SEL_NEW); 172 #endif 173 } else { 174 val = CCM_MMC_CTRL_OCLK_DLY(oclk_dly) | 175 CCM_MMC_CTRL_SCLK_DLY(sclk_dly); 176 } 177 178 writel(CCM_MMC_CTRL_ENABLE| pll | CCM_MMC_CTRL_N(n) | 179 CCM_MMC_CTRL_M(div) | val, priv->mclkreg); 180 181 debug("mmc %u set mod-clk req %u parent %u n %u m %u rate %u\n", 182 priv->mmc_no, hz, pll_hz, 1u << n, div, pll_hz / (1u << n) / div); 183 184 return 0; 185 } 186 187 static int mmc_update_clk(struct sunxi_mmc_priv *priv) 188 { 189 unsigned int cmd; 190 unsigned timeout_msecs = 2000; 191 192 cmd = SUNXI_MMC_CMD_START | 193 SUNXI_MMC_CMD_UPCLK_ONLY | 194 SUNXI_MMC_CMD_WAIT_PRE_OVER; 195 writel(cmd, &priv->reg->cmd); 196 while (readl(&priv->reg->cmd) & SUNXI_MMC_CMD_START) { 197 if (!timeout_msecs--) 198 return -1; 199 udelay(1000); 200 } 201 202 /* clock update sets various irq status bits, clear these */ 203 writel(readl(&priv->reg->rint), &priv->reg->rint); 204 205 return 0; 206 } 207 208 static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc) 209 { 210 unsigned rval = readl(&priv->reg->clkcr); 211 212 /* Disable Clock */ 213 rval &= ~SUNXI_MMC_CLK_ENABLE; 214 writel(rval, &priv->reg->clkcr); 215 if (mmc_update_clk(priv)) 216 return -1; 217 218 /* Set mod_clk to new rate */ 219 if (mmc_set_mod_clk(priv, mmc->clock)) 220 return -1; 221 222 /* Clear internal divider */ 223 rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK; 224 writel(rval, &priv->reg->clkcr); 225 226 /* Re-enable Clock */ 227 rval |= SUNXI_MMC_CLK_ENABLE; 228 writel(rval, &priv->reg->clkcr); 229 if (mmc_update_clk(priv)) 230 return -1; 231 232 return 0; 233 } 234 235 static int sunxi_mmc_set_ios_common(struct sunxi_mmc_priv *priv, 236 struct mmc *mmc) 237 { 238 debug("set ios: bus_width: %x, clock: %d\n", 239 mmc->bus_width, mmc->clock); 240 241 /* Change clock first */ 242 if (mmc->clock && mmc_config_clock(priv, mmc) != 0) { 243 priv->fatal_err = 1; 244 return -EINVAL; 245 } 246 247 /* Change bus width */ 248 if (mmc->bus_width == 8) 249 writel(0x2, &priv->reg->width); 250 else if (mmc->bus_width == 4) 251 writel(0x1, &priv->reg->width); 252 else 253 writel(0x0, &priv->reg->width); 254 255 return 0; 256 } 257 258 #if !CONFIG_IS_ENABLED(DM_MMC) 259 static int sunxi_mmc_core_init(struct mmc *mmc) 260 { 261 struct sunxi_mmc_priv *priv = mmc->priv; 262 263 /* Reset controller */ 264 writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl); 265 udelay(1000); 266 267 return 0; 268 } 269 #endif 270 271 static int mmc_trans_data_by_cpu(struct sunxi_mmc_priv *priv, struct mmc *mmc, 272 struct mmc_data *data) 273 { 274 const int reading = !!(data->flags & MMC_DATA_READ); 275 const uint32_t status_bit = reading ? SUNXI_MMC_STATUS_FIFO_EMPTY : 276 SUNXI_MMC_STATUS_FIFO_FULL; 277 unsigned i; 278 unsigned *buff = (unsigned int *)(reading ? data->dest : data->src); 279 unsigned byte_cnt = data->blocksize * data->blocks; 280 unsigned timeout_usecs = (byte_cnt >> 8) * 1000; 281 if (timeout_usecs < 2000000) 282 timeout_usecs = 2000000; 283 284 /* Always read / write data through the CPU */ 285 setbits_le32(&priv->reg->gctrl, SUNXI_MMC_GCTRL_ACCESS_BY_AHB); 286 287 for (i = 0; i < (byte_cnt >> 2); i++) { 288 while (readl(&priv->reg->status) & status_bit) { 289 if (!timeout_usecs--) 290 return -1; 291 udelay(1); 292 } 293 294 if (reading) 295 buff[i] = readl(&priv->reg->fifo); 296 else 297 writel(buff[i], &priv->reg->fifo); 298 } 299 300 return 0; 301 } 302 303 static int mmc_rint_wait(struct sunxi_mmc_priv *priv, struct mmc *mmc, 304 uint timeout_msecs, uint done_bit, const char *what) 305 { 306 unsigned int status; 307 308 do { 309 status = readl(&priv->reg->rint); 310 if (!timeout_msecs-- || 311 (status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT)) { 312 debug("%s timeout %x\n", what, 313 status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT); 314 return -ETIMEDOUT; 315 } 316 udelay(1000); 317 } while (!(status & done_bit)); 318 319 return 0; 320 } 321 322 static int sunxi_mmc_send_cmd_common(struct sunxi_mmc_priv *priv, 323 struct mmc *mmc, struct mmc_cmd *cmd, 324 struct mmc_data *data) 325 { 326 unsigned int cmdval = SUNXI_MMC_CMD_START; 327 unsigned int timeout_msecs; 328 int error = 0; 329 unsigned int status = 0; 330 unsigned int bytecnt = 0; 331 332 if (priv->fatal_err) 333 return -1; 334 if (cmd->resp_type & MMC_RSP_BUSY) 335 debug("mmc cmd %d check rsp busy\n", cmd->cmdidx); 336 if (cmd->cmdidx == 12) 337 return 0; 338 339 if (!cmd->cmdidx) 340 cmdval |= SUNXI_MMC_CMD_SEND_INIT_SEQ; 341 if (cmd->resp_type & MMC_RSP_PRESENT) 342 cmdval |= SUNXI_MMC_CMD_RESP_EXPIRE; 343 if (cmd->resp_type & MMC_RSP_136) 344 cmdval |= SUNXI_MMC_CMD_LONG_RESPONSE; 345 if (cmd->resp_type & MMC_RSP_CRC) 346 cmdval |= SUNXI_MMC_CMD_CHK_RESPONSE_CRC; 347 348 if (data) { 349 if ((u32)(long)data->dest & 0x3) { 350 error = -1; 351 goto out; 352 } 353 354 cmdval |= SUNXI_MMC_CMD_DATA_EXPIRE|SUNXI_MMC_CMD_WAIT_PRE_OVER; 355 if (data->flags & MMC_DATA_WRITE) 356 cmdval |= SUNXI_MMC_CMD_WRITE; 357 if (data->blocks > 1) 358 cmdval |= SUNXI_MMC_CMD_AUTO_STOP; 359 writel(data->blocksize, &priv->reg->blksz); 360 writel(data->blocks * data->blocksize, &priv->reg->bytecnt); 361 } 362 363 debug("mmc %d, cmd %d(0x%08x), arg 0x%08x\n", priv->mmc_no, 364 cmd->cmdidx, cmdval | cmd->cmdidx, cmd->cmdarg); 365 writel(cmd->cmdarg, &priv->reg->arg); 366 367 if (!data) 368 writel(cmdval | cmd->cmdidx, &priv->reg->cmd); 369 370 /* 371 * transfer data and check status 372 * STATREG[2] : FIFO empty 373 * STATREG[3] : FIFO full 374 */ 375 if (data) { 376 int ret = 0; 377 378 bytecnt = data->blocksize * data->blocks; 379 debug("trans data %d bytes\n", bytecnt); 380 writel(cmdval | cmd->cmdidx, &priv->reg->cmd); 381 ret = mmc_trans_data_by_cpu(priv, mmc, data); 382 if (ret) { 383 error = readl(&priv->reg->rint) & 384 SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT; 385 error = -ETIMEDOUT; 386 goto out; 387 } 388 } 389 390 error = mmc_rint_wait(priv, mmc, 1000, SUNXI_MMC_RINT_COMMAND_DONE, 391 "cmd"); 392 if (error) 393 goto out; 394 395 if (data) { 396 timeout_msecs = 120; 397 debug("cacl timeout %x msec\n", timeout_msecs); 398 error = mmc_rint_wait(priv, mmc, timeout_msecs, 399 data->blocks > 1 ? 400 SUNXI_MMC_RINT_AUTO_COMMAND_DONE : 401 SUNXI_MMC_RINT_DATA_OVER, 402 "data"); 403 if (error) 404 goto out; 405 } 406 407 if (cmd->resp_type & MMC_RSP_BUSY) { 408 timeout_msecs = 2000; 409 do { 410 status = readl(&priv->reg->status); 411 if (!timeout_msecs--) { 412 debug("busy timeout\n"); 413 error = -ETIMEDOUT; 414 goto out; 415 } 416 udelay(1000); 417 } while (status & SUNXI_MMC_STATUS_CARD_DATA_BUSY); 418 } 419 420 if (cmd->resp_type & MMC_RSP_136) { 421 cmd->response[0] = readl(&priv->reg->resp3); 422 cmd->response[1] = readl(&priv->reg->resp2); 423 cmd->response[2] = readl(&priv->reg->resp1); 424 cmd->response[3] = readl(&priv->reg->resp0); 425 debug("mmc resp 0x%08x 0x%08x 0x%08x 0x%08x\n", 426 cmd->response[3], cmd->response[2], 427 cmd->response[1], cmd->response[0]); 428 } else { 429 cmd->response[0] = readl(&priv->reg->resp0); 430 debug("mmc resp 0x%08x\n", cmd->response[0]); 431 } 432 out: 433 if (error < 0) { 434 writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl); 435 mmc_update_clk(priv); 436 } 437 writel(0xffffffff, &priv->reg->rint); 438 writel(readl(&priv->reg->gctrl) | SUNXI_MMC_GCTRL_FIFO_RESET, 439 &priv->reg->gctrl); 440 441 return error; 442 } 443 444 #if !CONFIG_IS_ENABLED(DM_MMC) 445 static int sunxi_mmc_set_ios_legacy(struct mmc *mmc) 446 { 447 struct sunxi_mmc_priv *priv = mmc->priv; 448 449 return sunxi_mmc_set_ios_common(priv, mmc); 450 } 451 452 static int sunxi_mmc_send_cmd_legacy(struct mmc *mmc, struct mmc_cmd *cmd, 453 struct mmc_data *data) 454 { 455 struct sunxi_mmc_priv *priv = mmc->priv; 456 457 return sunxi_mmc_send_cmd_common(priv, mmc, cmd, data); 458 } 459 460 static int sunxi_mmc_getcd_legacy(struct mmc *mmc) 461 { 462 struct sunxi_mmc_priv *priv = mmc->priv; 463 int cd_pin; 464 465 cd_pin = sunxi_mmc_getcd_gpio(priv->mmc_no); 466 if (cd_pin < 0) 467 return 1; 468 469 return !gpio_get_value(cd_pin); 470 } 471 472 static const struct mmc_ops sunxi_mmc_ops = { 473 .send_cmd = sunxi_mmc_send_cmd_legacy, 474 .set_ios = sunxi_mmc_set_ios_legacy, 475 .init = sunxi_mmc_core_init, 476 .getcd = sunxi_mmc_getcd_legacy, 477 }; 478 479 struct mmc *sunxi_mmc_init(int sdc_no) 480 { 481 struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 482 struct sunxi_mmc_priv *priv = &mmc_host[sdc_no]; 483 struct mmc_config *cfg = &priv->cfg; 484 int ret; 485 486 memset(priv, '\0', sizeof(struct sunxi_mmc_priv)); 487 488 cfg->name = "SUNXI SD/MMC"; 489 cfg->ops = &sunxi_mmc_ops; 490 491 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; 492 cfg->host_caps = MMC_MODE_4BIT; 493 #if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) 494 if (sdc_no == 2) 495 cfg->host_caps = MMC_MODE_8BIT; 496 #endif 497 cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; 498 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; 499 500 cfg->f_min = 400000; 501 cfg->f_max = 52000000; 502 503 if (mmc_resource_init(sdc_no) != 0) 504 return NULL; 505 506 /* config ahb clock */ 507 debug("init mmc %d clock and io\n", sdc_no); 508 setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no)); 509 510 #ifdef CONFIG_SUNXI_GEN_SUN6I 511 /* unassert reset */ 512 setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no)); 513 #endif 514 #if defined(CONFIG_MACH_SUN9I) 515 /* sun9i has a mmc-common module, also set the gate and reset there */ 516 writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET, 517 SUNXI_MMC_COMMON_BASE + 4 * sdc_no); 518 #endif 519 ret = mmc_set_mod_clk(priv, 24000000); 520 if (ret) 521 return NULL; 522 523 return mmc_create(cfg, priv); 524 } 525 #else 526 527 static int sunxi_mmc_set_ios(struct udevice *dev) 528 { 529 struct sunxi_mmc_plat *plat = dev_get_platdata(dev); 530 struct sunxi_mmc_priv *priv = dev_get_priv(dev); 531 532 return sunxi_mmc_set_ios_common(priv, &plat->mmc); 533 } 534 535 static int sunxi_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, 536 struct mmc_data *data) 537 { 538 struct sunxi_mmc_plat *plat = dev_get_platdata(dev); 539 struct sunxi_mmc_priv *priv = dev_get_priv(dev); 540 541 return sunxi_mmc_send_cmd_common(priv, &plat->mmc, cmd, data); 542 } 543 544 static int sunxi_mmc_getcd(struct udevice *dev) 545 { 546 struct sunxi_mmc_priv *priv = dev_get_priv(dev); 547 548 if (dm_gpio_is_valid(&priv->cd_gpio)) { 549 int cd_state = dm_gpio_get_value(&priv->cd_gpio); 550 551 return cd_state ^ priv->cd_inverted; 552 } 553 return 1; 554 } 555 556 static const struct dm_mmc_ops sunxi_mmc_ops = { 557 .send_cmd = sunxi_mmc_send_cmd, 558 .set_ios = sunxi_mmc_set_ios, 559 .get_cd = sunxi_mmc_getcd, 560 }; 561 562 static int sunxi_mmc_probe(struct udevice *dev) 563 { 564 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 565 struct sunxi_mmc_plat *plat = dev_get_platdata(dev); 566 struct sunxi_mmc_priv *priv = dev_get_priv(dev); 567 struct mmc_config *cfg = &plat->cfg; 568 struct ofnode_phandle_args args; 569 u32 *gate_reg; 570 int bus_width, ret; 571 572 cfg->name = dev->name; 573 bus_width = dev_read_u32_default(dev, "bus-width", 1); 574 575 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; 576 cfg->host_caps = 0; 577 if (bus_width == 8) 578 cfg->host_caps |= MMC_MODE_8BIT; 579 if (bus_width >= 4) 580 cfg->host_caps |= MMC_MODE_4BIT; 581 cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; 582 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; 583 584 cfg->f_min = 400000; 585 cfg->f_max = 52000000; 586 587 priv->reg = (void *)dev_read_addr(dev); 588 589 /* We don't have a sunxi clock driver so find the clock address here */ 590 ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0, 591 1, &args); 592 if (ret) 593 return ret; 594 priv->mclkreg = (u32 *)ofnode_get_addr(args.node); 595 596 ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0, 597 0, &args); 598 if (ret) 599 return ret; 600 gate_reg = (u32 *)ofnode_get_addr(args.node); 601 setbits_le32(gate_reg, 1 << args.args[0]); 602 priv->mmc_no = args.args[0] - 8; 603 604 ret = mmc_set_mod_clk(priv, 24000000); 605 if (ret) 606 return ret; 607 608 /* This GPIO is optional */ 609 if (!gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, 610 GPIOD_IS_IN)) { 611 int cd_pin = gpio_get_number(&priv->cd_gpio); 612 613 sunxi_gpio_set_pull(cd_pin, SUNXI_GPIO_PULL_UP); 614 } 615 616 /* Check if card detect is inverted */ 617 priv->cd_inverted = dev_read_bool(dev, "cd-inverted"); 618 619 upriv->mmc = &plat->mmc; 620 621 /* Reset controller */ 622 writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl); 623 udelay(1000); 624 625 return 0; 626 } 627 628 static int sunxi_mmc_bind(struct udevice *dev) 629 { 630 struct sunxi_mmc_plat *plat = dev_get_platdata(dev); 631 632 return mmc_bind(dev, &plat->mmc, &plat->cfg); 633 } 634 635 static const struct udevice_id sunxi_mmc_ids[] = { 636 { .compatible = "allwinner,sun5i-a13-mmc" }, 637 { } 638 }; 639 640 U_BOOT_DRIVER(sunxi_mmc_drv) = { 641 .name = "sunxi_mmc", 642 .id = UCLASS_MMC, 643 .of_match = sunxi_mmc_ids, 644 .bind = sunxi_mmc_bind, 645 .probe = sunxi_mmc_probe, 646 .ops = &sunxi_mmc_ops, 647 .platdata_auto_alloc_size = sizeof(struct sunxi_mmc_plat), 648 .priv_auto_alloc_size = sizeof(struct sunxi_mmc_priv), 649 }; 650 #endif 651