Commit d52ebf102209cc1ad460c79b9498b2c8936ba413

Authored by Thomas Chou
Committed by Andy Fleming
1 parent 5f837c2c0e

mmc: add generic mmc spi driver

This patch supports mmc/sd card with spi interface. It is based on
the generic mmc framework. It works with SDHC and supports multi
blocks read/write.

The crc checksum on data packet is enabled with the def,

There is a subcomamnd "mmc_spi" to setup spi bus and cs at run time.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
Signed-off-by: Andy Fleming <afleming@freescale.com>

Showing 6 changed files with 448 additions and 20 deletions Side-by-side Diff

... ... @@ -118,6 +118,7 @@
118 118 COBJS-$(CONFIG_CMD_MII) += cmd_mii.o
119 119 COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o
120 120 COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
  121 +COBJS-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o
121 122 COBJS-$(CONFIG_MP) += cmd_mp.o
122 123 COBJS-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o
123 124 COBJS-$(CONFIG_CMD_NAND) += cmd_nand.o
common/cmd_mmc_spi.c
  1 +/*
  2 + * Command for mmc_spi setup.
  3 + *
  4 + * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
  5 + * Licensed under the GPL-2 or later.
  6 + */
  7 +
  8 +#include <common.h>
  9 +#include <mmc.h>
  10 +#include <spi.h>
  11 +
  12 +#ifndef CONFIG_MMC_SPI_BUS
  13 +# define CONFIG_MMC_SPI_BUS 0
  14 +#endif
  15 +#ifndef CONFIG_MMC_SPI_CS
  16 +# define CONFIG_MMC_SPI_CS 1
  17 +#endif
  18 +/* in SPI mode, MMC speed limit is 20MHz, while SD speed limit is 25MHz */
  19 +#ifndef CONFIG_MMC_SPI_SPEED
  20 +# define CONFIG_MMC_SPI_SPEED 25000000
  21 +#endif
  22 +/* MMC and SD specs only seem to care that sampling is on the
  23 + * rising edge ... meaning SPI modes 0 or 3. So either SPI mode
  24 + * should be legit. We'll use mode 0 since the steady state is 0,
  25 + * which is appropriate for hotplugging, unless the platform data
  26 + * specify mode 3 (if hardware is not compatible to mode 0).
  27 + */
  28 +#ifndef CONFIG_MMC_SPI_MODE
  29 +# define CONFIG_MMC_SPI_MODE SPI_MODE_0
  30 +#endif
  31 +
  32 +static int do_mmc_spi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  33 +{
  34 + uint bus = CONFIG_MMC_SPI_BUS;
  35 + uint cs = CONFIG_MMC_SPI_CS;
  36 + uint speed = CONFIG_MMC_SPI_SPEED;
  37 + uint mode = CONFIG_MMC_SPI_MODE;
  38 + char *endp;
  39 + struct mmc *mmc;
  40 +
  41 + if (argc < 2)
  42 + goto usage;
  43 +
  44 + cs = simple_strtoul(argv[1], &endp, 0);
  45 + if (*argv[1] == 0 || (*endp != 0 && *endp != ':'))
  46 + goto usage;
  47 + if (*endp == ':') {
  48 + if (endp[1] == 0)
  49 + goto usage;
  50 + bus = cs;
  51 + cs = simple_strtoul(endp + 1, &endp, 0);
  52 + if (*endp != 0)
  53 + goto usage;
  54 + }
  55 + if (argc >= 3) {
  56 + speed = simple_strtoul(argv[2], &endp, 0);
  57 + if (*argv[2] == 0 || *endp != 0)
  58 + goto usage;
  59 + }
  60 + if (argc >= 4) {
  61 + mode = simple_strtoul(argv[3], &endp, 16);
  62 + if (*argv[3] == 0 || *endp != 0)
  63 + goto usage;
  64 + }
  65 + if (!spi_cs_is_valid(bus, cs)) {
  66 + printf("Invalid SPI bus %u cs %u\n", bus, cs);
  67 + return 1;
  68 + }
  69 +
  70 + mmc = mmc_spi_init(bus, cs, speed, mode);
  71 + if (!mmc) {
  72 + printf("Failed to create MMC Device\n");
  73 + return 1;
  74 + }
  75 + printf("%s: %d at %u:%u hz %u mode %u\n", mmc->name, mmc->block_dev.dev,
  76 + bus, cs, speed, mode);
  77 + return 0;
  78 +
  79 +usage:
  80 + cmd_usage(cmdtp);
  81 + return 1;
  82 +}
  83 +
  84 +U_BOOT_CMD(
  85 + mmc_spi, 4, 0, do_mmc_spi,
  86 + "mmc_spi setup",
  87 + "[bus:]cs [hz] [mode] - setup mmc_spi device"
  88 +);
