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