uboot/drivers/mmc/s5p_mmc.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2009 SAMSUNG Electronics
   3 * Minkyu Kang <mk7.kang@samsung.com>
   4 * Jaehoon Chung <jh80.chung@samsung.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 */
  20
  21#include <common.h>
  22#include <mmc.h>
  23#include <asm/io.h>
  24#include <asm/arch/mmc.h>
  25#include <asm/arch/clk.h>
  26
  27/* support 4 mmc hosts */
  28struct mmc mmc_dev[4];
  29struct mmc_host mmc_host[4];
  30
  31static inline struct s5p_mmc *s5p_get_base_mmc(int dev_index)
  32{
  33        unsigned long offset = dev_index * sizeof(struct s5p_mmc);
  34        return (struct s5p_mmc *)(samsung_get_base_mmc() + offset);
  35}
  36
  37static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data)
  38{
  39        unsigned char ctrl;
  40
  41        debug("data->dest: %08x\n", (u32)data->dest);
  42        writel((u32)data->dest, &host->reg->sysad);
  43        /*
  44         * DMASEL[4:3]
  45         * 00 = Selects SDMA
  46         * 01 = Reserved
  47         * 10 = Selects 32-bit Address ADMA2
  48         * 11 = Selects 64-bit Address ADMA2
  49         */
  50        ctrl = readb(&host->reg->hostctl);
  51        ctrl &= ~(3 << 3);
  52        writeb(ctrl, &host->reg->hostctl);
  53
  54        /* We do not handle DMA boundaries, so set it to max (512 KiB) */
  55        writew((7 << 12) | (data->blocksize & 0xFFF), &host->reg->blksize);
  56        writew(data->blocks, &host->reg->blkcnt);
  57}
  58
  59static void mmc_set_transfer_mode(struct mmc_host *host, struct mmc_data *data)
  60{
  61        unsigned short mode;
  62
  63        /*
  64         * TRNMOD
  65         * MUL1SIN0[5]  : Multi/Single Block Select
  66         * RD1WT0[4]    : Data Transfer Direction Select
  67         *      1 = read
  68         *      0 = write
  69         * ENACMD12[2]  : Auto CMD12 Enable
  70         * ENBLKCNT[1]  : Block Count Enable
  71         * ENDMA[0]     : DMA Enable
  72         */
  73        mode = (1 << 1) | (1 << 0);
  74        if (data->blocks > 1)
  75                mode |= (1 << 5);
  76        if (data->flags & MMC_DATA_READ)
  77                mode |= (1 << 4);
  78
  79        writew(mode, &host->reg->trnmod);
  80}
  81
  82static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
  83                        struct mmc_data *data)
  84{
  85        struct mmc_host *host = (struct mmc_host *)mmc->priv;
  86        int flags, i;
  87        unsigned int timeout;
  88        unsigned int mask;
  89        unsigned int retry = 0x100000;
  90
  91        /* Wait max 10 ms */
  92        timeout = 10;
  93
  94        /*
  95         * PRNSTS
  96         * CMDINHDAT[1] : Command Inhibit (DAT)
  97         * CMDINHCMD[0] : Command Inhibit (CMD)
  98         */
  99        mask = (1 << 0);
 100        if ((data != NULL) || (cmd->resp_type & MMC_RSP_BUSY))
 101                mask |= (1 << 1);
 102
 103        /*
 104         * We shouldn't wait for data inihibit for stop commands, even
 105         * though they might use busy signaling
 106         */
 107        if (data)
 108                mask &= ~(1 << 1);
 109
 110        while (readl(&host->reg->prnsts) & mask) {
 111                if (timeout == 0) {
 112                        printf("%s: timeout error\n", __func__);
 113                        return -1;
 114                }
 115                timeout--;
 116                udelay(1000);
 117        }
 118
 119        if (data)
 120                mmc_prepare_data(host, data);
 121
 122        debug("cmd->arg: %08x\n", cmd->cmdarg);
 123        writel(cmd->cmdarg, &host->reg->argument);
 124
 125        if (data)
 126                mmc_set_transfer_mode(host, data);
 127
 128        if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY))
 129                return -1;
 130
 131        /*
 132         * CMDREG
 133         * CMDIDX[13:8] : Command index
 134         * DATAPRNT[5]  : Data Present Select
 135         * ENCMDIDX[4]  : Command Index Check Enable
 136         * ENCMDCRC[3]  : Command CRC Check Enable
 137         * RSPTYP[1:0]
 138         *      00 = No Response
 139         *      01 = Length 136
 140         *      10 = Length 48
 141         *      11 = Length 48 Check busy after response
 142         */
 143        if (!(cmd->resp_type & MMC_RSP_PRESENT))
 144                flags = 0;
 145        else if (cmd->resp_type & MMC_RSP_136)
 146                flags = (1 << 0);
 147        else if (cmd->resp_type & MMC_RSP_BUSY)
 148                flags = (3 << 0);
 149        else
 150                flags = (2 << 0);
 151
 152        if (cmd->resp_type & MMC_RSP_CRC)
 153                flags |= (1 << 3);
 154        if (cmd->resp_type & MMC_RSP_OPCODE)
 155                flags |= (1 << 4);
 156        if (data)
 157                flags |= (1 << 5);
 158
 159        debug("cmd: %d\n", cmd->cmdidx);
 160
 161        writew((cmd->cmdidx << 8) | flags, &host->reg->cmdreg);
 162
 163        for (i = 0; i < retry; i++) {
 164                mask = readl(&host->reg->norintsts);
 165                /* Command Complete */
 166                if (mask & (1 << 0)) {
 167                        if (!data)
 168                                writel(mask, &host->reg->norintsts);
 169                        break;
 170                }
 171        }
 172
 173        if (i == retry) {
 174                printf("%s: waiting for status update\n", __func__);
 175                return TIMEOUT;
 176        }
 177
 178        if (mask & (1 << 16)) {
 179                /* Timeout Error */
 180                debug("timeout: %08x cmd %d\n", mask, cmd->cmdidx);
 181                return TIMEOUT;
 182        } else if (mask & (1 << 15)) {
 183                /* Error Interrupt */
 184                debug("error: %08x cmd %d\n", mask, cmd->cmdidx);
 185                return -1;
 186        }
 187
 188        if (cmd->resp_type & MMC_RSP_PRESENT) {
 189                if (cmd->resp_type & MMC_RSP_136) {
 190                        /* CRC is stripped so we need to do some shifting. */
 191                        for (i = 0; i < 4; i++) {
 192                                unsigned int offset =
 193                                        (unsigned int)(&host->reg->rspreg3 - i);
 194                                cmd->response[i] = readl(offset) << 8;
 195
 196                                if (i != 3) {
 197                                        cmd->response[i] |=
 198                                                readb(offset - 1);
 199                                }
 200                                debug("cmd->resp[%d]: %08x\n",
 201                                                i, cmd->response[i]);
 202                        }
 203                } else if (cmd->resp_type & MMC_RSP_BUSY) {
 204                        for (i = 0; i < retry; i++) {
 205                                /* PRNTDATA[23:20] : DAT[3:0] Line Signal */
 206                                if (readl(&host->reg->prnsts)
 207                                        & (1 << 20))    /* DAT[0] */
 208                                        break;
 209                        }
 210
 211                        if (i == retry) {
 212                                printf("%s: card is still busy\n", __func__);
 213                                return TIMEOUT;
 214                        }
 215
 216                        cmd->response[0] = readl(&host->reg->rspreg0);
 217                        debug("cmd->resp[0]: %08x\n", cmd->response[0]);
 218                } else {
 219                        cmd->response[0] = readl(&host->reg->rspreg0);
 220                        debug("cmd->resp[0]: %08x\n", cmd->response[0]);
 221                }
 222        }
 223
 224        if (data) {
 225                while (1) {
 226                        mask = readl(&host->reg->norintsts);
 227
 228                        if (mask & (1 << 15)) {
 229                                /* Error Interrupt */
 230                                writel(mask, &host->reg->norintsts);
 231                                printf("%s: error during transfer: 0x%08x\n",
 232                                                __func__, mask);
 233                                return -1;
 234                        } else if (mask & (1 << 3)) {
 235                                /*
 236                                 * DMA Interrupt, restart the transfer where
 237                                 * it was interrupted.
 238                                 */
 239                                unsigned int address = readl(&host->reg->sysad);
 240
 241                                debug("DMA end\n");
 242                                writel((1 << 3), &host->reg->norintsts);
 243                                writel(address, &host->reg->sysad);
 244                        } else if (mask & (1 << 1)) {
 245                                /* Transfer Complete */
 246                                debug("r/w is done\n");
 247                                break;
 248                        }
 249                }
 250                writel(mask, &host->reg->norintsts);
 251        }
 252
 253        udelay(1000);
 254        return 0;
 255}
 256
 257static void mmc_change_clock(struct mmc_host *host, uint clock)
 258{
 259        int div;
 260        unsigned short clk;
 261        unsigned long timeout;
 262        unsigned long ctrl2;
 263
 264        /*
 265         * SELBASECLK[5:4]
 266         * 00/01 = HCLK
 267         * 10 = EPLL
 268         * 11 = XTI or XEXTCLK
 269         */
 270        ctrl2 = readl(&host->reg->control2);
 271        ctrl2 &= ~(3 << 4);
 272        ctrl2 |= (2 << 4);
 273        writel(ctrl2, &host->reg->control2);
 274
 275        writew(0, &host->reg->clkcon);
 276
 277        /* XXX: we assume that clock is between 40MHz and 50MHz */
 278        if (clock == 0)
 279                goto out;
 280        else if (clock <= 400000)
 281                div = 0x100;
 282        else if (clock <= 20000000)
 283                div = 4;
 284        else if (clock <= 26000000)
 285                div = 2;
 286        else
 287                div = 1;
 288        debug("div: %d\n", div);
 289
 290        div >>= 1;
 291        /*
 292         * CLKCON
 293         * SELFREQ[15:8]        : base clock divied by value
 294         * ENSDCLK[2]           : SD Clock Enable
 295         * STBLINTCLK[1]        : Internal Clock Stable
 296         * ENINTCLK[0]          : Internal Clock Enable
 297         */
 298        clk = (div << 8) | (1 << 0);
 299        writew(clk, &host->reg->clkcon);
 300
 301        set_mmc_clk(host->dev_index, div);
 302
 303        /* Wait max 10 ms */
 304        timeout = 10;
 305        while (!(readw(&host->reg->clkcon) & (1 << 1))) {
 306                if (timeout == 0) {
 307                        printf("%s: timeout error\n", __func__);
 308                        return;
 309                }
 310                timeout--;
 311                udelay(1000);
 312        }
 313
 314        clk |= (1 << 2);
 315        writew(clk, &host->reg->clkcon);
 316
 317out:
 318        host->clock = clock;
 319}
 320
 321static void mmc_set_ios(struct mmc *mmc)
 322{
 323        struct mmc_host *host = mmc->priv;
 324        unsigned char ctrl;
 325        unsigned long val;
 326
 327        debug("bus_width: %x, clock: %d\n", mmc->bus_width, mmc->clock);
 328
 329        /*
 330         * SELCLKPADDS[17:16]
 331         * 00 = 2mA
 332         * 01 = 4mA
 333         * 10 = 7mA
 334         * 11 = 9mA
 335         */
 336        writel(0x3 << 16, &host->reg->control4);
 337
 338        val = readl(&host->reg->control2);
 339        val &= (0x3 << 4);
 340
 341        val |=  (1 << 31) |     /* write status clear async mode enable */
 342                (1 << 30) |     /* command conflict mask enable */
 343                (1 << 14) |     /* Feedback Clock Enable for Rx Clock */
 344                (1 << 8);       /* SDCLK hold enable */
 345
 346        writel(val, &host->reg->control2);
 347
 348        /*
 349         * FCSEL1[15] FCSEL0[7]
 350         * FCSel[1:0] : Rx Feedback Clock Delay Control
 351         *      Inverter delay means10ns delay if SDCLK 50MHz setting
 352         *      01 = Delay1 (basic delay)
 353         *      11 = Delay2 (basic delay + 2ns)
 354         *      00 = Delay3 (inverter delay)
 355         *      10 = Delay4 (inverter delay + 2ns)
 356         */
 357        writel(0x8080, &host->reg->control3);
 358
 359        mmc_change_clock(host, mmc->clock);
 360
 361        ctrl = readb(&host->reg->hostctl);
 362
 363        /*
 364         * WIDE8[5]
 365         * 0 = Depend on WIDE4
 366         * 1 = 8-bit mode
 367         * WIDE4[1]
 368         * 1 = 4-bit mode
 369         * 0 = 1-bit mode
 370         */
 371        if (mmc->bus_width == 8)
 372                ctrl |= (1 << 5);
 373        else if (mmc->bus_width == 4)
 374                ctrl |= (1 << 1);
 375        else
 376                ctrl &= ~(1 << 1);
 377
 378        /*
 379         * OUTEDGEINV[2]
 380         * 1 = Riging edge output
 381         * 0 = Falling edge output
 382         */
 383        ctrl &= ~(1 << 2);
 384
 385        writeb(ctrl, &host->reg->hostctl);
 386}
 387
 388static void mmc_reset(struct mmc_host *host)
 389{
 390        unsigned int timeout;
 391
 392        /*
 393         * RSTALL[0] : Software reset for all
 394         * 1 = reset
 395         * 0 = work
 396         */
 397        writeb((1 << 0), &host->reg->swrst);
 398
 399        host->clock = 0;
 400
 401        /* Wait max 100 ms */
 402        timeout = 100;
 403
 404        /* hw clears the bit when it's done */
 405        while (readb(&host->reg->swrst) & (1 << 0)) {
 406                if (timeout == 0) {
 407                        printf("%s: timeout error\n", __func__);
 408                        return;
 409                }
 410                timeout--;
 411                udelay(1000);
 412        }
 413}
 414
 415static int mmc_core_init(struct mmc *mmc)
 416{
 417        struct mmc_host *host = (struct mmc_host *)mmc->priv;
 418        unsigned int mask;
 419
 420        mmc_reset(host);
 421
 422        host->version = readw(&host->reg->hcver);
 423
 424        /* mask all */
 425        writel(0xffffffff, &host->reg->norintstsen);
 426        writel(0xffffffff, &host->reg->norintsigen);
 427
 428        writeb(0xe, &host->reg->timeoutcon);    /* TMCLK * 2^27 */
 429
 430        /*
 431         * NORMAL Interrupt Status Enable Register init
 432         * [5] ENSTABUFRDRDY : Buffer Read Ready Status Enable
 433         * [4] ENSTABUFWTRDY : Buffer write Ready Status Enable
 434         * [3] ENSTADMAINT : DMA Interrupt Status Enable
 435         * [1] ENSTASTANSCMPLT : Transfre Complete Status Enable
 436         * [0] ENSTACMDCMPLT : Command Complete Status Enable
 437         */
 438        mask = readl(&host->reg->norintstsen);
 439        mask &= ~(0xffff);
 440        mask |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1) | (1 << 0);
 441        writel(mask, &host->reg->norintstsen);
 442
 443        /*
 444         * NORMAL Interrupt Signal Enable Register init
 445         * [1] ENSTACMDCMPLT : Transfer Complete Signal Enable
 446         */
 447        mask = readl(&host->reg->norintsigen);
 448        mask &= ~(0xffff);
 449        mask |= (1 << 1);
 450        writel(mask, &host->reg->norintsigen);
 451
 452        return 0;
 453}
 454
 455static int s5p_mmc_initialize(int dev_index, int bus_width)
 456{
 457        struct mmc *mmc;
 458
 459        mmc = &mmc_dev[dev_index];
 460
 461        sprintf(mmc->name, "SAMSUNG SD/MMC");
 462        mmc->priv = &mmc_host[dev_index];
 463        mmc->send_cmd = mmc_send_cmd;
 464        mmc->set_ios = mmc_set_ios;
 465        mmc->init = mmc_core_init;
 466        mmc->getcd = NULL;
 467
 468        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 469        if (bus_width == 8)
 470                mmc->host_caps = MMC_MODE_8BIT;
 471        else
 472                mmc->host_caps = MMC_MODE_4BIT;
 473        mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
 474
 475        mmc->f_min = 400000;
 476        mmc->f_max = 52000000;
 477
 478        mmc_host[dev_index].dev_index = dev_index;
 479        mmc_host[dev_index].clock = 0;
 480        mmc_host[dev_index].reg = s5p_get_base_mmc(dev_index);
 481        mmc->b_max = 0;
 482        mmc_register(mmc);
 483
 484        return 0;
 485}
 486
 487int s5p_mmc_init(int dev_index, int bus_width)
 488{
 489        return s5p_mmc_initialize(dev_index, bus_width);
 490}
 491