drivers/mmc/Makefile
... ... @@ -31,6 +31,7 @@
31 31 COBJS-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
32 32 COBJS-$(CONFIG_GENERIC_MMC) += mmc.o
33 33 COBJS-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
  34 +COBJS-$(CONFIG_MMC_SPI) += mmc_spi.o
34 35 COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o
35 36 COBJS-$(CONFIG_OMAP3_MMC) += omap3_mmc.o
36 37 COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
... ... @@ -117,7 +117,10 @@
117 117 return 0;
118 118 }
119 119  
120   - if (blkcnt > 1) {
  120 + /* SPI multiblock writes terminate using a special
  121 + * token, not a STOP_TRANSMISSION request.
  122 + */
  123 + if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
121 124 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
122 125 cmd.cmdarg = 0;
123 126 cmd.resp_type = MMC_RSP_R1b;
... ... @@ -279,7 +282,8 @@
279 282 * how to manage low voltages SD card is not yet
280 283 * specified.
281 284 */
282   - cmd.cmdarg = mmc->voltages & 0xff8000;
  285 + cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
  286 + (mmc->voltages & 0xff8000);
283 287  
284 288 if (mmc->version == SD_VERSION_2)
285 289 cmd.cmdarg |= OCR_HCS;
... ... @@ -298,6 +302,18 @@
298 302 if (mmc->version != SD_VERSION_2)
299 303 mmc->version = SD_VERSION_1_0;
300 304  
  305 + if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
  306 + cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
  307 + cmd.resp_type = MMC_RSP_R3;
  308 + cmd.cmdarg = 0;
  309 + cmd.flags = 0;
  310 +
  311 + err = mmc_send_cmd(mmc, &cmd, NULL);
  312 +
  313 + if (err)
  314 + return err;
  315 + }
  316 +
301 317 mmc->ocr = cmd.response[0];
302 318  
303 319 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
... ... @@ -318,7 +334,8 @@
318 334 do {
319 335 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
320 336 cmd.resp_type = MMC_RSP_R3;
321   - cmd.cmdarg = OCR_HCS | mmc->voltages;
  337 + cmd.cmdarg = OCR_HCS | (mmc_host_is_spi(mmc) ? 0 :
  338 + mmc->voltages);
322 339 cmd.flags = 0;
323 340  
324 341 err = mmc_send_cmd(mmc, &cmd, NULL);
... ... @@ -332,6 +349,18 @@
332 349 if (timeout <= 0)
333 350 return UNUSABLE_ERR;
334 351  
  352 + if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
  353 + cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
  354 + cmd.resp_type = MMC_RSP_R3;
  355 + cmd.cmdarg = 0;
  356 + cmd.flags = 0;
  357 +
  358 + err = mmc_send_cmd(mmc, &cmd, NULL);
  359 +
  360 + if (err)
  361 + return err;
  362 + }
  363 +
335 364 mmc->version = MMC_VERSION_UNKNOWN;
336 365 mmc->ocr = cmd.response[0];
337 366  
... ... @@ -387,6 +416,9 @@
387 416  
388 417 mmc->card_caps = 0;
389 418  
  419 + if (mmc_host_is_spi(mmc))
  420 + return 0;
  421 +
390 422 /* Only version 4 supports high-speed */
391 423 if (mmc->version < MMC_VERSION_4)
392 424 return 0;
... ... @@ -460,6 +492,9 @@
460 492  
461 493 mmc->card_caps = 0;
462 494  
  495 + if (mmc_host_is_spi(mmc))
  496 + return 0;
  497 +
463 498 /* Read the SCR to find out if this card supports higher speeds */
464 499 cmd.cmdidx = MMC_CMD_APP_CMD;
465 500 cmd.resp_type = MMC_RSP_R1;
466 501  
... ... @@ -610,8 +645,22 @@
610 645 struct mmc_cmd cmd;
611 646 char ext_csd[512];
612 647  
  648 +#ifdef CONFIG_MMC_SPI_CRC_ON
  649 + if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
  650 + cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
  651 + cmd.resp_type = MMC_RSP_R1;
  652 + cmd.cmdarg = 1;
  653 + cmd.flags = 0;
  654 + err = mmc_send_cmd(mmc, &cmd, NULL);
  655 +
  656 + if (err)
  657 + return err;
  658 + }
  659 +#endif
  660 +
