uboot/drivers/mmc/fsl_esdhc.c
<<
>>
Prefs
   1/*
   2 * Copyright 2007,2010 Freescale Semiconductor, Inc
   3 * Andy Fleming
   4 *
   5 * Based vaguely on the pxa mmc code:
   6 * (C) Copyright 2003
   7 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
   8 *
   9 * See file CREDITS for list of people who contributed to this
  10 * project.
  11 *
  12 * This program is free software; you can redistribute it and/or
  13 * modify it under the terms of the GNU General Public License as
  14 * published by the Free Software Foundation; either version 2 of
  15 * the License, or (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25 * MA 02111-1307 USA
  26 */
  27
  28#include <config.h>
  29#include <common.h>
  30#include <command.h>
  31#include <hwconfig.h>
  32#include <mmc.h>
  33#include <part.h>
  34#include <malloc.h>
  35#include <mmc.h>
  36#include <fsl_esdhc.h>
  37#include <fdt_support.h>
  38#include <asm/io.h>
  39
  40DECLARE_GLOBAL_DATA_PTR;
  41
  42struct fsl_esdhc {
  43        uint    dsaddr;
  44        uint    blkattr;
  45        uint    cmdarg;
  46        uint    xfertyp;
  47        uint    cmdrsp0;
  48        uint    cmdrsp1;
  49        uint    cmdrsp2;
  50        uint    cmdrsp3;
  51        uint    datport;
  52        uint    prsstat;
  53        uint    proctl;
  54        uint    sysctl;
  55        uint    irqstat;
  56        uint    irqstaten;
  57        uint    irqsigen;
  58        uint    autoc12err;
  59        uint    hostcapblt;
  60        uint    wml;
  61        char    reserved1[8];
  62        uint    fevt;
  63        char    reserved2[168];
  64        uint    hostver;
  65        char    reserved3[780];
  66        uint    scr;
  67};
  68
  69/* Return the XFERTYP flags for a given command and data packet */
  70uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
  71{
  72        uint xfertyp = 0;
  73
  74        if (data) {
  75                xfertyp |= XFERTYP_DPSEL;
  76#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
  77                xfertyp |= XFERTYP_DMAEN;
  78#endif
  79                if (data->blocks > 1) {
  80                        xfertyp |= XFERTYP_MSBSEL;
  81                        xfertyp |= XFERTYP_BCEN;
  82                }
  83
  84                if (data->flags & MMC_DATA_READ)
  85                        xfertyp |= XFERTYP_DTDSEL;
  86        }
  87
  88        if (cmd->resp_type & MMC_RSP_CRC)
  89                xfertyp |= XFERTYP_CCCEN;
  90        if (cmd->resp_type & MMC_RSP_OPCODE)
  91                xfertyp |= XFERTYP_CICEN;
  92        if (cmd->resp_type & MMC_RSP_136)
  93                xfertyp |= XFERTYP_RSPTYP_136;
  94        else if (cmd->resp_type & MMC_RSP_BUSY)
  95                xfertyp |= XFERTYP_RSPTYP_48_BUSY;
  96        else if (cmd->resp_type & MMC_RSP_PRESENT)
  97                xfertyp |= XFERTYP_RSPTYP_48;
  98
  99        return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
 100}
 101
 102#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
 103/*
 104 * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
 105 */
 106static void
 107esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
 108{
 109        struct fsl_esdhc *regs = mmc->priv;
 110        uint blocks;
 111        char *buffer;
 112        uint databuf;
 113        uint size;
 114        uint irqstat;
 115        uint timeout;
 116
 117        if (data->flags & MMC_DATA_READ) {
 118                blocks = data->blocks;
 119                buffer = data->dest;
 120                while (blocks) {
 121                        timeout = PIO_TIMEOUT;
 122                        size = data->blocksize;
 123                        irqstat = esdhc_read32(&regs->irqstat);
 124                        while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BREN)
 125                                && --timeout);
 126                        if (timeout <= 0) {
 127                                printf("\nData Read Failed in PIO Mode.");
 128                                return;
 129                        }
 130                        while (size && (!(irqstat & IRQSTAT_TC))) {
 131                                udelay(100); /* Wait before last byte transfer complete */
 132                                irqstat = esdhc_read32(&regs->irqstat);
 133                                databuf = in_le32(&regs->datport);
 134                                *((uint *)buffer) = databuf;
 135                                buffer += 4;
 136                                size -= 4;
 137                        }
 138                        blocks--;
 139                }
 140        } else {
 141                blocks = data->blocks;
 142                buffer = (char *)data->src;
 143                while (blocks) {
 144                        timeout = PIO_TIMEOUT;
 145                        size = data->blocksize;
 146                        irqstat = esdhc_read32(&regs->irqstat);
 147                        while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BWEN)
 148                                && --timeout);
 149                        if (timeout <= 0) {
 150                                printf("\nData Write Failed in PIO Mode.");
 151                                return;
 152                        }
 153                        while (size && (!(irqstat & IRQSTAT_TC))) {
 154                                udelay(100); /* Wait before last byte transfer complete */
 155                                databuf = *((uint *)buffer);
 156                                buffer += 4;
 157                                size -= 4;
 158                                irqstat = esdhc_read32(&regs->irqstat);
 159                                out_le32(&regs->datport, databuf);
 160                        }
 161                        blocks--;
 162                }
 163        }
 164}
 165#endif
 166
 167static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
 168{
 169        int timeout;
 170        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 171        struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 172#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
 173        uint wml_value;
 174
 175        wml_value = data->blocksize/4;
 176
 177        if (data->flags & MMC_DATA_READ) {
 178                if (wml_value > 0x10)
 179                        wml_value = 0x10;
 180
 181                esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
 182                esdhc_write32(&regs->dsaddr, (u32)data->dest);
 183        } else {
 184                if (wml_value > 0x80)
 185                        wml_value = 0x80;
 186                if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
 187                        printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
 188                        return TIMEOUT;
 189                }
 190
 191                esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
 192                                        wml_value << 16);
 193                esdhc_write32(&regs->dsaddr, (u32)data->src);
 194        }
 195#else   /* CONFIG_SYS_FSL_ESDHC_USE_PIO */
 196        if (!(data->flags & MMC_DATA_READ)) {
 197                if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
 198                        printf("\nThe SD card is locked. "
 199                                "Can not write to a locked card.\n\n");
 200                        return TIMEOUT;
 201                }
 202                esdhc_write32(&regs->dsaddr, (u32)data->src);
 203        } else
 204                esdhc_write32(&regs->dsaddr, (u32)data->dest);
 205#endif  /* CONFIG_SYS_FSL_ESDHC_USE_PIO */
 206
 207        esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
 208
 209        /* Calculate the timeout period for data transactions */
 210        timeout = fls(mmc->tran_speed/10) - 1;
 211        timeout -= 13;
 212
 213        if (timeout > 14)
 214                timeout = 14;
 215
 216        if (timeout < 0)
 217                timeout = 0;
 218
 219        esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
 220
 221        return 0;
 222}
 223
 224
 225/*
 226 * Sends a command out on the bus.  Takes the mmc pointer,
 227 * a command pointer, and an optional data pointer.
 228 */
 229static int
 230esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 231{
 232        uint    xfertyp;
 233        uint    irqstat;
 234        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 235        volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 236
 237        esdhc_write32(&regs->irqstat, -1);
 238
 239        sync();
 240
 241        /* Wait for the bus to be idle */
 242        while ((esdhc_read32(&regs->prsstat) & PRSSTAT_CICHB) ||
 243                        (esdhc_read32(&regs->prsstat) & PRSSTAT_CIDHB))
 244                ;
 245
 246        while (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA)
 247                ;
 248
 249        /* Wait at least 8 SD clock cycles before the next command */
 250        /*
 251         * Note: This is way more than 8 cycles, but 1ms seems to
 252         * resolve timing issues with some cards
 253         */
 254        udelay(1000);
 255
 256        /* Set up for a data transfer if we have one */
 257        if (data) {
 258                int err;
 259
 260                err = esdhc_setup_data(mmc, data);
 261                if(err)
 262                        return err;
 263        }
 264
 265        /* Figure out the transfer arguments */
 266        xfertyp = esdhc_xfertyp(cmd, data);
 267
 268        /* Send the command */
 269        esdhc_write32(&regs->cmdarg, cmd->cmdarg);
 270        esdhc_write32(&regs->xfertyp, xfertyp);
 271
 272        /* Wait for the command to complete */
 273        while (!(esdhc_read32(&regs->irqstat) & IRQSTAT_CC))
 274                ;
 275
 276        irqstat = esdhc_read32(&regs->irqstat);
 277        esdhc_write32(&regs->irqstat, irqstat);
 278
 279        if (irqstat & CMD_ERR)
 280                return COMM_ERR;
 281
 282        if (irqstat & IRQSTAT_CTOE)
 283                return TIMEOUT;
 284
 285        /* Copy the response to the response buffer */
 286        if (cmd->resp_type & MMC_RSP_136) {
 287                u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;
 288
 289                cmdrsp3 = esdhc_read32(&regs->cmdrsp3);
 290                cmdrsp2 = esdhc_read32(&regs->cmdrsp2);
 291                cmdrsp1 = esdhc_read32(&regs->cmdrsp1);
 292                cmdrsp0 = esdhc_read32(&regs->cmdrsp0);
 293                cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24);
 294                cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24);
 295                cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24);
 296                cmd->response[3] = (cmdrsp0 << 8);
 297        } else
 298                cmd->response[0] = esdhc_read32(&regs->cmdrsp0);
 299
 300        /* Wait until all of the blocks are transferred */
 301        if (data) {
 302#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
 303                esdhc_pio_read_write(mmc, data);
 304#else
 305                do {
 306                        irqstat = esdhc_read32(&regs->irqstat);
 307
 308                        if (irqstat & DATA_ERR)
 309                                return COMM_ERR;
 310
 311                        if (irqstat & IRQSTAT_DTOE)
 312                                return TIMEOUT;
 313                } while (!(irqstat & IRQSTAT_TC) &&
 314                                (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA));
 315#endif
 316        }
 317
 318        esdhc_write32(&regs->irqstat, -1);
 319
 320        return 0;
 321}
 322
 323void set_sysctl(struct mmc *mmc, uint clock)
 324{
 325        int sdhc_clk = gd->sdhc_clk;
 326        int div, pre_div;
 327        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 328        volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 329        uint clk;
 330
 331        if (clock < mmc->f_min)
 332                clock = mmc->f_min;
 333
 334        if (sdhc_clk / 16 > clock) {
 335                for (pre_div = 2; pre_div < 256; pre_div *= 2)
 336                        if ((sdhc_clk / pre_div) <= (clock * 16))
 337                                break;
 338        } else
 339                pre_div = 2;
 340
 341        for (div = 1; div <= 16; div++)
 342                if ((sdhc_clk / (div * pre_div)) <= clock)
 343                        break;
 344
 345        pre_div >>= 1;
 346        div -= 1;
 347
 348        clk = (pre_div << 8) | (div << 4);
 349
 350        esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
 351
 352        esdhc_clrsetbits32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
 353
 354        udelay(10000);
 355
 356        clk = SYSCTL_PEREN | SYSCTL_CKEN;
 357
 358        esdhc_setbits32(&regs->sysctl, clk);
 359}
 360
 361static void esdhc_set_ios(struct mmc *mmc)
 362{
 363        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 364        struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 365
 366        /* Set the clock speed */
 367        set_sysctl(mmc, mmc->clock);
 368
 369        /* Set the bus width */
 370        esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
 371
 372        if (mmc->bus_width == 4)
 373                esdhc_setbits32(&regs->proctl, PROCTL_DTW_4);
 374        else if (mmc->bus_width == 8)
 375                esdhc_setbits32(&regs->proctl, PROCTL_DTW_8);
 376
 377}
 378
 379static int esdhc_init(struct mmc *mmc)
 380{
 381        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 382        struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
 383        int timeout = 1000;
 384        int ret = 0;
 385        u8 card_absent;
 386
 387        /* Enable cache snooping */
 388        if (cfg && !cfg->no_snoop)
 389                esdhc_write32(&regs->scr, 0x00000040);
 390
 391        /* Reset the entire host controller */
 392        esdhc_write32(&regs->sysctl, SYSCTL_RSTA);
 393
 394        /* Wait until the controller is available */
 395        while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
 396                udelay(1000);
 397
 398        esdhc_write32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
 399
 400        /* Set the initial clock speed */
 401        set_sysctl(mmc, 400000);
 402
 403        /* Disable the BRR and BWR bits in IRQSTAT */
 404        esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
 405
 406        /* Put the PROCTL reg back to the default */
 407        esdhc_write32(&regs->proctl, PROCTL_INIT);
 408
 409        /* Set timout to the maximum value */
 410        esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
 411
 412        /* Check if there is a callback for detecting the card */
 413        if (board_mmc_getcd(&card_absent, mmc)) {
 414                timeout = 1000;
 415                while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) &&
 416                                --timeout)
 417                        udelay(1000);
 418
 419                if (timeout <= 0)
 420                        ret = NO_CARD_ERR;
 421        } else {
 422                if (card_absent)
 423                        ret = NO_CARD_ERR;
 424        }
 425
 426        return ret;
 427}
 428
 429static void esdhc_reset(struct fsl_esdhc *regs)
 430{
 431        unsigned long timeout = 100; /* wait max 100 ms */
 432
 433        /* reset the controller */
 434        esdhc_write32(&regs->sysctl, SYSCTL_RSTA);
 435
 436        /* hardware clears the bit when it is done */
 437        while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
 438                udelay(1000);
 439        if (!timeout)
 440                printf("MMC/SD: Reset never completed.\n");
 441}
 442
 443int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 444{
 445        struct fsl_esdhc *regs;
 446        struct mmc *mmc;
 447        u32 caps;
 448
 449        if (!cfg)
 450                return -1;
 451
 452        mmc = malloc(sizeof(struct mmc));
 453
 454        sprintf(mmc->name, "FSL_ESDHC");
 455        regs = (struct fsl_esdhc *)cfg->esdhc_base;
 456
 457        /* First reset the eSDHC controller */
 458        esdhc_reset(regs);
 459
 460        mmc->priv = cfg;
 461        mmc->send_cmd = esdhc_send_cmd;
 462        mmc->set_ios = esdhc_set_ios;
 463        mmc->init = esdhc_init;
 464
 465        caps = regs->hostcapblt;
 466
 467        if (caps & ESDHC_HOSTCAPBLT_VS18)
 468                mmc->voltages |= MMC_VDD_165_195;
 469        if (caps & ESDHC_HOSTCAPBLT_VS30)
 470                mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
 471        if (caps & ESDHC_HOSTCAPBLT_VS33)
 472                mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
 473
 474        mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
 475
 476        if (caps & ESDHC_HOSTCAPBLT_HSS)
 477                mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 478
 479        mmc->f_min = 400000;
 480        mmc->f_max = MIN(gd->sdhc_clk, 50000000);
 481
 482        mmc_register(mmc);
 483
 484        return 0;
 485}
 486
 487int fsl_esdhc_mmc_init(bd_t *bis)
 488{
 489        struct fsl_esdhc_cfg *cfg;
 490
 491        cfg = malloc(sizeof(struct fsl_esdhc_cfg));
 492        memset(cfg, 0, sizeof(struct fsl_esdhc_cfg));
 493        cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR;
 494        return fsl_esdhc_initialize(bis, cfg);
 495}
 496
 497#ifdef CONFIG_OF_LIBFDT
 498void fdt_fixup_esdhc(void *blob, bd_t *bd)
 499{
 500        const char *compat = "fsl,esdhc";
 501        const char *status = "okay";
 502
 503        if (!hwconfig("esdhc")) {
 504                status = "disabled";
 505                goto out;
 506        }
 507
 508        do_fixup_by_compat_u32(blob, compat, "clock-frequency",
 509                               gd->sdhc_clk, 1);
 510out:
 511        do_fixup_by_compat(blob, compat, "status", status,
 512                           strlen(status) + 1, 1);
 513}
 514#endif
 515