uboot/drivers/mmc/gen_atmel_mci.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2010
   3 * Rob Emanuele <rob@emanuele.us>
   4 * Reinhard Meyer, EMK Elektronik <reinhard.meyer@emk-elektronik.de>
   5 *
   6 * Original Driver:
   7 * Copyright (C) 2004-2006 Atmel Corporation
   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 <common.h>
  29#include <mmc.h>
  30#include <part.h>
  31#include <malloc.h>
  32#include <asm/io.h>
  33#include <asm/errno.h>
  34#include <asm/byteorder.h>
  35#include <asm/arch/clk.h>
  36#include <asm/arch/hardware.h>
  37#include "atmel_mci.h"
  38
  39#ifndef CONFIG_SYS_MMC_CLK_OD
  40# define CONFIG_SYS_MMC_CLK_OD  150000
  41#endif
  42
  43#define MMC_DEFAULT_BLKLEN      512
  44
  45#if defined(CONFIG_ATMEL_MCI_PORTB)
  46# define MCI_BUS 1
  47#else
  48# define MCI_BUS 0
  49#endif
  50
  51static int initialized = 0;
  52
  53/*
  54 * Print command and status:
  55 *
  56 * - always when DEBUG is defined
  57 * - on command errors
  58 */
  59static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
  60{
  61        printf("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n",
  62                cmdr, cmdr&0x3F, arg, status, msg);
  63}
  64
  65/* Setup for MCI Clock and Block Size */
  66static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
  67{
  68        atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
  69        u32 bus_hz = get_mci_clk_rate();
  70        u32 clkdiv = 255;
  71
  72        debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n",
  73                bus_hz, hz, blklen);
  74        if (hz > 0) {
  75                /* find lowest clkdiv yielding a rate <= than requested */
  76                for (clkdiv=0; clkdiv<255; clkdiv++) {
  77                        if ((bus_hz / (clkdiv+1) / 2) <= hz)
  78                                break;
  79                }
  80        }
  81        printf("mci: setting clock %u Hz, block size %u\n",
  82                (bus_hz / (clkdiv+1)) / 2, blklen);
  83
  84        blklen &= 0xfffc;
  85        /* On some platforms RDPROOF and WRPROOF are ignored */
  86        writel((MMCI_BF(CLKDIV, clkdiv)
  87                 | MMCI_BF(BLKLEN, blklen)
  88                 | MMCI_BIT(RDPROOF)
  89                 | MMCI_BIT(WRPROOF)), &mci->mr);
  90        initialized = 1;
  91}
  92
  93/* Return the CMDR with flags for a given command and data packet */
  94static u32 mci_encode_cmd(
  95        struct mmc_cmd *cmd, struct mmc_data *data, u32* error_flags)
  96{
  97        u32 cmdr = 0;
  98
  99        /* Default Flags for Errors */
 100        *error_flags |= (MMCI_BIT(DTOE) | MMCI_BIT(RDIRE) | MMCI_BIT(RENDE) |
 101                MMCI_BIT(RINDE) | MMCI_BIT(RTOE));
 102
 103        /* Default Flags for the Command */
 104        cmdr |= MMCI_BIT(MAXLAT);
 105
 106        if (data) {
 107                cmdr |= MMCI_BF(TRCMD, 1);
 108                if (data->blocks > 1)
 109                        cmdr |= MMCI_BF(TRTYP, 1);
 110                if (data->flags & MMC_DATA_READ)
 111                        cmdr |= MMCI_BIT(TRDIR);
 112        }
 113
 114        if (cmd->resp_type & MMC_RSP_CRC)
 115                *error_flags |= MMCI_BIT(RCRCE);
 116        if (cmd->resp_type & MMC_RSP_136)
 117                cmdr |= MMCI_BF(RSPTYP, 2);
 118        else if (cmd->resp_type & MMC_RSP_BUSY)
 119                cmdr |= MMCI_BF(RSPTYP, 3);
 120        else if (cmd->resp_type & MMC_RSP_PRESENT)
 121                cmdr |= MMCI_BF(RSPTYP, 1);
 122
 123        return cmdr | MMCI_BF(CMDNB, cmd->cmdidx);
 124}
 125
 126/* Entered into function pointer in mci_send_cmd */
 127static u32 mci_data_read(atmel_mci_t *mci, u32* data, u32 error_flags)
 128{
 129        u32 status;
 130
 131        do {
 132                status = readl(&mci->sr);
 133                if (status & (error_flags | MMCI_BIT(OVRE)))
 134                        goto io_fail;
 135        } while (!(status & MMCI_BIT(RXRDY)));
 136
 137        if (status & MMCI_BIT(RXRDY)) {
 138                *data = readl(&mci->rdr);
 139                status = 0;
 140        }
 141io_fail:
 142        return status;
 143}
 144
 145/* Entered into function pointer in mci_send_cmd */
 146static u32 mci_data_write(atmel_mci_t *mci, u32* data, u32 error_flags)
 147{
 148        u32 status;
 149
 150        do {
 151                status = readl(&mci->sr);
 152                if (status & (error_flags | MMCI_BIT(UNRE)))
 153                        goto io_fail;
 154        } while (!(status & MMCI_BIT(TXRDY)));
 155
 156        if (status & MMCI_BIT(TXRDY)) {
 157                writel(*data, &mci->tdr);
 158                status = 0;
 159        }
 160io_fail:
 161        return status;
 162}
 163
 164/*
 165 * Entered into mmc structure during driver init
 166 *
 167 * Sends a command out on the bus and deals with the block data.
 168 * Takes the mmc pointer, a command pointer, and an optional data pointer.
 169 */
 170static int
 171mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 172{
 173        atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
 174        u32 cmdr;
 175        u32 error_flags = 0;
 176        u32 status;
 177
 178        if (!initialized) {
 179                puts ("MCI not initialized!\n");
 180                return COMM_ERR;
 181        }
 182
 183        /* Figure out the transfer arguments */
 184        cmdr = mci_encode_cmd(cmd, data, &error_flags);
 185
 186        /* Send the command */
 187        writel(cmd->cmdarg, &mci->argr);
 188        writel(cmdr, &mci->cmdr);
 189
 190#ifdef DEBUG
 191        dump_cmd(cmdr, cmd->cmdarg, 0, "DEBUG");
 192#endif
 193
 194        /* Wait for the command to complete */
 195        while (!((status = readl(&mci->sr)) & MMCI_BIT(CMDRDY)));
 196
 197        if (status & error_flags) {
 198                dump_cmd(cmdr, cmd->cmdarg, status, "Command Failed");
 199                return COMM_ERR;
 200        }
 201
 202        /* Copy the response to the response buffer */
 203        if (cmd->resp_type & MMC_RSP_136) {
 204                cmd->response[0] = readl(&mci->rspr);
 205                cmd->response[1] = readl(&mci->rspr1);
 206                cmd->response[2] = readl(&mci->rspr2);
 207                cmd->response[3] = readl(&mci->rspr3);
 208        } else
 209                cmd->response[0] = readl(&mci->rspr);
 210
 211        /* transfer all of the blocks */
 212        if (data) {
 213                u32 word_count, block_count;
 214                u32* ioptr;
 215                u32 sys_blocksize, dummy, i;
 216                u32 (*mci_data_op)
 217                        (atmel_mci_t *mci, u32* data, u32 error_flags);
 218
 219                if (data->flags & MMC_DATA_READ) {
 220                        mci_data_op = mci_data_read;
 221                        sys_blocksize = mmc->read_bl_len;
 222                        ioptr = (u32*)data->dest;
 223                } else {
 224                        mci_data_op = mci_data_write;
 225                        sys_blocksize = mmc->write_bl_len;
 226                        ioptr = (u32*)data->src;
 227                }
 228
 229                status = 0;
 230                for (block_count = 0;
 231                                block_count < data->blocks && !status;
 232                                block_count++) {
 233                        word_count = 0;
 234                        do {
 235                                status = mci_data_op(mci, ioptr, error_flags);
 236                                word_count++;
 237                                ioptr++;
 238                        } while (!status && word_count < (data->blocksize/4));
 239#ifdef DEBUG
 240                        if (data->flags & MMC_DATA_READ)
 241                        {
 242                                printf("Read Data:\n");
 243                                print_buffer(0, data->dest, 1,
 244                                        word_count*4, 0);
 245                        }
 246#endif
 247#ifdef DEBUG
 248                        if (!status && word_count < (sys_blocksize / 4))
 249                                printf("filling rest of block...\n");
 250#endif
 251                        /* fill the rest of a full block */
 252                        while (!status && word_count < (sys_blocksize / 4)) {
 253                                status = mci_data_op(mci, &dummy,
 254                                        error_flags);
 255                                word_count++;
 256                        }
 257                        if (status) {
 258                                dump_cmd(cmdr, cmd->cmdarg, status,
 259                                        "Data Transfer Failed");
 260                                return COMM_ERR;
 261                        }
 262                }
 263
 264                /* Wait for Transfer End */
 265                i = 0;
 266                do {
 267                        status = readl(&mci->sr);
 268
 269                        if (status & error_flags) {
 270                                dump_cmd(cmdr, cmd->cmdarg, status,
 271                                        "DTIP Wait Failed");
 272                                return COMM_ERR;
 273                        }
 274                        i++;
 275                } while ((status & MMCI_BIT(DTIP)) && i < 10000);
 276                if (status & MMCI_BIT(DTIP)) {
 277                        dump_cmd(cmdr, cmd->cmdarg, status,
 278                                "XFER DTIP never unset, ignoring");
 279                }
 280        }
 281
 282        return 0;
 283}
 284
 285/* Entered into mmc structure during driver init */
 286static void mci_set_ios(struct mmc *mmc)
 287{
 288        atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
 289        int busw = (mmc->bus_width == 4) ? 1 : 0;
 290
 291        /* Set the clock speed */
 292        mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
 293
 294        /*
 295         * set the bus width and select slot for this interface
 296         * there is no capability for multiple slots on the same interface yet
 297         * Bitfield SCDBUS needs to be expanded to 2 bits for 8-bit buses
 298         */
 299        writel(MMCI_BF(SCDBUS, busw) | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
 300}
 301
 302/* Entered into mmc structure during driver init */
 303static int mci_init(struct mmc *mmc)
 304{
 305        atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
 306
 307        /* Initialize controller */
 308        writel(MMCI_BIT(SWRST), &mci->cr);      /* soft reset */
 309        writel(MMCI_BIT(PWSDIS), &mci->cr);     /* disable power save */
 310        writel(MMCI_BIT(MCIEN), &mci->cr);      /* enable mci */
 311        writel(MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);   /* select port */
 312
 313        /* Initial Time-outs */
 314        writel(0x5f, &mci->dtor);
 315        /* Disable Interrupts */
 316        writel(~0UL, &mci->idr);
 317
 318        /* Set default clocks and blocklen */
 319        mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
 320
 321        return 0;
 322}
 323
 324/*
 325 * This is the only exported function
 326 *
 327 * Call it with the MCI register base address
 328 */
 329int atmel_mci_init(void *regs)
 330{
 331        struct mmc *mmc = malloc(sizeof(struct mmc));
 332
 333        if (!mmc)
 334                return -1;
 335        strcpy(mmc->name, "mci");
 336        mmc->priv = regs;
 337        mmc->send_cmd = mci_send_cmd;
 338        mmc->set_ios = mci_set_ios;
 339        mmc->init = mci_init;
 340        mmc->getcd = NULL;
 341
 342        /* need to be able to pass these in on a board by board basis */
 343        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 344        mmc->host_caps = MMC_MODE_4BIT;
 345        /*
 346         * min and max frequencies determined by
 347         * max and min of clock divider
 348         */
 349        mmc->f_min = get_mci_clk_rate() / (2*256);
 350        mmc->f_max = get_mci_clk_rate() / (2*1);
 351
 352        mmc->b_max = 0;
 353
 354        mmc_register(mmc);
 355
 356        return 0;
 357}
 358