613 661 /* Put the Card in Identify Mode */
614   - cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
  662 + cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
  663 + MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
615 664 cmd.resp_type = MMC_RSP_R2;
616 665 cmd.cmdarg = 0;
617 666 cmd.flags = 0;
618 667  
619 668  
620 669  
... ... @@ -628,18 +677,20 @@
628 677 * For SD cards, get the Relatvie Address.
629 678 * This also puts the cards into Standby State
630 679 */
631   - cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
632   - cmd.cmdarg = mmc->rca << 16;
633   - cmd.resp_type = MMC_RSP_R6;
634   - cmd.flags = 0;
  680 + if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
  681 + cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
  682 + cmd.cmdarg = mmc->rca << 16;
  683 + cmd.resp_type = MMC_RSP_R6;
  684 + cmd.flags = 0;
635 685  
636   - err = mmc_send_cmd(mmc, &cmd, NULL);
  686 + err = mmc_send_cmd(mmc, &cmd, NULL);
637 687  
638   - if (err)
639   - return err;
  688 + if (err)
  689 + return err;
640 690  
641   - if (IS_SD(mmc))
642   - mmc->rca = (cmd.response[0] >> 16) & 0xffff;
  691 + if (IS_SD(mmc))
  692 + mmc->rca = (cmd.response[0] >> 16) & 0xffff;
  693 + }
643 694  
644 695 /* Get the Card-Specific Data */
645 696 cmd.cmdidx = MMC_CMD_SEND_CSD;
646 697  
... ... @@ -715,14 +766,16 @@
715 766 mmc->write_bl_len = 512;
716 767  
717 768 /* Select the card, and put it into Transfer Mode */
718   - cmd.cmdidx = MMC_CMD_SELECT_CARD;
719   - cmd.resp_type = MMC_RSP_R1b;
720   - cmd.cmdarg = mmc->rca << 16;
721   - cmd.flags = 0;
722   - err = mmc_send_cmd(mmc, &cmd, NULL);
  769 + if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
  770 + cmd.cmdidx = MMC_CMD_SELECT_CARD;
  771 + cmd.resp_type = MMC_RSP_R1b;
  772 + cmd.cmdarg = mmc->rca << 16;
  773 + cmd.flags = 0;
  774 + err = mmc_send_cmd(mmc, &cmd, NULL);
723 775  
724   - if (err)
725   - return err;
  776 + if (err)
  777 + return err;
  778 + }
