Commit fc26c97bb6df41b4a95662c34054fe912387bf38

Authored by Haavard Skinnemoen
1 parent 05fdab1ef6

Atmel MCI driver

Driver for the Atmel MCI controller (MMC interface) for AT32AP CPUs.

The AT91 ARM-based CPUs use basically the same hardware, so it should
be possible to share this driver, but no effort has been made so far.

Hardware documentation can be found in the AT32AP7000 data sheet,
which can be downloaded from

http://www.atmel.com/dyn/products/datasheets.asp?family_id=682

Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>

Showing 4 changed files with 771 additions and 1 deletions Side-by-side Diff

... ... @@ -30,7 +30,7 @@
30 30 START := start.o
31 31 SOBJS := entry.o
32 32 COBJS := cpu.o hsdramc.o exception.o cache.o
33   -COBJS += interrupts.o pio.o
  33 +COBJS += interrupts.o pio.o atmel_mci.o
34 34 SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
35 35 OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
36 36 START := $(addprefix $(obj),$(START))
cpu/at32ap/atmel_mci.c
  1 +/*
  2 + * Copyright (C) 2004-2006 Atmel Corporation
  3 + *
  4 + * See file CREDITS for list of people who contributed to this
  5 + * project.
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License as
  9 + * published by the Free Software Foundation; either version 2 of
  10 + * the License, or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 + * MA 02111-1307 USA
  21 + */
  22 +#include <common.h>
  23 +
  24 +#ifdef CONFIG_MMC
  25 +
  26 +#include <part.h>
  27 +#include <mmc.h>
  28 +
  29 +#include <asm/io.h>
  30 +#include <asm/errno.h>
  31 +#include <asm/byteorder.h>
  32 +#include <asm/arch/clk.h>
  33 +#include <asm/arch/memory-map.h>
  34 +
  35 +#include "atmel_mci.h"
  36 +
  37 +#ifdef DEBUG
  38 +#define pr_debug(fmt, args...) printf(fmt, ##args)
  39 +#else
  40 +#define pr_debug(...) do { } while(0)
  41 +#endif
  42 +
  43 +#ifndef CFG_MMC_CLK_OD
  44 +#define CFG_MMC_CLK_OD 150000
  45 +#endif
  46 +
  47 +#ifndef CFG_MMC_CLK_PP
  48 +#define CFG_MMC_CLK_PP 5000000
  49 +#endif
  50 +
  51 +#ifndef CFG_MMC_OP_COND
  52 +#define CFG_MMC_OP_COND 0x00100000
  53 +#endif
  54 +
  55 +#define MMC_DEFAULT_BLKLEN 512
  56 +#define MMC_DEFAULT_RCA 1
  57 +
  58 +static unsigned int mmc_rca;
  59 +static block_dev_desc_t mmc_blkdev;
  60 +
  61 +block_dev_desc_t *mmc_get_dev(int dev)
  62 +{
  63 + return &mmc_blkdev;
  64 +}
  65 +
  66 +static void mci_set_mode(unsigned long hz, unsigned long blklen)
  67 +{
  68 + unsigned long bus_hz;
  69 + unsigned long clkdiv;
  70 +
  71 + bus_hz = get_mci_clk_rate();
  72 + clkdiv = (bus_hz / hz) / 2 - 1;
  73 +
  74 + pr_debug("mmc: setting clock %lu Hz, block size %lu\n",
  75 + hz, blklen);
  76 +
  77 + if (clkdiv & ~255UL) {
  78 + clkdiv = 255;
  79 + printf("mmc: clock %lu too low; setting CLKDIV to 255\n",
  80 + hz);
  81 + }
  82 +
  83 + blklen &= 0xfffc;
  84 + mmci_writel(MR, (MMCI_BF(CLKDIV, clkdiv)
  85 + | MMCI_BF(BLKLEN, blklen)));
  86 +}
  87 +
  88 +#define RESP_NO_CRC 1
  89 +#define R1 MMCI_BF(RSPTYP, 1)
  90 +#define R2 MMCI_BF(RSPTYP, 2)
  91 +#define R3 (R1 | RESP_NO_CRC)
  92 +#define R6 R1
  93 +#define NID MMCI_BF(MAXLAT, 0)
  94 +#define NCR MMCI_BF(MAXLAT, 1)
  95 +#define TRCMD_START MMCI_BF(TRCMD, 1)
  96 +#define TRDIR_READ MMCI_BF(TRDIR, 1)
  97 +#define TRTYP_BLOCK MMCI_BF(TRTYP, 0)
  98 +#define INIT_CMD MMCI_BF(SPCMD, 1)
  99 +#define OPEN_DRAIN MMCI_BF(OPDCMD, 1)
  100 +
  101 +#define ERROR_FLAGS (MMCI_BIT(DTOE) \
  102 + | MMCI_BIT(RDIRE) \
  103 + | MMCI_BIT(RENDE) \
  104 + | MMCI_BIT(RINDE) \
  105 + | MMCI_BIT(RTOE))
  106 +
  107 +static int
  108 +mmc_cmd(unsigned long cmd, unsigned long arg,
  109 + void *resp, unsigned long flags)
  110 +{
  111 + unsigned long *response = resp;
  112 + int i, response_words = 0;
  113 + unsigned long error_flags;
  114 + u32 status;
  115 +
  116 + pr_debug("mmc: CMD%lu 0x%lx (flags 0x%lx)\n",
  117 + cmd, arg, flags);
  118 +
  119 + error_flags = ERROR_FLAGS;
  120 + if (!(flags & RESP_NO_CRC))
  121 + error_flags |= MMCI_BIT(RCRCE);
  122 +
  123 + flags &= ~MMCI_BF(CMDNB, ~0UL);
  124 +
  125 + if (MMCI_BFEXT(RSPTYP, flags) == MMCI_RSPTYP_48_BIT_RESP)
  126 + response_words = 1;
  127 + else if (MMCI_BFEXT(RSPTYP, flags) == MMCI_RSPTYP_136_BIT_RESP)
  128 + response_words = 4;
  129 +
  130 + mmci_writel(ARGR, arg);
  131 + mmci_writel(CMDR, cmd | flags);
  132 + do {
  133 + udelay(40);
  134 + status = mmci_readl(SR);
  135 + } while (!(status & MMCI_BIT(CMDRDY)));
  136 +
  137 + pr_debug("mmc: status 0x%08lx\n", status);
  138 +
  139 + if (status & ERROR_FLAGS) {
  140 + printf("mmc: command %lu failed (status: 0x%08lx)\n",
  141 + cmd, status);
  142 + return -EIO;
  143 + }
  144 +
  145 + if (response_words)
  146 + pr_debug("mmc: response:");
  147 +
  148 + for (i = 0; i < response_words; i++) {
  149 + response[i] = mmci_readl(RSPR);
  150 + pr_debug(" %08lx", response[i]);
  151 + }
  152 + pr_debug("\n");
  153 +
  154 + return 0;
  155 +}
  156 +
  157 +static int mmc_acmd(unsigned long cmd, unsigned long arg,
  158 + void *resp, unsigned long flags)
  159 +{
  160 + unsigned long aresp[4];
  161 + int ret;
  162 +
  163 + /*
  164 + * Seems like the APP_CMD part of an ACMD has 64 cycles max
  165 + * latency even though the ACMD part doesn't. This isn't
  166 + * entirely clear in the SD Card spec, but some cards refuse
  167 + * to work if we attempt to use 5 cycles max latency here...
  168 + */
  169 + ret = mmc_cmd(MMC_CMD_APP_CMD, 0, aresp,
  170 + R1 | NCR | (flags & OPEN_DRAIN));
  171 + if (ret)
  172 + return ret;
  173 + if ((aresp[0] & (R1_ILLEGAL_COMMAND | R1_APP_CMD)) != R1_APP_CMD)
  174 + return -ENODEV;
  175 +
  176 + ret = mmc_cmd(cmd, arg, resp, flags);
  177 + return ret;
  178 +}
  179 +
  180 +static unsigned long
  181 +mmc_bread(int dev, unsigned long start, lbaint_t blkcnt,
  182 + unsigned long *buffer)
  183 +{
  184 + int ret, i = 0;
  185 + unsigned long resp[4];
  186 + unsigned long card_status, data;
  187 + unsigned long wordcount;
  188 + u32 status;
  189 +
  190 + if (blkcnt == 0)
  191 + return 0;
  192 +
  193 + pr_debug("mmc_bread: dev %d, start %lx, blkcnt %lx\n",
  194 + dev, start, blkcnt);
  195 +
  196 + /* Put the device into Transfer state */
  197 + ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, R1 | NCR);
  198 + if (ret) goto fail;
  199 +
  200 + /* Set block length */
  201 + ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, R1 | NCR);
  202 + if (ret) goto fail;
  203 +
  204 + pr_debug("MCI_DTOR = %08lx\n", mmci_readl(DTOR));
  205 +
  206 + for (i = 0; i < blkcnt; i++, start++) {
  207 + ret = mmc_cmd(MMC_CMD_READ_SINGLE_BLOCK,
  208 + start * mmc_blkdev.blksz, resp,
  209 + (R1 | NCR | TRCMD_START | TRDIR_READ
  210 + | TRTYP_BLOCK));
  211 + if (ret) goto fail;
  212 +
  213 + ret = -EIO;
  214 + wordcount = 0;
  215 + do {
  216 + do {
  217 + status = mmci_readl(SR);
  218 + if (status & (ERROR_FLAGS | MMCI_BIT(OVRE)))
  219 + goto fail;
  220 + } while (!(status & MMCI_BIT(RXRDY)));
  221 +
  222 + if (status & MMCI_BIT(RXRDY)) {
  223 + data = mmci_readl(RDR);
  224 + // pr_debug("%x\n", data);
  225 + *buffer++ = data;
  226 + wordcount++;
  227 + }
  228 + } while(wordcount < (512 / 4));
  229 +
  230 + pr_debug("mmc: read %u words, waiting for BLKE\n", wordcount);
  231 +
  232 + do {
  233 + status = mmci_readl(SR);
  234 + } while (!(status & MMCI_BIT(BLKE)));
  235 +
  236 + putc('.');
  237 + }
  238 +
  239 +out:
  240 + /* Put the device back into Standby state */
  241 + mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, NCR);
  242 + return i;
  243 +
  244 +fail:
  245 + mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 | NCR);
  246 + printf("mmc: bread failed, card status = ", card_status);
  247 + goto out;
  248 +}
  249 +
  250 +static void mmc_parse_cid(struct mmc_cid *cid, unsigned long *resp)
  251 +{
  252 + cid->mid = resp[0] >> 24;
  253 + cid->oid = (resp[0] >> 8) & 0xffff;
  254 + cid->pnm[0] = resp[0];
  255 + cid->pnm[1] = resp[1] >> 24;
  256 + cid->pnm[2] = resp[1] >> 16;
  257 + cid->pnm[3] = resp[1] >> 8;
  258 + cid->pnm[4] = resp[1];
  259 + cid->pnm[5] = resp[2] >> 24;
  260 + cid->pnm[6] = 0;
  261 + cid->prv = resp[2] >> 16;
  262 + cid->psn = (resp[2] << 16) | (resp[3] >> 16);
  263 + cid->mdt = resp[3] >> 8;
  264 +}
  265 +
  266 +static void sd_parse_cid(struct mmc_cid *cid, unsigned long *resp)
  267 +{
  268 + cid->mid = resp[0] >> 24;
  269 + cid->oid = (resp[0] >> 8) & 0xffff;
  270 + cid->pnm[0] = resp[0];
  271 + cid->pnm[1] = resp[1] >> 24;
  272 + cid->pnm[2] = resp[1] >> 16;
  273 + cid->pnm[3] = resp[1] >> 8;
  274 + cid->pnm[4] = resp[1];
  275 + cid->pnm[5] = 0;
  276 + cid->pnm[6] = 0;
  277 + cid->prv = resp[2] >> 24;
  278 + cid->psn = (resp[2] << 8) | (resp[3] >> 24);
  279 + cid->mdt = (resp[3] >> 8) & 0x0fff;
  280 +}
  281 +
  282 +static void mmc_dump_cid(const struct mmc_cid *cid)
  283 +{
  284 + printf("Manufacturer ID: %02lX\n", cid->mid);
  285 + printf("OEM/Application ID: %04lX\n", cid->oid);
  286 + printf("Product name: %s\n", cid->pnm);
  287 + printf("Product Revision: %lu.%lu\n",
  288 + cid->prv >> 4, cid->prv & 0x0f);
  289 + printf("Product Serial Number: %lu\n", cid->psn);
  290 + printf("Manufacturing Date: %02lu/%02lu\n",
  291 + cid->mdt >> 4, cid->mdt & 0x0f);
  292 +}
  293 +
  294 +static void mmc_dump_csd(const struct mmc_csd *csd)
  295 +{
  296 + unsigned long *csd_raw = (unsigned long *)csd;
  297 + printf("CSD data: %08lx %08lx %08lx %08lx\n",
  298 + csd_raw[0], csd_raw[1], csd_raw[2], csd_raw[3]);
  299 + printf("CSD structure version: 1.%u\n", csd->csd_structure);
  300 + printf("MMC System Spec version: %u\n", csd->spec_vers);
  301 + printf("Card command classes: %03x\n", csd->ccc);
  302 + printf("Read block length: %u\n", 1 << csd->read_bl_len);
  303 + if (csd->read_bl_partial)
  304 + puts("Supports partial reads\n");
  305 + else
  306 + puts("Does not support partial reads\n");
  307 + printf("Write block length: %u\n", 1 << csd->write_bl_len);
  308 + if (csd->write_bl_partial)
  309 + puts("Supports partial writes\n");
  310 + else
  311 + puts("Does not support partial writes\n");
  312 + if (csd->wp_grp_enable)
  313 + printf("Supports group WP: %u\n", csd->wp_grp_size + 1);
  314 + else
  315 + puts("Does not support group WP\n");
  316 + printf("Card capacity: %u bytes\n",
  317 + (csd->c_size + 1) * (1 << (csd->c_size_mult + 2)) *
  318 + (1 << csd->read_bl_len));
  319 + printf("File format: %u/%u\n",
  320 + csd->file_format_grp, csd->file_format);
  321 + puts("Write protection: ");
  322 + if (csd->perm_write_protect)
  323 + puts(" permanent");
  324 + if (csd->tmp_write_protect)
  325 + puts(" temporary");
  326 + putc('\n');
  327 +}
  328 +
  329 +static int mmc_idle_cards(void)
  330 +{
  331 + int ret;
  332 +
  333 + /* Reset and initialize all cards */
  334 + ret = mmc_cmd(MMC_CMD_GO_IDLE_STATE, 0, NULL, 0);
  335 + if (ret)
  336 + return ret;
  337 +
  338 + /* Keep the bus idle for 74 clock cycles */
  339 + return mmc_cmd(0, 0, NULL, INIT_CMD);
  340 +}
  341 +
  342 +static int sd_init_card(struct mmc_cid *cid, int verbose)
  343 +{
  344 + unsigned long resp[4];
  345 + int i, ret = 0;
  346 +
  347 + mmc_idle_cards();
  348 + for (i = 0; i < 1000; i++) {
  349 + ret = mmc_acmd(MMC_ACMD_SD_SEND_OP_COND, CFG_MMC_OP_COND,
  350 + resp, R3 | NID);
  351 + if (ret || (resp[0] & 0x80000000))
  352 + break;
  353 + ret = -ETIMEDOUT;
  354 + }
  355 +
  356 + if (ret)
  357 + return ret;
  358 +
  359 + ret = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, resp, R2 | NID);
  360 + if (ret)
  361 + return ret;
  362 + sd_parse_cid(cid, resp);
  363 + if (verbose)
  364 + mmc_dump_cid(cid);
  365 +
  366 + /* Get RCA of the card that responded */
  367 + ret = mmc_cmd(MMC_CMD_SD_SEND_RELATIVE_ADDR, 0, resp, R6 | NCR);
  368 + if (ret)
  369 + return ret;
  370 +
  371 + mmc_rca = resp[0] >> 16;
  372 + if (verbose)
  373 + printf("SD Card detected (RCA %u)\n", mmc_rca);
  374 + return 0;
  375 +}
  376 +
  377 +static int mmc_init_card(struct mmc_cid *cid, int verbose)
  378 +{
  379 + unsigned long resp[4];
  380 + int i, ret = 0;
  381 +
  382 + mmc_idle_cards();
  383 + for (i = 0; i < 1000; i++) {
  384 + ret = mmc_cmd(MMC_CMD_SEND_OP_COND, CFG_MMC_OP_COND, resp,
  385 + R3 | NID | OPEN_DRAIN);
  386 + if (ret || (resp[0] & 0x80000000))
  387 + break;
  388 + ret = -ETIMEDOUT;
  389 + }
  390 +
  391 + if (ret)
  392 + return ret;
  393 +
  394 + /* Get CID of all cards. FIXME: Support more than one card */
  395 + ret = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, resp, R2 | NID | OPEN_DRAIN);
  396 + if (ret)
  397 + return ret;
  398 + mmc_parse_cid(cid, resp);
  399 + if (verbose)
  400 + mmc_dump_cid(cid);
  401 +
  402 + /* Set Relative Address of the card that responded */
  403 + ret = mmc_cmd(MMC_CMD_SET_RELATIVE_ADDR, mmc_rca << 16, resp,
  404 + R1 | NCR | OPEN_DRAIN);
  405 + return ret;
  406 +}
  407 +
  408 +int mmc_init(int verbose)
  409 +{
  410 + struct mmc_cid cid;
  411 + struct mmc_csd csd;
  412 + int ret;
  413 +
  414 + /* Initialize controller */
  415 + mmci_writel(CR, MMCI_BIT(SWRST));
  416 + mmci_writel(CR, MMCI_BIT(MCIEN));
  417 + mmci_writel(DTOR, 0x5f);
  418 + mmci_writel(IDR, ~0UL);
  419 + mci_set_mode(CFG_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
  420 +
  421 + ret = sd_init_card(&cid, verbose);
  422 + if (ret) {
  423 + mmc_rca = MMC_DEFAULT_RCA;
  424 + ret = mmc_init_card(&cid, verbose);
  425 + }
  426 + if (ret)
  427 + return ret;
  428 +
  429 + /* Get CSD from the card */
  430 + ret = mmc_cmd(MMC_CMD_SEND_CSD, mmc_rca << 16, &csd, R2 | NCR);
  431 + if (ret)
  432 + return ret;
  433 + if (verbose)
  434 + mmc_dump_csd(&csd);
  435 +
  436 + /* Initialize the blockdev structure */
  437 + mmc_blkdev.if_type = IF_TYPE_MMC;
  438 + mmc_blkdev.part_type = PART_TYPE_DOS;
  439 + mmc_blkdev.block_read = mmc_bread;
  440 + sprintf((char *)mmc_blkdev.vendor,
  441 + "Man %02x%04x Snr %08x",
  442 + cid.mid, cid.oid, cid.psn);
  443 + strncpy((char *)mmc_blkdev.product, cid.pnm,
  444 + sizeof(mmc_blkdev.product));
  445 + sprintf((char *)mmc_blkdev.revision, "%x %x",
  446 + cid.prv >> 4, cid.prv & 0x0f);
  447 + mmc_blkdev.blksz = 1 << csd.read_bl_len;
  448 + mmc_blkdev.lba = (csd.c_size + 1) * (1 << (csd.c_size_mult + 2));
  449 +
  450 + mci_set_mode(CFG_MMC_CLK_PP, mmc_blkdev.blksz);
  451 +
  452 +#if 0
  453 + if (fat_register_device(&mmc_blkdev, 1))
  454 + printf("Could not register MMC fat device\n");
  455 +#else
  456 + init_part(&mmc_blkdev);
  457 +#endif
  458 +
  459 + return 0;
  460 +}
  461 +
  462 +int mmc_read(ulong src, uchar *dst, int size)
  463 +{
  464 + return -ENOSYS;
  465 +}
  466 +
  467 +int mmc_write(uchar *src, ulong dst, int size)
  468 +{
  469 + return -ENOSYS;
  470 +}
  471 +
  472 +int mmc2info(ulong addr)
  473 +{
  474 + return 0;
  475 +}
  476 +
  477 +#endif /* CONFIG_MMC */
cpu/at32ap/atmel_mci.h
  1 +/*
  2 + * Copyright (C) 2005-2006 Atmel Corporation
  3 + *
  4 + * See file CREDITS for list of people who contributed to this
  5 + * project.
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License as
  9 + * published by the Free Software Foundation; either version 2 of
  10 + * the License, or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 + * MA 02111-1307 USA
  21 + */
  22 +#ifndef __CPU_AT32AP_ATMEL_MCI_H__
  23 +#define __CPU_AT32AP_ATMEL_MCI_H__
  24 +
  25 +/* Atmel MultiMedia Card Interface (MCI) registers */
  26 +#define MMCI_CR 0x0000
  27 +#define MMCI_MR 0x0004
  28 +#define MMCI_DTOR 0x0008
  29 +#define MMCI_SDCR 0x000c
  30 +#define MMCI_ARGR 0x0010
  31 +#define MMCI_CMDR 0x0014
  32 +#define MMCI_RSPR 0x0020
  33 +#define MMCI_RSPR1 0x0024
  34 +#define MMCI_RSPR2 0x0028
  35 +#define MMCI_RSPR3 0x002c
  36 +#define MMCI_RDR 0x0030
  37 +#define MMCI_TDR 0x0034
  38 +#define MMCI_SR 0x0040
  39 +#define MMCI_IER 0x0044
  40 +#define MMCI_IDR 0x0048
  41 +#define MMCI_IMR 0x004c
  42 +
  43 +/* Bitfields in CR */
  44 +#define MMCI_MCIEN_OFFSET 0
  45 +#define MMCI_MCIEN_SIZE 1
  46 +#define MMCI_MCIDIS_OFFSET 1
  47 +#define MMCI_MCIDIS_SIZE 1
  48 +#define MMCI_PWSEN_OFFSET 2
  49 +#define MMCI_PWSEN_SIZE 1
  50 +#define MMCI_PWSDIS_OFFSET 3
  51 +#define MMCI_PWSDIS_SIZE 1
  52 +#define MMCI_SWRST_OFFSET 7
  53 +#define MMCI_SWRST_SIZE 1
  54 +
  55 +/* Bitfields in MR */
  56 +#define MMCI_CLKDIV_OFFSET 0
  57 +#define MMCI_CLKDIV_SIZE 8
  58 +#define MMCI_PWSDIV_OFFSET 8
  59 +#define MMCI_PWSDIV_SIZE 3
  60 +#define MMCI_PDCPADV_OFFSET 14
  61 +#define MMCI_PDCPADV_SIZE 1
  62 +#define MMCI_PDCMODE_OFFSET 15
  63 +#define MMCI_PDCMODE_SIZE 1
  64 +#define MMCI_BLKLEN_OFFSET 16
  65 +#define MMCI_BLKLEN_SIZE 16
  66 +
  67 +/* Bitfields in DTOR */
  68 +#define MMCI_DTOCYC_OFFSET 0
  69 +#define MMCI_DTOCYC_SIZE 4
  70 +#define MMCI_DTOMUL_OFFSET 4
  71 +#define MMCI_DTOMUL_SIZE 3
  72 +
  73 +/* Bitfields in SDCR */
  74 +#define MMCI_SCDSEL_OFFSET 0
  75 +#define MMCI_SCDSEL_SIZE 4
  76 +#define MMCI_SCDBUS_OFFSET 7
  77 +#define MMCI_SCDBUS_SIZE 1
  78 +
  79 +/* Bitfields in ARGR */
  80 +#define MMCI_ARG_OFFSET 0
  81 +#define MMCI_ARG_SIZE 32
  82 +
  83 +/* Bitfields in CMDR */
  84 +#define MMCI_CMDNB_OFFSET 0
  85 +#define MMCI_CMDNB_SIZE 6
  86 +#define MMCI_RSPTYP_OFFSET 6
  87 +#define MMCI_RSPTYP_SIZE 2
  88 +#define MMCI_SPCMD_OFFSET 8
  89 +#define MMCI_SPCMD_SIZE 3
  90 +#define MMCI_OPDCMD_OFFSET 11
  91 +#define MMCI_OPDCMD_SIZE 1
  92 +#define MMCI_MAXLAT_OFFSET 12
  93 +#define MMCI_MAXLAT_SIZE 1
  94 +#define MMCI_TRCMD_OFFSET 16
  95 +#define MMCI_TRCMD_SIZE 2
  96 +#define MMCI_TRDIR_OFFSET 18
  97 +#define MMCI_TRDIR_SIZE 1
  98 +#define MMCI_TRTYP_OFFSET 19
  99 +#define MMCI_TRTYP_SIZE 2
  100 +
  101 +/* Bitfields in RSPRx */
  102 +#define MMCI_RSP_OFFSET 0
  103 +#define MMCI_RSP_SIZE 32
  104 +
  105 +/* Bitfields in SR/IER/IDR/IMR */
  106 +#define MMCI_CMDRDY_OFFSET 0
  107 +#define MMCI_CMDRDY_SIZE 1
  108 +#define MMCI_RXRDY_OFFSET 1
  109 +#define MMCI_RXRDY_SIZE 1
  110 +#define MMCI_TXRDY_OFFSET 2
  111 +#define MMCI_TXRDY_SIZE 1
  112 +#define MMCI_BLKE_OFFSET 3
  113 +#define MMCI_BLKE_SIZE 1
  114 +#define MMCI_DTIP_OFFSET 4
  115 +#define MMCI_DTIP_SIZE 1
  116 +#define MMCI_NOTBUSY_OFFSET 5
  117 +#define MMCI_NOTBUSY_SIZE 1
  118 +#define MMCI_ENDRX_OFFSET 6
  119 +#define MMCI_ENDRX_SIZE 1
  120 +#define MMCI_ENDTX_OFFSET 7
  121 +#define MMCI_ENDTX_SIZE 1
  122 +#define MMCI_RXBUFF_OFFSET 14
  123 +#define MMCI_RXBUFF_SIZE 1
  124 +#define MMCI_TXBUFE_OFFSET 15
  125 +#define MMCI_TXBUFE_SIZE 1
  126 +#define MMCI_RINDE_OFFSET 16
  127 +#define MMCI_RINDE_SIZE 1
  128 +#define MMCI_RDIRE_OFFSET 17
  129 +#define MMCI_RDIRE_SIZE 1
  130 +#define MMCI_RCRCE_OFFSET 18
  131 +#define MMCI_RCRCE_SIZE 1
  132 +#define MMCI_RENDE_OFFSET 19
  133 +#define MMCI_RENDE_SIZE 1
  134 +#define MMCI_RTOE_OFFSET 20
  135 +#define MMCI_RTOE_SIZE 1
  136 +#define MMCI_DCRCE_OFFSET 21
  137 +#define MMCI_DCRCE_SIZE 1
  138 +#define MMCI_DTOE_OFFSET 22
  139 +#define MMCI_DTOE_SIZE 1
  140 +#define MMCI_OVRE_OFFSET 30
  141 +#define MMCI_OVRE_SIZE 1
  142 +#define MMCI_UNRE_OFFSET 31
  143 +#define MMCI_UNRE_SIZE 1
  144 +
  145 +/* Constants for DTOMUL */
  146 +#define MMCI_DTOMUL_1_CYCLE 0
  147 +#define MMCI_DTOMUL_16_CYCLES 1
  148 +#define MMCI_DTOMUL_128_CYCLES 2
  149 +#define MMCI_DTOMUL_256_CYCLES 3
  150 +#define MMCI_DTOMUL_1024_CYCLES 4
  151 +#define MMCI_DTOMUL_4096_CYCLES 5
  152 +#define MMCI_DTOMUL_65536_CYCLES 6
  153 +#define MMCI_DTOMUL_1048576_CYCLES 7
  154 +
  155 +/* Constants for RSPTYP */
  156 +#define MMCI_RSPTYP_NO_RESP 0
  157 +#define MMCI_RSPTYP_48_BIT_RESP 1
  158 +#define MMCI_RSPTYP_136_BIT_RESP 2
  159 +
  160 +/* Constants for SPCMD */
  161 +#define MMCI_SPCMD_NO_SPEC_CMD 0
  162 +#define MMCI_SPCMD_INIT_CMD 1
  163 +#define MMCI_SPCMD_SYNC_CMD 2
  164 +#define MMCI_SPCMD_INT_CMD 4
  165 +#define MMCI_SPCMD_INT_RESP 5
  166 +
  167 +/* Constants for TRCMD */
  168 +#define MMCI_TRCMD_NO_TRANS 0
  169 +#define MMCI_TRCMD_START_TRANS 1
  170 +#define MMCI_TRCMD_STOP_TRANS 2
  171 +
  172 +/* Constants for TRTYP */
  173 +#define MMCI_TRTYP_BLOCK 0
  174 +#define MMCI_TRTYP_MULTI_BLOCK 1
  175 +#define MMCI_TRTYP_STREAM 2
  176 +
  177 +/* Bit manipulation macros */
  178 +#define MMCI_BIT(name) \
  179 + (1 << MMCI_##name##_OFFSET)
  180 +#define MMCI_BF(name,value) \
  181 + (((value) & ((1 << MMCI_##name##_SIZE) - 1)) \
  182 + << MMCI_##name##_OFFSET)
  183 +#define MMCI_BFEXT(name,value) \
  184 + (((value) >> MMCI_##name##_OFFSET)\
  185 + & ((1 << MMCI_##name##_SIZE) - 1))
  186 +#define MMCI_BFINS(name,value,old) \
  187 + (((old) & ~(((1 << MMCI_##name##_SIZE) - 1) \
  188 + << MMCI_##name##_OFFSET)) \
  189 + | MMCI_BF(name,value))
  190 +
  191 +/* Register access macros */
  192 +#define mmci_readl(reg) \
  193 + readl((void *)MMCI_BASE + MMCI_##reg)
  194 +#define mmci_writel(reg,value) \
  195 + writel((value), (void *)MMCI_BASE + MMCI_##reg)
  196 +
  197 +#endif /* __CPU_AT32AP_ATMEL_MCI_H__ */
include/asm-avr32/arch-at32ap7000/mmc.h
  1 +/*
  2 + * Copyright (C) 2004-2006 Atmel Corporation
  3 + *
  4 + * See file CREDITS for list of people who contributed to this
  5 + * project.
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License as
  9 + * published by the Free Software Foundation; either version 2 of
  10 + * the License, or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 + * MA 02111-1307 USA
  21 + */
  22 +#ifndef __ASM_AVR32_MMC_H
  23 +#define __ASM_AVR32_MMC_H
  24 +
  25 +struct mmc_cid {
  26 + unsigned long psn;
  27 + unsigned short oid;
  28 + unsigned char mid;
  29 + unsigned char prv;
  30 + unsigned char mdt;
  31 + char pnm[7];
  32 +};
  33 +
  34 +struct mmc_csd
  35 +{
  36 + u8 csd_structure:2,
  37 + spec_vers:4,
  38 + rsvd1:2;
  39 + u8 taac;
  40 + u8 nsac;
  41 + u8 tran_speed;
  42 + u16 ccc:12,
  43 + read_bl_len:4;
  44 + u64 read_bl_partial:1,
  45 + write_blk_misalign:1,
  46 + read_blk_misalign:1,
  47 + dsr_imp:1,
  48 + rsvd2:2,
  49 + c_size:12,
  50 + vdd_r_curr_min:3,
  51 + vdd_r_curr_max:3,
  52 + vdd_w_curr_min:3,
  53 + vdd_w_curr_max:3,
  54 + c_size_mult:3,
  55 + sector_size:5,
  56 + erase_grp_size:5,
  57 + wp_grp_size:5,
  58 + wp_grp_enable:1,
  59 + default_ecc:2,
  60 + r2w_factor:3,
  61 + write_bl_len:4,
  62 + write_bl_partial:1,
  63 + rsvd3:5;
  64 + u8 file_format_grp:1,
  65 + copy:1,
  66 + perm_write_protect:1,
  67 + tmp_write_protect:1,
  68 + file_format:2,
  69 + ecc:2;
  70 + u8 crc:7;
  71 + u8 one:1;
  72 +};
  73 +
  74 +/* MMC Command numbers */
  75 +#define MMC_CMD_GO_IDLE_STATE 0
  76 +#define MMC_CMD_SEND_OP_COND 1
  77 +#define MMC_CMD_ALL_SEND_CID 2
  78 +#define MMC_CMD_SET_RELATIVE_ADDR 3
  79 +#define MMC_CMD_SD_SEND_RELATIVE_ADDR 3
  80 +#define MMC_CMD_SET_DSR 4
  81 +#define MMC_CMD_SELECT_CARD 7
  82 +#define MMC_CMD_SEND_CSD 9
  83 +#define MMC_CMD_SEND_CID 10
  84 +#define MMC_CMD_SEND_STATUS 13
  85 +#define MMC_CMD_SET_BLOCKLEN 16
  86 +#define MMC_CMD_READ_SINGLE_BLOCK 17
  87 +#define MMC_CMD_READ_MULTIPLE_BLOCK 18
  88 +#define MMC_CMD_WRITE_BLOCK 24
  89 +#define MMC_CMD_APP_CMD 55
  90 +
  91 +#define MMC_ACMD_SD_SEND_OP_COND 41
  92 +
  93 +#define R1_ILLEGAL_COMMAND (1 << 22)
  94 +#define R1_APP_CMD (1 << 5)
  95 +
  96 +#endif /* __ASM_AVR32_MMC_H */