uboot/drivers/mmc/fsl_esdhc.c
<<
>>
Prefs
   1/*
   2 * Copyright 2007, 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
  40
  41DECLARE_GLOBAL_DATA_PTR;
  42
  43struct fsl_esdhc {
  44        uint    dsaddr;
  45        uint    blkattr;
  46        uint    cmdarg;
  47        uint    xfertyp;
  48        uint    cmdrsp0;
  49        uint    cmdrsp1;
  50        uint    cmdrsp2;
  51        uint    cmdrsp3;
  52        uint    datport;
  53        uint    prsstat;
  54        uint    proctl;
  55        uint    sysctl;
  56        uint    irqstat;
  57        uint    irqstaten;
  58        uint    irqsigen;
  59        uint    autoc12err;
  60        uint    hostcapblt;
  61        uint    wml;
  62        char    reserved1[8];
  63        uint    fevt;
  64        char    reserved2[168];
  65        uint    hostver;
  66        char    reserved3[780];
  67        uint    scr;
  68};
  69
  70/* Return the XFERTYP flags for a given command and data packet */
  71uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
  72{
  73        uint xfertyp = 0;
  74
  75        if (data) {
  76                xfertyp |= XFERTYP_DPSEL | XFERTYP_DMAEN;
  77
  78                if (data->blocks > 1) {
  79                        xfertyp |= XFERTYP_MSBSEL;
  80                        xfertyp |= XFERTYP_BCEN;
  81                }
  82
  83                if (data->flags & MMC_DATA_READ)
  84                        xfertyp |= XFERTYP_DTDSEL;
  85        }
  86
  87        if (cmd->resp_type & MMC_RSP_CRC)
  88                xfertyp |= XFERTYP_CCCEN;
  89        if (cmd->resp_type & MMC_RSP_OPCODE)
  90                xfertyp |= XFERTYP_CICEN;
  91        if (cmd->resp_type & MMC_RSP_136)
  92                xfertyp |= XFERTYP_RSPTYP_136;
  93        else if (cmd->resp_type & MMC_RSP_BUSY)
  94                xfertyp |= XFERTYP_RSPTYP_48_BUSY;
  95        else if (cmd->resp_type & MMC_RSP_PRESENT)
  96                xfertyp |= XFERTYP_RSPTYP_48;
  97
  98        return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
  99}
 100
 101static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
 102{
 103        uint wml_value;
 104        int timeout;
 105        struct fsl_esdhc *regs = mmc->priv;
 106
 107        wml_value = data->blocksize/4;
 108
 109        if (data->flags & MMC_DATA_READ) {
 110                if (wml_value > 0x10)
 111                        wml_value = 0x10;
 112
 113                wml_value = 0x100000 | wml_value;
 114
 115                out_be32(&regs->dsaddr, (u32)data->dest);
 116        } else {
 117                if (wml_value > 0x80)
 118                        wml_value = 0x80;
 119                if ((in_be32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
 120                        printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
 121                        return TIMEOUT;
 122                }
 123                wml_value = wml_value << 16 | 0x10;
 124                out_be32(&regs->dsaddr, (u32)data->src);
 125        }
 126
 127        out_be32(&regs->wml, wml_value);
 128
 129        out_be32(&regs->blkattr, data->blocks << 16 | data->blocksize);
 130
 131        /* Calculate the timeout period for data transactions */
 132        timeout = __ilog2(mmc->tran_speed/10);
 133        timeout -= 13;
 134
 135        if (timeout > 14)
 136                timeout = 14;
 137
 138        if (timeout < 0)
 139                timeout = 0;
 140
 141        clrsetbits_be32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
 142
 143        return 0;
 144}
 145
 146
 147/*
 148 * Sends a command out on the bus.  Takes the mmc pointer,
 149 * a command pointer, and an optional data pointer.
 150 */
 151static int
 152esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 153{
 154        uint    xfertyp;
 155        uint    irqstat;
 156        volatile struct fsl_esdhc *regs = mmc->priv;
 157
 158        out_be32(&regs->irqstat, -1);
 159
 160        sync();
 161
 162        /* Wait for the bus to be idle */
 163        while ((in_be32(&regs->prsstat) & PRSSTAT_CICHB) ||
 164                        (in_be32(&regs->prsstat) & PRSSTAT_CIDHB));
 165
 166        while (in_be32(&regs->prsstat) & PRSSTAT_DLA);
 167
 168        /* Wait at least 8 SD clock cycles before the next command */
 169        /*
 170         * Note: This is way more than 8 cycles, but 1ms seems to
 171         * resolve timing issues with some cards
 172         */
 173        udelay(1000);
 174
 175        /* Set up for a data transfer if we have one */
 176        if (data) {
 177                int err;
 178
 179                err = esdhc_setup_data(mmc, data);
 180                if(err)
 181                        return err;
 182        }
 183
 184        /* Figure out the transfer arguments */
 185        xfertyp = esdhc_xfertyp(cmd, data);
 186
 187        /* Send the command */
 188        out_be32(&regs->cmdarg, cmd->cmdarg);
 189        out_be32(&regs->xfertyp, xfertyp);
 190
 191        /* Wait for the command to complete */
 192        while (!(in_be32(&regs->irqstat) & IRQSTAT_CC));
 193
 194        irqstat = in_be32(&regs->irqstat);
 195        out_be32(&regs->irqstat, irqstat);
 196
 197        if (irqstat & CMD_ERR)
 198                return COMM_ERR;
 199
 200        if (irqstat & IRQSTAT_CTOE)
 201                return TIMEOUT;
 202
 203        /* Copy the response to the response buffer */
 204        if (cmd->resp_type & MMC_RSP_136) {
 205                u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;
 206
 207                cmdrsp3 = in_be32(&regs->cmdrsp3);
 208                cmdrsp2 = in_be32(&regs->cmdrsp2);
 209                cmdrsp1 = in_be32(&regs->cmdrsp1);
 210                cmdrsp0 = in_be32(&regs->cmdrsp0);
 211                cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24);
 212                cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24);
 213                cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24);
 214                cmd->response[3] = (cmdrsp0 << 8);
 215        } else
 216                cmd->response[0] = in_be32(&regs->cmdrsp0);
 217
 218        /* Wait until all of the blocks are transferred */
 219        if (data) {
 220                do {
 221                        irqstat = in_be32(&regs->irqstat);
 222
 223                        if (irqstat & DATA_ERR)
 224                                return COMM_ERR;
 225
 226                        if (irqstat & IRQSTAT_DTOE)
 227                                return TIMEOUT;
 228                } while (!(irqstat & IRQSTAT_TC) &&
 229                                (in_be32(&regs->prsstat) & PRSSTAT_DLA));
 230        }
 231
 232        out_be32(&regs->irqstat, -1);
 233
 234        return 0;
 235}
 236
 237void set_sysctl(struct mmc *mmc, uint clock)
 238{
 239        int sdhc_clk = gd->sdhc_clk;
 240        int div, pre_div;
 241        volatile struct fsl_esdhc *regs = mmc->priv;
 242        uint clk;
 243
 244        if (sdhc_clk / 16 > clock) {
 245                for (pre_div = 2; pre_div < 256; pre_div *= 2)
 246                        if ((sdhc_clk / pre_div) <= (clock * 16))
 247                                break;
 248        } else
 249                pre_div = 2;
 250
 251        for (div = 1; div <= 16; div++)
 252                if ((sdhc_clk / (div * pre_div)) <= clock)
 253                        break;
 254
 255        pre_div >>= 1;
 256        div -= 1;
 257
 258        clk = (pre_div << 8) | (div << 4);
 259
 260        clrsetbits_be32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
 261
 262        udelay(10000);
 263
 264        setbits_be32(&regs->sysctl, SYSCTL_PEREN);
 265}
 266
 267static void esdhc_set_ios(struct mmc *mmc)
 268{
 269        struct fsl_esdhc *regs = mmc->priv;
 270
 271        /* Set the clock speed */
 272        set_sysctl(mmc, mmc->clock);
 273
 274        /* Set the bus width */
 275        clrbits_be32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
 276
 277        if (mmc->bus_width == 4)
 278                setbits_be32(&regs->proctl, PROCTL_DTW_4);
 279        else if (mmc->bus_width == 8)
 280                setbits_be32(&regs->proctl, PROCTL_DTW_8);
 281}
 282
 283static int esdhc_init(struct mmc *mmc)
 284{
 285        struct fsl_esdhc *regs = mmc->priv;
 286        int timeout = 1000;
 287
 288        /* Enable cache snooping */
 289        out_be32(&regs->scr, 0x00000040);
 290
 291        out_be32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
 292
 293        /* Set the initial clock speed */
 294        set_sysctl(mmc, 400000);
 295
 296        /* Disable the BRR and BWR bits in IRQSTAT */
 297        clrbits_be32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
 298
 299        /* Put the PROCTL reg back to the default */
 300        out_be32(&regs->proctl, PROCTL_INIT);
 301
 302        while (!(in_be32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
 303                udelay(1000);
 304
 305        if (timeout <= 0)
 306                return NO_CARD_ERR;
 307
 308        return 0;
 309}
 310
 311static int esdhc_initialize(bd_t *bis)
 312{
 313        struct fsl_esdhc *regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR;
 314        struct mmc *mmc;
 315        u32 caps;
 316
 317        mmc = malloc(sizeof(struct mmc));
 318
 319        sprintf(mmc->name, "FSL_ESDHC");
 320        mmc->priv = regs;
 321        mmc->send_cmd = esdhc_send_cmd;
 322        mmc->set_ios = esdhc_set_ios;
 323        mmc->init = esdhc_init;
 324
 325        caps = regs->hostcapblt;
 326
 327        if (caps & ESDHC_HOSTCAPBLT_VS18)
 328                mmc->voltages |= MMC_VDD_165_195;
 329        if (caps & ESDHC_HOSTCAPBLT_VS30)
 330                mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
 331        if (caps & ESDHC_HOSTCAPBLT_VS33)
 332                mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
 333
 334        mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
 335
 336        if (caps & ESDHC_HOSTCAPBLT_HSS)
 337                mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 338
 339        mmc->f_min = 400000;
 340        mmc->f_max = MIN(gd->sdhc_clk, 50000000);
 341
 342        mmc_register(mmc);
 343
 344        return 0;
 345}
 346
 347int fsl_esdhc_mmc_init(bd_t *bis)
 348{
 349        return esdhc_initialize(bis);
 350}
 351
 352void fdt_fixup_esdhc(void *blob, bd_t *bd)
 353{
 354        const char *compat = "fsl,esdhc";
 355        const char *status = "okay";
 356
 357        if (!hwconfig("esdhc")) {
 358                status = "disabled";
 359                goto out;
 360        }
 361
 362        do_fixup_by_compat_u32(blob, compat, "clock-frequency",
 363                               gd->sdhc_clk, 1);
 364out:
 365        do_fixup_by_compat(blob, compat, "status", status,
 366                           strlen(status) + 1, 1);
 367}
 368