726 779  
727 780 if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
728 781 /* check ext_csd version and capacity */
drivers/mmc/mmc_spi.c
  1 +/*
  2 + * generic mmc spi driver
  3 + *
  4 + * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
  5 + * Licensed under the GPL-2 or later.
  6 + */
  7 +#include <common.h>
  8 +#include <malloc.h>
  9 +#include <part.h>
  10 +#include <mmc.h>
  11 +#include <spi.h>
  12 +#include <crc.h>
  13 +#include <linux/crc7.h>
  14 +#include <linux/byteorder/swab.h>
  15 +
  16 +/* MMC/SD in SPI mode reports R1 status always */
  17 +#define R1_SPI_IDLE (1 << 0)
  18 +#define R1_SPI_ERASE_RESET (1 << 1)
  19 +#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
  20 +#define R1_SPI_COM_CRC (1 << 3)
  21 +#define R1_SPI_ERASE_SEQ (1 << 4)
  22 +#define R1_SPI_ADDRESS (1 << 5)
  23 +#define R1_SPI_PARAMETER (1 << 6)
  24 +/* R1 bit 7 is always zero, reuse this bit for error */
  25 +#define R1_SPI_ERROR (1 << 7)
  26 +
  27 +/* Response tokens used to ack each block written: */
  28 +#define SPI_MMC_RESPONSE_CODE(x) ((x) & 0x1f)
  29 +#define SPI_RESPONSE_ACCEPTED ((2 << 1)|1)
  30 +#define SPI_RESPONSE_CRC_ERR ((5 << 1)|1)
  31 +#define SPI_RESPONSE_WRITE_ERR ((6 << 1)|1)
  32 +
  33 +/* Read and write blocks start with these tokens and end with crc;
  34 + * on error, read tokens act like a subset of R2_SPI_* values.
  35 + */
  36 +#define SPI_TOKEN_SINGLE 0xfe /* single block r/w, multiblock read */
  37 +#define SPI_TOKEN_MULTI_WRITE 0xfc /* multiblock write */
  38 +#define SPI_TOKEN_STOP_TRAN 0xfd /* terminate multiblock write */
  39 +
  40 +/* MMC SPI commands start with a start bit "0" and a transmit bit "1" */
  41 +#define MMC_SPI_CMD(x) (0x40 | (x & 0x3f))
  42 +
  43 +/* bus capability */
  44 +#define MMC_SPI_VOLTAGE (MMC_VDD_32_33 | MMC_VDD_33_34)
  45 +#define MMC_SPI_MIN_CLOCK 400000 /* 400KHz to meet MMC spec */
  46 +
  47 +/* timeout value */
  48 +#define CTOUT 8
  49 +#define RTOUT 3000000 /* 1 sec */
  50 +#define WTOUT 3000000 /* 1 sec */
  51 +
  52 +static uint mmc_spi_sendcmd(struct mmc *mmc, ushort cmdidx, u32 cmdarg)
  53 +{
  54 + struct spi_slave *spi = mmc->priv;
  55 + u8 cmdo[7];
  56 + u8 r1;
  57 + int i;
  58 + cmdo[0] = 0xff;
  59 + cmdo[1] = MMC_SPI_CMD(cmdidx);
  60 + cmdo[2] = cmdarg >> 24;
  61 + cmdo[3] = cmdarg >> 16;
  62 + cmdo[4] = cmdarg >> 8;
  63 + cmdo[5] = cmdarg;
  64 + cmdo[6] = (crc7(0, &cmdo[1], 5) << 1) | 0x01;
  65 + spi_xfer(spi, sizeof(cmdo) * 8, cmdo, NULL, 0);
  66 + for (i = 0; i < CTOUT; i++) {
  67 + spi_xfer(spi, 1 * 8, NULL, &r1, 0);
  68 + if (i && (r1 & 0x80) == 0) /* r1 response */
  69 + break;
  70 + }
  71 + debug("%s:cmd%d resp%d %x\n", __func__, cmdidx, i, r1);
  72 + return r1;
  73 +}
  74 +
  75 +static uint mmc_spi_readdata(struct mmc *mmc, void *xbuf,
  76 + u32 bcnt, u32 bsize)
  77 +{
  78 + struct spi_slave *spi = mmc->priv;
  79 + u8 *buf = xbuf;
  80 + u8 r1;
  81 + u16 crc;
  82 + int i;
  83 + while (bcnt--) {
  84 + for (i = 0; i < RTOUT; i++) {
  85 + spi_xfer(spi, 1 * 8, NULL, &r1, 0);
  86 + if (r1 != 0xff) /* data token */
  87 + break;
  88 + }
  89 + debug("%s:tok%d %x\n", __func__, i, r1);
  90 + if (r1 == SPI_TOKEN_SINGLE) {
  91 + spi_xfer(spi, bsize * 8, NULL, buf, 0);
  92 + spi_xfer(spi, 2 * 8, NULL, &crc, 0);
  93 +#ifdef CONFIG_MMC_SPI_CRC_ON
  94 + if (swab16(cyg_crc16(buf, bsize)) != crc) {
  95 + debug("%s: CRC error\n", mmc->name);
  96 + r1 = R1_SPI_COM_CRC;
  97 + break;
  98 + }
  99 +#endif
  100 + r1 = 0;
  101 + } else {
  102 + r1 = R1_SPI_ERROR;
  103 + break;
  104 + }
  105 + buf += bsize;
  106 + }
  107 + return r1;
  108 +}
  109 +
  110 +static uint mmc_spi_writedata(struct mmc *mmc, const void *xbuf,
  111 + u32 bcnt, u32 bsize, int multi)
  112 +{
  113 + struct spi_slave *spi = mmc->priv;
  114 + const u8 *buf = xbuf;
  115 + u8 r1;
  116 + u16 crc;
  117 + u8 tok[2];
  118 + int i;
  119 + tok[0] = 0xff;
  120 + tok[1] = multi ? SPI_TOKEN_MULTI_WRITE : SPI_TOKEN_SINGLE;
  121 + while (bcnt--) {
  122 +#ifdef CONFIG_MMC_SPI_CRC_ON
  123 + crc = swab16(cyg_crc16((u8 *)buf, bsize));
  124 +#endif
  125 + spi_xfer(spi, 2 * 8, tok, NULL, 0);
  126 + spi_xfer(spi, bsize * 8, buf, NULL, 0);
  127 + spi_xfer(spi, 2 * 8, &crc, NULL, 0);
  128 + for (i = 0; i < CTOUT; i++) {
  129 + spi_xfer(spi, 1 * 8, NULL, &r1, 0);
  130 + if ((r1 & 0x10) == 0) /* response token */
  131 + break;
  132 + }
  133 + debug("%s:tok%d %x\n", __func__, i, r1);
  134 + if (SPI_MMC_RESPONSE_CODE(r1) == SPI_RESPONSE_ACCEPTED) {
  135 + for (i = 0; i < WTOUT; i++) { /* wait busy */
  136 + spi_xfer(spi, 1 * 8, NULL, &r1, 0);
  137 + if (i && r1 == 0xff) {
  138 + r1 = 0;
  139 + break;
  140 + }
  141 + }
  142 + if (i == WTOUT) {
  143 + debug("%s:wtout %x\n", __func__, r1);
  144 + r1 = R1_SPI_ERROR;
  145 + break;
  146 + }
  147 + } else {
  148 + debug("%s: err %x\n", __func__, r1);
  149 + r1 = R1_SPI_COM_CRC;
  150 + break;
  151 + }
  152 + buf += bsize;
  153 + }
  154 + if (multi && bcnt == -1) { /* stop multi write */
  155 + tok[1] = SPI_TOKEN_STOP_TRAN;
  156 + spi_xfer(spi, 2 * 8, tok, NULL, 0);
  157 + for (i = 0; i < WTOUT; i++) { /* wait busy */
  158 + spi_xfer(spi, 1 * 8, NULL, &r1, 0);
  159 + if (i && r1 == 0xff) {
  160 + r1 = 0;
  161 + break;
  162 + }
  163 + }
  164 + if (i == WTOUT) {
  165 + debug("%s:wstop %x\n", __func__, r1);
  166 + r1 = R1_SPI_ERROR;
  167 + }
  168 + }
  169 + return r1;
  170 +}
  171 +
  172 +static int mmc_spi_request(struct mmc *mmc, struct mmc_cmd *cmd,
  173 + struct mmc_data *data)
  174 +{
  175 + struct spi_slave *spi = mmc->priv;
  176 + u8 r1;
  177 + int i;
  178 + int ret = 0;
  179 + debug("%s:cmd%d %x %x %x\n", __func__,
  180 + cmd->cmdidx, cmd->resp_type, cmd->cmdarg, cmd->flags);
  181 + spi_claim_bus(spi);
  182 + spi_cs_activate(spi);
  183 + r1 = mmc_spi_sendcmd(mmc, cmd->cmdidx, cmd->cmdarg);
  184 + if (r1 == 0xff) { /* no response */
  185 + ret = NO_CARD_ERR;
  186 + goto done;
  187 + } else if (r1 & R1_SPI_COM_CRC) {
  188 + ret = COMM_ERR;
  189 + goto done;
  190 + } else if (r1 & ~R1_SPI_IDLE) { /* other errors */
  191 + ret = TIMEOUT;
  192 + goto done;
  193 + } else if (cmd->resp_type == MMC_RSP_R2) {
  194 + r1 = mmc_spi_readdata(mmc, cmd->response, 1, 16);
  195 + for (i = 0; i < 4; i++)
  196 + cmd->response[i] = swab32(cmd->response[i]);
  197 + debug("r128 %x %x %x %x\n", cmd->response[0], cmd->response[1],
  198 + cmd->response[2], cmd->response[3]);
  199 + } else if (!data) {
  200 + switch (cmd->cmdidx) {
  201 + case SD_CMD_APP_SEND_OP_COND:
  202 + case MMC_CMD_SEND_OP_COND:
  203 + cmd->response[0] = (r1 & R1_SPI_IDLE) ? 0 : OCR_BUSY;
  204 + break;
  205 + case SD_CMD_SEND_IF_COND:
  206 + case MMC_CMD_SPI_READ_OCR:
  207 + spi_xfer(spi, 4 * 8, NULL, cmd->response, 0);
  208 + cmd->response[0] = swab32(cmd->response[0]);
  209 + debug("r32 %x\n", cmd->response[0]);
  210 + break;
  211 + }
  212 + } else {
  213 + debug("%s:data %x %x %x\n", __func__,
  214 + data->flags, data->blocks, data->blocksize);
  215 + if (data->flags == MMC_DATA_READ)
  216 + r1 = mmc_spi_readdata(mmc, data->dest,
  217 + data->blocks, data->blocksize);
  218 + else if (data->flags == MMC_DATA_WRITE)
  219 + r1 = mmc_spi_writedata(mmc, data->src,
  220 + data->blocks, data->blocksize,
  221 + (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK));
  222 + if (r1 & R1_SPI_COM_CRC)
  223 + ret = COMM_ERR;
  224 + else if (r1) /* other errors */
  225 + ret = TIMEOUT;
  226 + }
  227 +done:
  228 + spi_cs_deactivate(spi);
  229 + spi_release_bus(spi);
  230 + return ret;
  231 +}
  232 +
  233 +static void mmc_spi_set_ios(struct mmc *mmc)
  234 +{
  235 + struct spi_slave *spi = mmc->priv;
  236 + debug("%s: clock %u\n", __func__, mmc->clock);
  237 + if (mmc->clock)
  238 + spi_set_speed(spi, mmc->clock);
  239 +}
  240 +
  241 +static int mmc_spi_init_p(struct mmc *mmc)
  242 +{
  243 + struct spi_slave *spi = mmc->priv;
  244 + mmc->clock = 0;
  245 + spi_set_speed(spi, MMC_SPI_MIN_CLOCK);
  246 + spi_claim_bus(spi);
  247 + /* cs deactivated for 100+ clock */
  248 + spi_xfer(spi, 18 * 8, NULL, NULL, 0);
  249 + spi_release_bus(spi);
  250 + return 0;
  251 +}
  252 +
  253 +struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
  254 +{
  255 + struct mmc *mmc;
  256 +
  257 + mmc = malloc(sizeof(*mmc));
  258 + if (!mmc)
  259 + return NULL;
  260 + memset(mmc, 0, sizeof(*mmc));
  261 + mmc->priv = spi_setup_slave(bus, cs, speed, mode);
  262 + if (!mmc->priv) {
  263 + free(mmc);
  264 + return NULL;
  265 + }
  266 + sprintf(mmc->name, "MMC_SPI");
  267 + mmc->send_cmd = mmc_spi_request;
  268 + mmc->set_ios = mmc_spi_set_ios;
  269 + mmc->init = mmc_spi_init_p;
  270 + mmc->host_caps = MMC_MODE_SPI;
  271 +
  272 + mmc->voltages = MMC_SPI_VOLTAGE;
  273 + mmc->f_max = speed;
  274 + mmc->f_min = MMC_SPI_MIN_CLOCK;
  275 + mmc->block_dev.part_type = PART_TYPE_DOS;
  276 +
  277 + mmc_register(mmc);
  278 +
  279 + return mmc;
  280 +}
