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