uboot/drivers/mmc/gen_atmel_mci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2010
   4 * Rob Emanuele <rob@emanuele.us>
   5 * Reinhard Meyer, EMK Elektronik <reinhard.meyer@emk-elektronik.de>
   6 *
   7 * Original Driver:
   8 * Copyright (C) 2004-2006 Atmel Corporation
   9 */
  10
  11#include <common.h>
  12#include <clk.h>
  13#include <dm.h>
  14#include <mmc.h>
  15#include <part.h>
  16#include <malloc.h>
  17#include <asm/io.h>
  18#include <linux/errno.h>
  19#include <asm/byteorder.h>
  20#include <asm/arch/clk.h>
  21#include <asm/arch/hardware.h>
  22#include "atmel_mci.h"
  23
  24#ifndef CONFIG_SYS_MMC_CLK_OD
  25# define CONFIG_SYS_MMC_CLK_OD  150000
  26#endif
  27
  28#define MMC_DEFAULT_BLKLEN      512
  29
  30#if defined(CONFIG_ATMEL_MCI_PORTB)
  31# define MCI_BUS 1
  32#else
  33# define MCI_BUS 0
  34#endif
  35
  36#ifdef CONFIG_DM_MMC
  37struct atmel_mci_plat {
  38        struct mmc              mmc;
  39        struct mmc_config       cfg;
  40        struct atmel_mci        *mci;
  41};
  42#endif
  43
  44struct atmel_mci_priv {
  45#ifndef CONFIG_DM_MMC
  46        struct mmc_config       cfg;
  47        struct atmel_mci        *mci;
  48#endif
  49        unsigned int            initialized:1;
  50        unsigned int            curr_clk;
  51#ifdef CONFIG_DM_MMC
  52        ulong           bus_clk_rate;
  53#endif
  54};
  55
  56/* Read Atmel MCI IP version */
  57static unsigned int atmel_mci_get_version(struct atmel_mci *mci)
  58{
  59        return readl(&mci->version) & 0x00000fff;
  60}
  61
  62/*
  63 * Print command and status:
  64 *
  65 * - always when DEBUG is defined
  66 * - on command errors
  67 */
  68static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
  69{
  70        debug("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n",
  71              cmdr, cmdr & 0x3F, arg, status, msg);
  72}
  73
  74static inline void mci_set_blklen(atmel_mci_t *mci, int blklen)
  75{
  76        unsigned int version = atmel_mci_get_version(mci);
  77
  78        blklen &= 0xfffc;
  79
  80        /* MCI IP version >= 0x200 has blkr */
  81        if (version >= 0x200)
  82                writel(MMCI_BFINS(BLKLEN, blklen, readl(&mci->blkr)),
  83                       &mci->blkr);
  84        else
  85                writel(MMCI_BFINS(BLKLEN, blklen, readl(&mci->mr)), &mci->mr);
  86}
  87
  88/* Setup for MCI Clock and Block Size */
  89#ifdef CONFIG_DM_MMC
  90static void mci_set_mode(struct udevice *dev, u32 hz, u32 blklen)
  91{
  92        struct atmel_mci_plat *plat = dev_get_platdata(dev);
  93        struct atmel_mci_priv *priv = dev_get_priv(dev);
  94        struct mmc *mmc = &plat->mmc;
  95        u32 bus_hz = priv->bus_clk_rate;
  96        atmel_mci_t *mci = plat->mci;
  97#else
  98static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
  99{
 100        struct atmel_mci_priv *priv = mmc->priv;
 101        u32 bus_hz = get_mci_clk_rate();
 102        atmel_mci_t *mci = priv->mci;
 103#endif
 104
 105        u32 clkdiv = 255;
 106        unsigned int version = atmel_mci_get_version(mci);
 107        u32 clkodd = 0;
 108        u32 mr;
 109
 110        debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n",
 111                bus_hz, hz, blklen);
 112        if (hz > 0) {
 113                if (version >= 0x500) {
 114                        clkdiv = DIV_ROUND_UP(bus_hz, hz) - 2;
 115                        if (clkdiv > 511)
 116                                clkdiv = 511;
 117
 118                        clkodd = clkdiv & 1;
 119                        clkdiv >>= 1;
 120
 121                        debug("mci: setting clock %u Hz, block size %u\n",
 122                              bus_hz / (clkdiv * 2 + clkodd + 2), blklen);
 123                } else {
 124                        /* find clkdiv yielding a rate <= than requested */
 125                        for (clkdiv = 0; clkdiv < 255; clkdiv++) {
 126                                if ((bus_hz / (clkdiv + 1) / 2) <= hz)
 127                                        break;
 128                        }
 129                        debug("mci: setting clock %u Hz, block size %u\n",
 130                              (bus_hz / (clkdiv + 1)) / 2, blklen);
 131
 132                }
 133        }
 134        if (version >= 0x500)
 135                priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
 136        else
 137                priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
 138
 139        mr = MMCI_BF(CLKDIV, clkdiv);
 140
 141        /* MCI IP version >= 0x200 has R/WPROOF */
 142        if (version >= 0x200)
 143                mr |= MMCI_BIT(RDPROOF) | MMCI_BIT(WRPROOF);
 144
 145        /*
 146         * MCI IP version >= 0x500 use bit 16 as clkodd.
 147         * MCI IP version < 0x500 use upper 16 bits for blklen.
 148         */
 149        if (version >= 0x500)
 150                mr |= MMCI_BF(CLKODD, clkodd);
 151
 152        writel(mr, &mci->mr);
 153
 154        mci_set_blklen(mci, blklen);
 155
 156        if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
 157                writel(MMCI_BIT(HSMODE), &mci->cfg);
 158
 159        priv->initialized = 1;
 160}
 161
 162/* Return the CMDR with flags for a given command and data packet */
 163static u32 mci_encode_cmd(
 164        struct mmc_cmd *cmd, struct mmc_data *data, u32* error_flags)
 165{
 166        u32 cmdr = 0;
 167
 168        /* Default Flags for Errors */
 169        *error_flags |= (MMCI_BIT(DTOE) | MMCI_BIT(RDIRE) | MMCI_BIT(RENDE) |
 170                MMCI_BIT(RINDE) | MMCI_BIT(RTOE));
 171
 172        /* Default Flags for the Command */
 173        cmdr |= MMCI_BIT(MAXLAT);
 174
 175        if (data) {
 176                cmdr |= MMCI_BF(TRCMD, 1);
 177                if (data->blocks > 1)
 178                        cmdr |= MMCI_BF(TRTYP, 1);
 179                if (data->flags & MMC_DATA_READ)
 180                        cmdr |= MMCI_BIT(TRDIR);
 181        }
 182
 183        if (cmd->resp_type & MMC_RSP_CRC)
 184                *error_flags |= MMCI_BIT(RCRCE);
 185        if (cmd->resp_type & MMC_RSP_136)
 186                cmdr |= MMCI_BF(RSPTYP, 2);
 187        else if (cmd->resp_type & MMC_RSP_BUSY)
 188                cmdr |= MMCI_BF(RSPTYP, 3);
 189        else if (cmd->resp_type & MMC_RSP_PRESENT)
 190                cmdr |= MMCI_BF(RSPTYP, 1);
 191
 192        return cmdr | MMCI_BF(CMDNB, cmd->cmdidx);
 193}
 194
 195/* Entered into function pointer in mci_send_cmd */
 196static u32 mci_data_read(atmel_mci_t *mci, u32* data, u32 error_flags)
 197{
 198        u32 status;
 199
 200        do {
 201                status = readl(&mci->sr);
 202                if (status & (error_flags | MMCI_BIT(OVRE)))
 203                        goto io_fail;
 204        } while (!(status & MMCI_BIT(RXRDY)));
 205
 206        if (status & MMCI_BIT(RXRDY)) {
 207                *data = readl(&mci->rdr);
 208                status = 0;
 209        }
 210io_fail:
 211        return status;
 212}
 213
 214/* Entered into function pointer in mci_send_cmd */
 215static u32 mci_data_write(atmel_mci_t *mci, u32* data, u32 error_flags)
 216{
 217        u32 status;
 218
 219        do {
 220                status = readl(&mci->sr);
 221                if (status & (error_flags | MMCI_BIT(UNRE)))
 222                        goto io_fail;
 223        } while (!(status & MMCI_BIT(TXRDY)));
 224
 225        if (status & MMCI_BIT(TXRDY)) {
 226                writel(*data, &mci->tdr);
 227                status = 0;
 228        }
 229io_fail:
 230        return status;
 231}
 232
 233/*
 234 * Entered into mmc structure during driver init
 235 *
 236 * Sends a command out on the bus and deals with the block data.
 237 * Takes the mmc pointer, a command pointer, and an optional data pointer.
 238 */
 239#ifdef CONFIG_DM_MMC
 240static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 241                              struct mmc_data *data)
 242{
 243        struct atmel_mci_plat *plat = dev_get_platdata(dev);
 244        struct atmel_mci_priv *priv = dev_get_priv(dev);
 245        atmel_mci_t *mci = plat->mci;
 246#else
 247static int
 248mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 249{
 250        struct atmel_mci_priv *priv = mmc->priv;
 251        atmel_mci_t *mci = priv->mci;
 252#endif
 253        u32 cmdr;
 254        u32 error_flags = 0;
 255        u32 status;
 256
 257        if (!priv->initialized) {
 258                puts ("MCI not initialized!\n");
 259                return -ECOMM;
 260        }
 261
 262        /* Figure out the transfer arguments */
 263        cmdr = mci_encode_cmd(cmd, data, &error_flags);
 264
 265        mci_set_blklen(mci, data->blocksize);
 266
 267        /* For multi blocks read/write, set the block register */
 268        if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK)
 269                        || (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK))
 270                writel(data->blocks | MMCI_BF(BLKLEN, data->blocksize),
 271                       &mci->blkr);
 272
 273        /* Send the command */
 274        writel(cmd->cmdarg, &mci->argr);
 275        writel(cmdr, &mci->cmdr);
 276
 277#ifdef DEBUG
 278        dump_cmd(cmdr, cmd->cmdarg, 0, "DEBUG");
 279#endif
 280
 281        /* Wait for the command to complete */
 282        while (!((status = readl(&mci->sr)) & MMCI_BIT(CMDRDY)));
 283
 284        if ((status & error_flags) & MMCI_BIT(RTOE)) {
 285                dump_cmd(cmdr, cmd->cmdarg, status, "Command Time Out");
 286                return -ETIMEDOUT;
 287        } else if (status & error_flags) {
 288                dump_cmd(cmdr, cmd->cmdarg, status, "Command Failed");
 289                return -ECOMM;
 290        }
 291
 292        /* Copy the response to the response buffer */
 293        if (cmd->resp_type & MMC_RSP_136) {
 294                cmd->response[0] = readl(&mci->rspr);
 295                cmd->response[1] = readl(&mci->rspr1);
 296                cmd->response[2] = readl(&mci->rspr2);
 297                cmd->response[3] = readl(&mci->rspr3);
 298        } else
 299                cmd->response[0] = readl(&mci->rspr);
 300
 301        /* transfer all of the blocks */
 302        if (data) {
 303                u32 word_count, block_count;
 304                u32* ioptr;
 305                u32 i;
 306                u32 (*mci_data_op)
 307                        (atmel_mci_t *mci, u32* data, u32 error_flags);
 308
 309                if (data->flags & MMC_DATA_READ) {
 310                        mci_data_op = mci_data_read;
 311                        ioptr = (u32*)data->dest;
 312                } else {
 313                        mci_data_op = mci_data_write;
 314                        ioptr = (u32*)data->src;
 315                }
 316
 317                status = 0;
 318                for (block_count = 0;
 319                                block_count < data->blocks && !status;
 320                                block_count++) {
 321                        word_count = 0;
 322                        do {
 323                                status = mci_data_op(mci, ioptr, error_flags);
 324                                word_count++;
 325                                ioptr++;
 326                        } while (!status && word_count < (data->blocksize/4));
 327#ifdef DEBUG
 328                        if (data->flags & MMC_DATA_READ)
 329                        {
 330                                u32 cnt = word_count * 4;
 331                                printf("Read Data:\n");
 332                                print_buffer(0, data->dest + cnt * block_count,
 333                                             1, cnt, 0);
 334                        }
 335#endif
 336                        if (status) {
 337                                dump_cmd(cmdr, cmd->cmdarg, status,
 338                                        "Data Transfer Failed");
 339                                return -ECOMM;
 340                        }
 341                }
 342
 343                /* Wait for Transfer End */
 344                i = 0;
 345                do {
 346                        status = readl(&mci->sr);
 347
 348                        if (status & error_flags) {
 349                                dump_cmd(cmdr, cmd->cmdarg, status,
 350                                        "DTIP Wait Failed");
 351                                return -ECOMM;
 352                        }
 353                        i++;
 354                } while ((status & MMCI_BIT(DTIP)) && i < 10000);
 355                if (status & MMCI_BIT(DTIP)) {
 356                        dump_cmd(cmdr, cmd->cmdarg, status,
 357                                "XFER DTIP never unset, ignoring");
 358                }
 359        }
 360
 361        /*
 362         * After the switch command, wait for 8 clocks before the next
 363         * command
 364         */
 365        if (cmd->cmdidx == MMC_CMD_SWITCH)
 366                udelay(8*1000000 / priv->curr_clk); /* 8 clk in us */
 367
 368        return 0;
 369}
 370
 371#ifdef CONFIG_DM_MMC
 372static int atmel_mci_set_ios(struct udevice *dev)
 373{
 374        struct atmel_mci_plat *plat = dev_get_platdata(dev);
 375        struct mmc *mmc = mmc_get_mmc_dev(dev);
 376        atmel_mci_t *mci = plat->mci;
 377#else
 378/* Entered into mmc structure during driver init */
 379static int mci_set_ios(struct mmc *mmc)
 380{
 381        struct atmel_mci_priv *priv = mmc->priv;
 382        atmel_mci_t *mci = priv->mci;
 383#endif
 384        int bus_width = mmc->bus_width;
 385        unsigned int version = atmel_mci_get_version(mci);
 386        int busw;
 387
 388        /* Set the clock speed */
 389#ifdef CONFIG_DM_MMC
 390        mci_set_mode(dev, mmc->clock, MMC_DEFAULT_BLKLEN);
 391#else
 392        mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
 393#endif
 394
 395        /*
 396         * set the bus width and select slot for this interface
 397         * there is no capability for multiple slots on the same interface yet
 398         */
 399        if ((version & 0xf00) >= 0x300) {
 400                switch (bus_width) {
 401                case 8:
 402                        busw = 3;
 403                        break;
 404                case 4:
 405                        busw = 2;
 406                        break;
 407                default:
 408                        busw = 0;
 409                        break;
 410                }
 411
 412                writel(busw << 6 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
 413        } else {
 414                busw = (bus_width == 4) ? 1 : 0;
 415
 416                writel(busw << 7 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
 417        }
 418
 419        return 0;
 420}
 421
 422#ifdef CONFIG_DM_MMC
 423static int atmel_mci_hw_init(struct udevice *dev)
 424{
 425        struct atmel_mci_plat *plat = dev_get_platdata(dev);
 426        atmel_mci_t *mci = plat->mci;
 427#else
 428/* Entered into mmc structure during driver init */
 429static int mci_init(struct mmc *mmc)
 430{
 431        struct atmel_mci_priv *priv = mmc->priv;
 432        atmel_mci_t *mci = priv->mci;
 433#endif
 434
 435        /* Initialize controller */
 436        writel(MMCI_BIT(SWRST), &mci->cr);      /* soft reset */
 437        writel(MMCI_BIT(PWSDIS), &mci->cr);     /* disable power save */
 438        writel(MMCI_BIT(MCIEN), &mci->cr);      /* enable mci */
 439        writel(MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);   /* select port */
 440
 441        /* This delay can be optimized, but stick with max value */
 442        writel(0x7f, &mci->dtor);
 443        /* Disable Interrupts */
 444        writel(~0UL, &mci->idr);
 445
 446        /* Set default clocks and blocklen */
 447#ifdef CONFIG_DM_MMC
 448        mci_set_mode(dev, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
 449#else
 450        mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
 451#endif
 452
 453        return 0;
 454}
 455
 456#ifndef CONFIG_DM_MMC
 457static const struct mmc_ops atmel_mci_ops = {
 458        .send_cmd       = mci_send_cmd,
 459        .set_ios        = mci_set_ios,
 460        .init           = mci_init,
 461};
 462
 463/*
 464 * This is the only exported function
 465 *
 466 * Call it with the MCI register base address
 467 */
 468int atmel_mci_init(void *regs)
 469{
 470        struct mmc *mmc;
 471        struct mmc_config *cfg;
 472        struct atmel_mci_priv *priv;
 473        unsigned int version;
 474
 475        priv = calloc(1, sizeof(*priv));
 476        if (!priv)
 477                return -ENOMEM;
 478
 479        cfg = &priv->cfg;
 480
 481        cfg->name = "mci";
 482        cfg->ops = &atmel_mci_ops;
 483
 484        priv->mci = (struct atmel_mci *)regs;
 485        priv->initialized = 0;
 486
 487        /* need to be able to pass these in on a board by board basis */
 488        cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 489        version = atmel_mci_get_version(priv->mci);
 490        if ((version & 0xf00) >= 0x300) {
 491                cfg->host_caps = MMC_MODE_8BIT;
 492                cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz;
 493        }
 494
 495        cfg->host_caps |= MMC_MODE_4BIT;
 496
 497        /*
 498         * min and max frequencies determined by
 499         * max and min of clock divider
 500         */
 501        cfg->f_min = get_mci_clk_rate() / (2*256);
 502        cfg->f_max = get_mci_clk_rate() / (2*1);
 503
 504        cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 505
 506        mmc = mmc_create(cfg, priv);
 507
 508        if (mmc == NULL) {
 509                free(priv);
 510                return -ENODEV;
 511        }
 512        /* NOTE: possibly leaking the priv structure */
 513
 514        return 0;
 515}
 516#endif
 517
 518#ifdef CONFIG_DM_MMC
 519static const struct dm_mmc_ops atmel_mci_mmc_ops = {
 520        .send_cmd = atmel_mci_send_cmd,
 521        .set_ios = atmel_mci_set_ios,
 522};
 523
 524static void atmel_mci_setup_cfg(struct udevice *dev)
 525{
 526        struct atmel_mci_plat *plat = dev_get_platdata(dev);
 527        struct atmel_mci_priv *priv = dev_get_priv(dev);
 528        struct mmc_config *cfg;
 529        u32 version;
 530
 531        cfg = &plat->cfg;
 532        cfg->name = "Atmel mci";
 533        cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 534
 535        /*
 536         * If the version is above 3.0, the capabilities of the 8-bit
 537         * bus width and high speed are supported.
 538         */
 539        version = atmel_mci_get_version(plat->mci);
 540        if ((version & 0xf00) >= 0x300) {
 541                cfg->host_caps = MMC_MODE_8BIT |
 542                                 MMC_MODE_HS | MMC_MODE_HS_52MHz;
 543        }
 544
 545        cfg->host_caps |= MMC_MODE_4BIT;
 546        cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 547        cfg->f_min = priv->bus_clk_rate / (2 * 256);
 548        cfg->f_max = priv->bus_clk_rate / 2;
 549}
 550
 551static int atmel_mci_enable_clk(struct udevice *dev)
 552{
 553        struct atmel_mci_priv *priv = dev_get_priv(dev);
 554        struct clk clk;
 555        ulong clk_rate;
 556        int ret = 0;
 557
 558        ret = clk_get_by_index(dev, 0, &clk);
 559        if (ret) {
 560                ret = -EINVAL;
 561                goto failed;
 562        }
 563
 564        ret = clk_enable(&clk);
 565        if (ret)
 566                goto failed;
 567
 568        clk_rate = clk_get_rate(&clk);
 569        if (!clk_rate) {
 570                ret = -EINVAL;
 571                goto failed;
 572        }
 573
 574        priv->bus_clk_rate = clk_rate;
 575
 576failed:
 577        clk_free(&clk);
 578
 579        return ret;
 580}
 581
 582static int atmel_mci_probe(struct udevice *dev)
 583{
 584        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 585        struct atmel_mci_plat *plat = dev_get_platdata(dev);
 586        struct mmc *mmc;
 587        int ret;
 588
 589        ret = atmel_mci_enable_clk(dev);
 590        if (ret)
 591                return ret;
 592
 593        plat->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev);
 594
 595        atmel_mci_setup_cfg(dev);
 596
 597        mmc = &plat->mmc;
 598        mmc->cfg = &plat->cfg;
 599        mmc->dev = dev;
 600        upriv->mmc = mmc;
 601
 602        atmel_mci_hw_init(dev);
 603
 604        return 0;
 605}
 606
 607static int atmel_mci_bind(struct udevice *dev)
 608{
 609        struct atmel_mci_plat *plat = dev_get_platdata(dev);
 610
 611        return mmc_bind(dev, &plat->mmc, &plat->cfg);
 612}
 613
 614static const struct udevice_id atmel_mci_ids[] = {
 615        { .compatible = "atmel,hsmci" },
 616        { }
 617};
 618
 619U_BOOT_DRIVER(atmel_mci) = {
 620        .name = "atmel-mci",
 621        .id = UCLASS_MMC,
 622        .of_match = atmel_mci_ids,
 623        .bind = atmel_mci_bind,
 624        .probe = atmel_mci_probe,
 625        .platdata_auto_alloc_size = sizeof(struct atmel_mci_plat),
 626        .priv_auto_alloc_size = sizeof(struct atmel_mci_priv),
 627        .ops = &atmel_mci_mmc_ops,
 628};
 629#endif
 630