... ... @@ -44,6 +44,7 @@
44 44 #define MMC_MODE_HS_52MHz 0x010
45 45 #define MMC_MODE_4BIT 0x100
46 46 #define MMC_MODE_8BIT 0x200
  47 +#define MMC_MODE_SPI 0x400
47 48  
48 49 #define SD_DATA_4BIT 0x00040000
49 50  
... ... @@ -75,6 +76,8 @@
75 76 #define MMC_CMD_WRITE_SINGLE_BLOCK 24
76 77 #define MMC_CMD_WRITE_MULTIPLE_BLOCK 25
77 78 #define MMC_CMD_APP_CMD 55
  79 +#define MMC_CMD_SPI_READ_OCR 58
  80 +#define MMC_CMD_SPI_CRC_ON_OFF 59
78 81  
79 82 #define SD_CMD_SEND_RELATIVE_ADDR 3
80 83 #define SD_CMD_SWITCH_FUNC 6
... ... @@ -291,6 +294,8 @@
291 294  
292 295 #ifdef CONFIG_GENERIC_MMC
293 296 int atmel_mci_init(void *regs);
  297 +#define mmc_host_is_spi(mmc) ((mmc)->host_caps & MMC_MODE_SPI)
  298 +struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
294 299 #else
295 300 int mmc_legacy_init(int verbose);
296 301 #endif