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