uboot/drivers/mmc/arm_pl180_mmci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * ARM PrimeCell MultiMedia Card Interface - PL180
   4 *
   5 * Copyright (C) ST-Ericsson SA 2010
   6 *
   7 * Author: Ulf Hansson <ulf.hansson@stericsson.com>
   8 * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com>
   9 * Ported to drivers/mmc/ by: Matt Waddel <matt.waddel@linaro.org>
  10 */
  11
  12/* #define DEBUG */
  13
  14#include "common.h"
  15#include <clk.h>
  16#include <errno.h>
  17#include <malloc.h>
  18#include <mmc.h>
  19
  20#include <asm/io.h>
  21#include <asm-generic/gpio.h>
  22
  23#include "arm_pl180_mmci.h"
  24
  25#ifdef CONFIG_DM_MMC
  26#include <dm.h>
  27#define MMC_CLOCK_MAX   48000000
  28#define MMC_CLOCK_MIN   400000
  29
  30struct arm_pl180_mmc_plat {
  31        struct mmc_config cfg;
  32        struct mmc mmc;
  33};
  34#endif
  35
  36static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
  37{
  38        u32 hoststatus, statusmask;
  39        struct pl180_mmc_host *host = dev->priv;
  40
  41        statusmask = SDI_STA_CTIMEOUT | SDI_STA_CCRCFAIL;
  42        if ((cmd->resp_type & MMC_RSP_PRESENT))
  43                statusmask |= SDI_STA_CMDREND;
  44        else
  45                statusmask |= SDI_STA_CMDSENT;
  46
  47        do
  48                hoststatus = readl(&host->base->status) & statusmask;
  49        while (!hoststatus);
  50
  51        writel(statusmask, &host->base->status_clear);
  52        if (hoststatus & SDI_STA_CTIMEOUT) {
  53                debug("CMD%d time out\n", cmd->cmdidx);
  54                return -ETIMEDOUT;
  55        } else if ((hoststatus & SDI_STA_CCRCFAIL) &&
  56                   (cmd->resp_type & MMC_RSP_CRC)) {
  57                printf("CMD%d CRC error\n", cmd->cmdidx);
  58                return -EILSEQ;
  59        }
  60
  61        if (cmd->resp_type & MMC_RSP_PRESENT) {
  62                cmd->response[0] = readl(&host->base->response0);
  63                cmd->response[1] = readl(&host->base->response1);
  64                cmd->response[2] = readl(&host->base->response2);
  65                cmd->response[3] = readl(&host->base->response3);
  66                debug("CMD%d response[0]:0x%08X, response[1]:0x%08X, "
  67                        "response[2]:0x%08X, response[3]:0x%08X\n",
  68                        cmd->cmdidx, cmd->response[0], cmd->response[1],
  69                        cmd->response[2], cmd->response[3]);
  70        }
  71
  72        return 0;
  73}
  74
  75/* send command to the mmc card and wait for results */
  76static int do_command(struct mmc *dev, struct mmc_cmd *cmd)
  77{
  78        int result;
  79        u32 sdi_cmd = 0;
  80        struct pl180_mmc_host *host = dev->priv;
  81
  82        sdi_cmd = ((cmd->cmdidx & SDI_CMD_CMDINDEX_MASK) | SDI_CMD_CPSMEN);
  83
  84        if (cmd->resp_type) {
  85                sdi_cmd |= SDI_CMD_WAITRESP;
  86                if (cmd->resp_type & MMC_RSP_136)
  87                        sdi_cmd |= SDI_CMD_LONGRESP;
  88        }
  89
  90        writel((u32)cmd->cmdarg, &host->base->argument);
  91        udelay(COMMAND_REG_DELAY);
  92        writel(sdi_cmd, &host->base->command);
  93        result = wait_for_command_end(dev, cmd);
  94
  95        /* After CMD2 set RCA to a none zero value. */
  96        if ((result == 0) && (cmd->cmdidx == MMC_CMD_ALL_SEND_CID))
  97                dev->rca = 10;
  98
  99        /* After CMD3 open drain is switched off and push pull is used. */
 100        if ((result == 0) && (cmd->cmdidx == MMC_CMD_SET_RELATIVE_ADDR)) {
 101                u32 sdi_pwr = readl(&host->base->power) & ~SDI_PWR_OPD;
 102                writel(sdi_pwr, &host->base->power);
 103        }
 104
 105        return result;
 106}
 107
 108static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize)
 109{
 110        u32 *tempbuff = dest;
 111        u64 xfercount = blkcount * blksize;
 112        struct pl180_mmc_host *host = dev->priv;
 113        u32 status, status_err;
 114
 115        debug("read_bytes: blkcount=%u blksize=%u\n", blkcount, blksize);
 116
 117        status = readl(&host->base->status);
 118        status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT |
 119                               SDI_STA_RXOVERR);
 120        while ((!status_err) && (xfercount >= sizeof(u32))) {
 121                if (status & SDI_STA_RXDAVL) {
 122                        *(tempbuff) = readl(&host->base->fifo);
 123                        tempbuff++;
 124                        xfercount -= sizeof(u32);
 125                }
 126                status = readl(&host->base->status);
 127                status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT |
 128                                       SDI_STA_RXOVERR);
 129        }
 130
 131        status_err = status &
 132                (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND |
 133                 SDI_STA_RXOVERR);
 134        while (!status_err) {
 135                status = readl(&host->base->status);
 136                status_err = status &
 137                        (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND |
 138                         SDI_STA_RXOVERR);
 139        }
 140
 141        if (status & SDI_STA_DTIMEOUT) {
 142                printf("Read data timed out, xfercount: %llu, status: 0x%08X\n",
 143                        xfercount, status);
 144                return -ETIMEDOUT;
 145        } else if (status & SDI_STA_DCRCFAIL) {
 146                printf("Read data bytes CRC error: 0x%x\n", status);
 147                return -EILSEQ;
 148        } else if (status & SDI_STA_RXOVERR) {
 149                printf("Read data RX overflow error\n");
 150                return -EIO;
 151        }
 152
 153        writel(SDI_ICR_MASK, &host->base->status_clear);
 154
 155        if (xfercount) {
 156                printf("Read data error, xfercount: %llu\n", xfercount);
 157                return -ENOBUFS;
 158        }
 159
 160        return 0;
 161}
 162
 163static int write_bytes(struct mmc *dev, u32 *src, u32 blkcount, u32 blksize)
 164{
 165        u32 *tempbuff = src;
 166        int i;
 167        u64 xfercount = blkcount * blksize;
 168        struct pl180_mmc_host *host = dev->priv;
 169        u32 status, status_err;
 170
 171        debug("write_bytes: blkcount=%u blksize=%u\n", blkcount, blksize);
 172
 173        status = readl(&host->base->status);
 174        status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT);
 175        while (!status_err && xfercount) {
 176                if (status & SDI_STA_TXFIFOBW) {
 177                        if (xfercount >= SDI_FIFO_BURST_SIZE * sizeof(u32)) {
 178                                for (i = 0; i < SDI_FIFO_BURST_SIZE; i++)
 179                                        writel(*(tempbuff + i),
 180                                                &host->base->fifo);
 181                                tempbuff += SDI_FIFO_BURST_SIZE;
 182                                xfercount -= SDI_FIFO_BURST_SIZE * sizeof(u32);
 183                        } else {
 184                                while (xfercount >= sizeof(u32)) {
 185                                        writel(*(tempbuff), &host->base->fifo);
 186                                        tempbuff++;
 187                                        xfercount -= sizeof(u32);
 188                                }
 189                        }
 190                }
 191                status = readl(&host->base->status);
 192                status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT);
 193        }
 194
 195        status_err = status &
 196                (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND);
 197        while (!status_err) {
 198                status = readl(&host->base->status);
 199                status_err = status &
 200                        (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_DBCKEND);
 201        }
 202
 203        if (status & SDI_STA_DTIMEOUT) {
 204                printf("Write data timed out, xfercount:%llu,status:0x%08X\n",
 205                       xfercount, status);
 206                return -ETIMEDOUT;
 207        } else if (status & SDI_STA_DCRCFAIL) {
 208                printf("Write data CRC error\n");
 209                return -EILSEQ;
 210        }
 211
 212        writel(SDI_ICR_MASK, &host->base->status_clear);
 213
 214        if (xfercount) {
 215                printf("Write data error, xfercount:%llu", xfercount);
 216                return -ENOBUFS;
 217        }
 218
 219        return 0;
 220}
 221
 222static int do_data_transfer(struct mmc *dev,
 223                            struct mmc_cmd *cmd,
 224                            struct mmc_data *data)
 225{
 226        int error = -ETIMEDOUT;
 227        struct pl180_mmc_host *host = dev->priv;
 228        u32 blksz = 0;
 229        u32 data_ctrl = 0;
 230        u32 data_len = (u32) (data->blocks * data->blocksize);
 231
 232        if (!host->version2) {
 233                blksz = (ffs(data->blocksize) - 1);
 234                data_ctrl |= ((blksz << 4) & SDI_DCTRL_DBLKSIZE_MASK);
 235        } else {
 236                blksz = data->blocksize;
 237                data_ctrl |= (blksz << SDI_DCTRL_DBLOCKSIZE_V2_SHIFT);
 238        }
 239        data_ctrl |= SDI_DCTRL_DTEN | SDI_DCTRL_BUSYMODE;
 240
 241        writel(SDI_DTIMER_DEFAULT, &host->base->datatimer);
 242        writel(data_len, &host->base->datalength);
 243        udelay(DATA_REG_DELAY);
 244
 245        if (data->flags & MMC_DATA_READ) {
 246                data_ctrl |= SDI_DCTRL_DTDIR_IN;
 247                writel(data_ctrl, &host->base->datactrl);
 248
 249                error = do_command(dev, cmd);
 250                if (error)
 251                        return error;
 252
 253                error = read_bytes(dev, (u32 *)data->dest, (u32)data->blocks,
 254                                   (u32)data->blocksize);
 255        } else if (data->flags & MMC_DATA_WRITE) {
 256                error = do_command(dev, cmd);
 257                if (error)
 258                        return error;
 259
 260                writel(data_ctrl, &host->base->datactrl);
 261                error = write_bytes(dev, (u32 *)data->src, (u32)data->blocks,
 262                                                        (u32)data->blocksize);
 263        }
 264
 265        return error;
 266}
 267
 268static int host_request(struct mmc *dev,
 269                        struct mmc_cmd *cmd,
 270                        struct mmc_data *data)
 271{
 272        int result;
 273
 274        if (data)
 275                result = do_data_transfer(dev, cmd, data);
 276        else
 277                result = do_command(dev, cmd);
 278
 279        return result;
 280}
 281
 282static int  host_set_ios(struct mmc *dev)
 283{
 284        struct pl180_mmc_host *host = dev->priv;
 285        u32 sdi_clkcr;
 286
 287        sdi_clkcr = readl(&host->base->clock);
 288
 289        /* Ramp up the clock rate */
 290        if (dev->clock) {
 291                u32 clkdiv = 0;
 292                u32 tmp_clock;
 293
 294                if (dev->clock >= dev->cfg->f_max) {
 295                        clkdiv = 0;
 296                        dev->clock = dev->cfg->f_max;
 297                } else {
 298                        clkdiv = (host->clock_in / dev->clock) - 2;
 299                }
 300
 301                tmp_clock = host->clock_in / (clkdiv + 2);
 302                while (tmp_clock > dev->clock) {
 303                        clkdiv++;
 304                        tmp_clock = host->clock_in / (clkdiv + 2);
 305                }
 306
 307                if (clkdiv > SDI_CLKCR_CLKDIV_MASK)
 308                        clkdiv = SDI_CLKCR_CLKDIV_MASK;
 309
 310                tmp_clock = host->clock_in / (clkdiv + 2);
 311                dev->clock = tmp_clock;
 312                sdi_clkcr &= ~(SDI_CLKCR_CLKDIV_MASK);
 313                sdi_clkcr |= clkdiv;
 314        }
 315
 316        /* Set the bus width */
 317        if (dev->bus_width) {
 318                u32 buswidth = 0;
 319
 320                switch (dev->bus_width) {
 321                case 1:
 322                        buswidth |= SDI_CLKCR_WIDBUS_1;
 323                        break;
 324                case 4:
 325                        buswidth |= SDI_CLKCR_WIDBUS_4;
 326                        break;
 327                case 8:
 328                        buswidth |= SDI_CLKCR_WIDBUS_8;
 329                        break;
 330                default:
 331                        printf("Invalid bus width: %d\n", dev->bus_width);
 332                        break;
 333                }
 334                sdi_clkcr &= ~(SDI_CLKCR_WIDBUS_MASK);
 335                sdi_clkcr |= buswidth;
 336        }
 337
 338        writel(sdi_clkcr, &host->base->clock);
 339        udelay(CLK_CHANGE_DELAY);
 340
 341        return 0;
 342}
 343
 344#ifndef CONFIG_DM_MMC
 345/* MMC uses open drain drivers in the enumeration phase */
 346static int mmc_host_reset(struct mmc *dev)
 347{
 348        struct pl180_mmc_host *host = dev->priv;
 349
 350        writel(host->pwr_init, &host->base->power);
 351
 352        return 0;
 353}
 354
 355static const struct mmc_ops arm_pl180_mmci_ops = {
 356        .send_cmd = host_request,
 357        .set_ios = host_set_ios,
 358        .init = mmc_host_reset,
 359};
 360
 361/*
 362 * mmc_host_init - initialize the mmc controller.
 363 * Set initial clock and power for mmc slot.
 364 * Initialize mmc struct and register with mmc framework.
 365 */
 366
 367int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
 368{
 369        u32 sdi_u32;
 370
 371        writel(host->pwr_init, &host->base->power);
 372        writel(host->clkdiv_init, &host->base->clock);
 373        udelay(CLK_CHANGE_DELAY);
 374
 375        /* Disable mmc interrupts */
 376        sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
 377        writel(sdi_u32, &host->base->mask0);
 378
 379        host->cfg.name = host->name;
 380        host->cfg.ops = &arm_pl180_mmci_ops;
 381
 382        /* TODO remove the duplicates */
 383        host->cfg.host_caps = host->caps;
 384        host->cfg.voltages = host->voltages;
 385        host->cfg.f_min = host->clock_min;
 386        host->cfg.f_max = host->clock_max;
 387        if (host->b_max != 0)
 388                host->cfg.b_max = host->b_max;
 389        else
 390                host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 391
 392        *mmc = mmc_create(&host->cfg, host);
 393        if (!*mmc)
 394                return -1;
 395        debug("registered mmc interface number is:%d\n",
 396              (*mmc)->block_dev.devnum);
 397
 398        return 0;
 399}
 400#endif
 401
 402#ifdef CONFIG_DM_MMC
 403static void arm_pl180_mmc_init(struct pl180_mmc_host *host)
 404{
 405        u32 sdi_u32;
 406
 407        writel(host->pwr_init, &host->base->power);
 408        writel(host->clkdiv_init, &host->base->clock);
 409        udelay(CLK_CHANGE_DELAY);
 410
 411        /* Disable mmc interrupts */
 412        sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
 413        writel(sdi_u32, &host->base->mask0);
 414}
 415
 416static int arm_pl180_mmc_probe(struct udevice *dev)
 417{
 418        struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
 419        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 420        struct mmc *mmc = &pdata->mmc;
 421        struct pl180_mmc_host *host = dev->priv;
 422        struct mmc_config *cfg = &pdata->cfg;
 423        struct clk clk;
 424        u32 bus_width;
 425        u32 periphid;
 426        int ret;
 427
 428        ret = clk_get_by_index(dev, 0, &clk);
 429        if (ret < 0)
 430                return ret;
 431
 432        ret = clk_enable(&clk);
 433        if (ret) {
 434                clk_free(&clk);
 435                dev_err(dev, "failed to enable clock\n");
 436                return ret;
 437        }
 438
 439        host->pwr_init = INIT_PWR;
 440        host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN |
 441                            SDI_CLKCR_HWFC_EN;
 442        host->clock_in = clk_get_rate(&clk);
 443
 444        periphid = dev_read_u32_default(dev, "arm,primecell-periphid", 0);
 445        switch (periphid) {
 446        case STM32_MMCI_ID: /* stm32 variant */
 447                host->version2 = false;
 448                break;
 449        default:
 450                host->version2 = true;
 451        }
 452
 453        cfg->name = dev->name;
 454        cfg->voltages = VOLTAGE_WINDOW_SD;
 455        cfg->host_caps = 0;
 456        cfg->f_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
 457        cfg->f_max = dev_read_u32_default(dev, "max-frequency", MMC_CLOCK_MAX);
 458        cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 459
 460        gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN);
 461
 462        bus_width = dev_read_u32_default(dev, "bus-width", 1);
 463        switch (bus_width) {
 464        case 8:
 465                cfg->host_caps |= MMC_MODE_8BIT;
 466                /* Hosts capable of 8-bit transfers can also do 4 bits */
 467        case 4:
 468                cfg->host_caps |= MMC_MODE_4BIT;
 469                break;
 470        case 1:
 471                break;
 472        default:
 473                dev_err(dev, "Invalid bus-width value %u\n", bus_width);
 474        }
 475
 476        arm_pl180_mmc_init(host);
 477        mmc->priv = host;
 478        mmc->dev = dev;
 479        upriv->mmc = mmc;
 480
 481        return 0;
 482}
 483
 484int arm_pl180_mmc_bind(struct udevice *dev)
 485{
 486        struct arm_pl180_mmc_plat *plat = dev_get_platdata(dev);
 487
 488        return mmc_bind(dev, &plat->mmc, &plat->cfg);
 489}
 490
 491static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd,
 492                           struct mmc_data *data)
 493{
 494        struct mmc *mmc = mmc_get_mmc_dev(dev);
 495
 496        return host_request(mmc, cmd, data);
 497}
 498
 499static int dm_host_set_ios(struct udevice *dev)
 500{
 501        struct mmc *mmc = mmc_get_mmc_dev(dev);
 502
 503        return host_set_ios(mmc);
 504}
 505
 506static int dm_mmc_getcd(struct udevice *dev)
 507{
 508        struct pl180_mmc_host *host = dev->priv;
 509        int value = 1;
 510
 511        if (dm_gpio_is_valid(&host->cd_gpio))
 512                value = dm_gpio_get_value(&host->cd_gpio);
 513
 514        return value;
 515}
 516
 517static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = {
 518        .send_cmd = dm_host_request,
 519        .set_ios = dm_host_set_ios,
 520        .get_cd = dm_mmc_getcd,
 521};
 522
 523static int arm_pl180_mmc_ofdata_to_platdata(struct udevice *dev)
 524{
 525        struct pl180_mmc_host *host = dev->priv;
 526        fdt_addr_t addr;
 527
 528        addr = dev_read_addr(dev);
 529        if (addr == FDT_ADDR_T_NONE)
 530                return -EINVAL;
 531
 532        host->base = (void *)addr;
 533
 534        return 0;
 535}
 536
 537static const struct udevice_id arm_pl180_mmc_match[] = {
 538        { .compatible = "arm,pl180" },
 539        { .compatible = "arm,primecell" },
 540        { /* sentinel */ }
 541};
 542
 543U_BOOT_DRIVER(arm_pl180_mmc) = {
 544        .name = "arm_pl180_mmc",
 545        .id = UCLASS_MMC,
 546        .of_match = arm_pl180_mmc_match,
 547        .ops = &arm_pl180_dm_mmc_ops,
 548        .probe = arm_pl180_mmc_probe,
 549        .ofdata_to_platdata = arm_pl180_mmc_ofdata_to_platdata,
 550        .bind = arm_pl180_mmc_bind,
 551        .priv_auto_alloc_size = sizeof(struct pl180_mmc_host),
 552        .platdata_auto_alloc_size = sizeof(struct arm_pl180_mmc_plat),
 553};
 554#endif
 555