mmc: Separate out protocol ops
authorPierre Ossman <drzeus@drzeus.cx>
Sun, 24 Dec 2006 21:46:55 +0000 (22:46 +0100)
committerPierre Ossman <drzeus@drzeus.cx>
Tue, 1 May 2007 11:04:18 +0000 (13:04 +0200)
Move protocol operations and definitions into their own files
in an effort to separate protocol handling and bus
arbitration more clearly.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
14 files changed:
drivers/mmc/card/block.c
drivers/mmc/core/Makefile
drivers/mmc/core/core.c
drivers/mmc/core/core.h
drivers/mmc/core/mmc_ops.c [new file with mode: 0644]
drivers/mmc/core/mmc_ops.h [new file with mode: 0644]
drivers/mmc/core/sd_ops.c [new file with mode: 0644]
drivers/mmc/core/sd_ops.h [new file with mode: 0644]
drivers/mmc/core/sysfs.c
drivers/mmc/core/sysfs.h [new file with mode: 0644]
include/linux/mmc/core.h
include/linux/mmc/mmc.h [new file with mode: 0644]
include/linux/mmc/protocol.h [deleted file]
include/linux/mmc/sd.h [new file with mode: 0644]

index 8a84e4d..d24ab23 100644 (file)
@@ -32,8 +32,8 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
index f911fbd..5977abf 100644 (file)
@@ -7,5 +7,5 @@ ifeq ($(CONFIG_MMC_DEBUG),y)
 endif
 
 obj-$(CONFIG_MMC)              += mmc_core.o
-mmc_core-y                     := core.o sysfs.o
+mmc_core-y                     := core.o sysfs.o mmc_ops.o sd_ops.o
 
index 334e663..310be2f 100644 (file)
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
 
 #include "core.h"
+#include "sysfs.h"
+
+#include "mmc_ops.h"
+#include "sd_ops.h"
 
 #define CMD_RETRIES    3
 
@@ -190,80 +195,6 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
 
 EXPORT_SYMBOL(mmc_wait_for_cmd);
 
-/**
- *     mmc_wait_for_app_cmd - start an application command and wait for
-                              completion
- *     @host: MMC host to start command
- *     @rca: RCA to send MMC_APP_CMD to
- *     @cmd: MMC command to start
- *     @retries: maximum number of retries
- *
- *     Sends a MMC_APP_CMD, checks the card response, sends the command
- *     in the parameter and waits for it to complete. Return any error
- *     that occurred while the command was executing.  Do not attempt to
- *     parse the response.
- */
-int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
-       struct mmc_command *cmd, int retries)
-{
-       struct mmc_request mrq;
-       struct mmc_command appcmd;
-
-       int i, err;
-
-       BUG_ON(!host->claimed);
-       BUG_ON(retries < 0);
-
-       err = MMC_ERR_INVALID;
-
-       /*
-        * We have to resend MMC_APP_CMD for each attempt so
-        * we cannot use the retries field in mmc_command.
-        */
-       for (i = 0;i <= retries;i++) {
-               memset(&mrq, 0, sizeof(struct mmc_request));
-
-               appcmd.opcode = MMC_APP_CMD;
-               appcmd.arg = rca << 16;
-               appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-               appcmd.retries = 0;
-               memset(appcmd.resp, 0, sizeof(appcmd.resp));
-               appcmd.data = NULL;
-
-               mrq.cmd = &appcmd;
-               appcmd.data = NULL;
-
-               mmc_wait_for_req(host, &mrq);
-
-               if (appcmd.error) {
-                       err = appcmd.error;
-                       continue;
-               }
-
-               /* Check that card supported application commands */
-               if (!(appcmd.resp[0] & R1_APP_CMD))
-                       return MMC_ERR_FAILED;
-
-               memset(&mrq, 0, sizeof(struct mmc_request));
-
-               memset(cmd->resp, 0, sizeof(cmd->resp));
-               cmd->retries = 0;
-
-               mrq.cmd = cmd;
-               cmd->data = NULL;
-
-               mmc_wait_for_req(host, &mrq);
-
-               err = cmd->error;
-               if (cmd->error == MMC_ERR_NONE)
-                       break;
-       }
-
-       return err;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_app_cmd);
-
 /**
  *     mmc_set_data_timeout - set the timeout for a data command
  *     @data: data phase for command
@@ -385,60 +316,10 @@ static inline void mmc_set_ios(struct mmc_host *host)
        host->ops->set_ios(host, ios);
 }
 
-static int mmc_select_card(struct mmc_card *card)
-{
-       int err;
-       struct mmc_command cmd;
-
-       BUG_ON(!card->host->claimed);
-
-       cmd.opcode = MMC_SELECT_CARD;
-       cmd.arg = card->rca << 16;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-       err = mmc_wait_for_cmd(card->host, &cmd, CMD_RETRIES);
-       if (err != MMC_ERR_NONE)
-               return err;
-
-       /*
-        * We can only change the bus width of SD cards when
-        * they are selected so we have to put the handling
-        * here.
-        *
-        * The card is in 1 bit mode by default so
-        * we only need to change if it supports the
-        * wider version.
-        */
-       if (mmc_card_sd(card) &&
-               (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4) &&
-               (card->host->caps & MMC_CAP_4_BIT_DATA)) {
-
-               struct mmc_command cmd;
-               cmd.opcode = SD_APP_SET_BUS_WIDTH;
-               cmd.arg = SD_BUS_WIDTH_4;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-               err = mmc_wait_for_app_cmd(card->host, card->rca,
-                       &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE)
-                       return err;
-
-               card->host->ios.bus_width = MMC_BUS_WIDTH_4;
-               mmc_set_ios(card->host);
-       }
-
-       return MMC_ERR_NONE;
-}
-
-
-static inline void mmc_delay(unsigned int ms)
+void mmc_set_chip_select(struct mmc_host *host, int mode)
 {
-       if (ms < 1000 / HZ) {
-               cond_resched();
-               mdelay(ms);
-       } else {
-               msleep(ms);
-       }
+       host->ios.chip_select = mode;
+       mmc_set_ios(host);
 }
 
 /*
@@ -708,32 +589,6 @@ mmc_alloc_card(struct mmc_host *host, u32 *raw_cid)
        return card;
 }
 
-/*
- * Tell attached cards to go to IDLE state
- */
-static void mmc_idle_cards(struct mmc_host *host)
-{
-       struct mmc_command cmd;
-
-       host->ios.chip_select = MMC_CS_HIGH;
-       mmc_set_ios(host);
-
-       mmc_delay(1);
-
-       cmd.opcode = MMC_GO_IDLE_STATE;
-       cmd.arg = 0;
-       cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
-
-       mmc_wait_for_cmd(host, &cmd, 0);
-
-       mmc_delay(1);
-
-       host->ios.chip_select = MMC_CS_DONTCARE;
-       mmc_set_ios(host);
-
-       mmc_delay(1);
-}
-
 /*
  * Apply power to the MMC stack.  This is a two-stage process.
  * First, we enable power to the card without the clock running.
@@ -778,97 +633,6 @@ static void mmc_power_off(struct mmc_host *host)
        mmc_set_ios(host);
 }
 
-static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
-{
-       struct mmc_command cmd;
-       int i, err = 0;
-
-       cmd.opcode = MMC_SEND_OP_COND;
-       cmd.arg = ocr;
-       cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
-
-       for (i = 100; i; i--) {
-               err = mmc_wait_for_cmd(host, &cmd, 0);
-               if (err != MMC_ERR_NONE)
-                       break;
-
-               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
-                       break;
-
-               err = MMC_ERR_TIMEOUT;
-
-               mmc_delay(10);
-       }
-
-       if (rocr)
-               *rocr = cmd.resp[0];
-
-       return err;
-}
-
-static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
-{
-       struct mmc_command cmd;
-       int i, err = 0;
-
-       cmd.opcode = SD_APP_OP_COND;
-       cmd.arg = ocr;
-       cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
-
-       for (i = 100; i; i--) {
-               err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE)
-                       break;
-
-               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
-                       break;
-
-               err = MMC_ERR_TIMEOUT;
-
-               mmc_delay(10);
-       }
-
-       if (rocr)
-               *rocr = cmd.resp[0];
-
-       return err;
-}
-
-static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
-{
-       struct mmc_command cmd;
-       int err, sd2;
-       static const u8 test_pattern = 0xAA;
-
-       /*
-       * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
-       * before SD_APP_OP_COND. This command will harmlessly fail for
-       * SD 1.0 cards.
-       */
-       cmd.opcode = SD_SEND_IF_COND;
-       cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
-       cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
-
-       err = mmc_wait_for_cmd(host, &cmd, 0);
-       if (err == MMC_ERR_NONE) {
-               if ((cmd.resp[0] & 0xFF) == test_pattern) {
-                       sd2 = 1;
-               } else {
-                       sd2 = 0;
-                       err = MMC_ERR_FAILED;
-               }
-       } else {
-               /*
-                * Treat errors as SD 1.0 card.
-                */
-               sd2 = 0;
-               err = MMC_ERR_NONE;
-       }
-       if (rsd2)
-               *rsd2 = sd2;
-       return err;
-}
-
 /*
  * Discover the card by requesting its CID.
  *
@@ -878,27 +642,18 @@ static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
 static void mmc_discover_card(struct mmc_host *host)
 {
        unsigned int err;
-
-       struct mmc_command cmd;
+       u32 cid[4];
 
        BUG_ON(host->card);
 
-       cmd.opcode = MMC_ALL_SEND_CID;
-       cmd.arg = 0;
-       cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
-
-       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-       if (err == MMC_ERR_TIMEOUT) {
-               err = MMC_ERR_NONE;
-               return;
-       }
+       err = mmc_all_send_cid(host, cid);
        if (err != MMC_ERR_NONE) {
                printk(KERN_ERR "%s: error requesting CID: %d\n",
                        mmc_hostname(host), err);
                return;
        }
 
-       host->card = mmc_alloc_card(host, cmd.resp);
+       host->card = mmc_alloc_card(host, cid);
        if (IS_ERR(host->card)) {
                err = PTR_ERR(host->card);
                host->card = NULL;
@@ -908,16 +663,10 @@ static void mmc_discover_card(struct mmc_host *host)
        if (host->mode == MMC_MODE_SD) {
                host->card->type = MMC_TYPE_SD;
 
-               cmd.opcode = SD_SEND_RELATIVE_ADDR;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
-
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+               err = mmc_send_relative_addr(host, &host->card->rca);
                if (err != MMC_ERR_NONE)
                        mmc_card_set_dead(host->card);
                else {
-                       host->card->rca = cmd.resp[0] >> 16;
-
                        if (!host->ops->get_ro) {
                                printk(KERN_WARNING "%s: host does not "
                                        "support reading read-only "
@@ -932,11 +681,7 @@ static void mmc_discover_card(struct mmc_host *host)
                host->card->type = MMC_TYPE_MMC;
                host->card->rca = 1;
 
-               cmd.opcode = MMC_SET_RELATIVE_ADDR;
-               cmd.arg = host->card->rca << 16;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+               err = mmc_set_relative_addr(host->card);
                if (err != MMC_ERR_NONE)
                        mmc_card_set_dead(host->card);
        }
@@ -944,7 +689,6 @@ static void mmc_discover_card(struct mmc_host *host)
 
 static void mmc_read_csd(struct mmc_host *host)
 {
-       struct mmc_command cmd;
        int err;
 
        if (!host->card)
@@ -952,18 +696,12 @@ static void mmc_read_csd(struct mmc_host *host)
        if (mmc_card_dead(host->card))
                return;
 
-       cmd.opcode = MMC_SEND_CSD;
-       cmd.arg = host->card->rca << 16;
-       cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
-
-       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+       err = mmc_send_csd(host->card, host->card->raw_csd);
        if (err != MMC_ERR_NONE) {
                mmc_card_set_dead(host->card);
                return;
        }
 
-       memcpy(host->card->raw_csd, cmd.resp, sizeof(host->card->raw_csd));
-
        mmc_decode_csd(host->card);
        mmc_decode_cid(host->card);
 }
@@ -971,13 +709,7 @@ static void mmc_read_csd(struct mmc_host *host)
 static void mmc_process_ext_csd(struct mmc_host *host)
 {
        int err;
-
-       struct mmc_request mrq;
-       struct mmc_command cmd;
-       struct mmc_data data;
-
        u8 *ext_csd;
-       struct scatterlist sg;
 
        if (!host->card)
                return;
@@ -1000,32 +732,8 @@ static void mmc_process_ext_csd(struct mmc_host *host)
                return;
        }
 
-       memset(&cmd, 0, sizeof(struct mmc_command));
-
-       cmd.opcode = MMC_SEND_EXT_CSD;
-       cmd.arg = 0;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-       memset(&data, 0, sizeof(struct mmc_data));
-
-       mmc_set_data_timeout(&data, host->card, 0);
-
-       data.blksz = 512;
-       data.blocks = 1;
-       data.flags = MMC_DATA_READ;
-       data.sg = &sg;
-       data.sg_len = 1;
-
-       memset(&mrq, 0, sizeof(struct mmc_request));
-
-       mrq.cmd = &cmd;
-       mrq.data = &data;
-
-       sg_init_one(&sg, ext_csd, 512);
-
-       mmc_wait_for_req(host, &mrq);
-
-       if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+       err = mmc_send_ext_csd(host->card, ext_csd);
+       if (err != MMC_ERR_NONE) {
                if (host->card->csd.capacity == (4096 * 512)) {
                        printk(KERN_ERR "%s: unable to read EXT_CSD "
                                "on a possible high capacity card. "
@@ -1066,14 +774,8 @@ static void mmc_process_ext_csd(struct mmc_host *host)
 
        if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
                /* Activate highspeed support. */
-               cmd.opcode = MMC_SWITCH;
-               cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                         (EXT_CSD_HS_TIMING << 16) |
-                         (1 << 8) |
-                         EXT_CSD_CMD_SET_NORMAL;
-               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
-
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+               err = mmc_switch(host->card, MMC_SWITCH_MODE_WRITE_BYTE,
+                       EXT_CSD_HS_TIMING, 1);
                if (err != MMC_ERR_NONE) {
                        printk("%s: failed to switch card to mmc v4 "
                               "high-speed mode.\n",
@@ -1090,14 +792,9 @@ static void mmc_process_ext_csd(struct mmc_host *host)
        /* Check for host support for wide-bus modes. */
        if (host->caps & MMC_CAP_4_BIT_DATA) {
                /* Activate 4-bit support. */
-               cmd.opcode = MMC_SWITCH;
-               cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                         (EXT_CSD_BUS_WIDTH << 16) |
-                         (EXT_CSD_BUS_WIDTH_4 << 8) |
-                         EXT_CSD_CMD_SET_NORMAL;
-               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
-
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+               err = mmc_switch(host->card, MMC_SWITCH_MODE_WRITE_BYTE,
+                       EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4 |
+                       EXT_CSD_CMD_SET_NORMAL);
                if (err != MMC_ERR_NONE) {
                        printk("%s: failed to switch card to "
                               "mmc v4 4-bit bus mode.\n",
@@ -1116,10 +813,6 @@ out:
 static void mmc_read_scr(struct mmc_host *host)
 {
        int err;
-       struct mmc_request mrq;
-       struct mmc_command cmd;
-       struct mmc_data data;
-       struct scatterlist sg;
 
        if (!host->card)
                return;
@@ -1128,61 +821,19 @@ static void mmc_read_scr(struct mmc_host *host)
        if (!mmc_card_sd(host->card))
                return;
 
-       memset(&cmd, 0, sizeof(struct mmc_command));
-
-       cmd.opcode = MMC_APP_CMD;
-       cmd.arg = host->card->rca << 16;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-       err = mmc_wait_for_cmd(host, &cmd, 0);
-       if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
-               mmc_card_set_dead(host->card);
-               return;
-       }
-
-       memset(&cmd, 0, sizeof(struct mmc_command));
-
-       cmd.opcode = SD_APP_SEND_SCR;
-       cmd.arg = 0;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-       memset(&data, 0, sizeof(struct mmc_data));
-
-       mmc_set_data_timeout(&data, host->card, 0);
-
-       data.blksz = 1 << 3;
-       data.blocks = 1;
-       data.flags = MMC_DATA_READ;
-       data.sg = &sg;
-       data.sg_len = 1;
-
-       memset(&mrq, 0, sizeof(struct mmc_request));
-
-       mrq.cmd = &cmd;
-       mrq.data = &data;
-
-       sg_init_one(&sg, (u8*)host->card->raw_scr, 8);
-
-       mmc_wait_for_req(host, &mrq);
-
-       if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+       err = mmc_app_send_scr(host->card, host->card->raw_scr);
+       if (err != MMC_ERR_NONE) {
                mmc_card_set_dead(host->card);
                return;
        }
 
-       host->card->raw_scr[0] = ntohl(host->card->raw_scr[0]);
-       host->card->raw_scr[1] = ntohl(host->card->raw_scr[1]);
-
        mmc_decode_scr(host->card);
 }
 
 static void mmc_read_switch_caps(struct mmc_host *host)
 {
-       struct mmc_request mrq;
-       struct mmc_command cmd;
-       struct mmc_data data;
+       int err;
        unsigned char *status;
-       struct scatterlist sg;
 
        if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
                return;
@@ -1204,32 +855,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
                return;
        }
 
-       memset(&cmd, 0, sizeof(struct mmc_command));
-
-       cmd.opcode = SD_SWITCH;
-       cmd.arg = 0x00FFFFF1;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-       memset(&data, 0, sizeof(struct mmc_data));
-
-       mmc_set_data_timeout(&data, host->card, 0);
-
-       data.blksz = 64;
-       data.blocks = 1;
-       data.flags = MMC_DATA_READ;
-       data.sg = &sg;
-       data.sg_len = 1;
-
-       memset(&mrq, 0, sizeof(struct mmc_request));
-
-       mrq.cmd = &cmd;
-       mrq.data = &data;
-
-       sg_init_one(&sg, status, 64);
-
-       mmc_wait_for_req(host, &mrq);
-
-       if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+       err = mmc_sd_switch(host->card, SD_SWITCH_CHECK,
+               SD_SWITCH_GRP_ACCESS, SD_SWITCH_ACCESS_HS, status);
+       if (err != MMC_ERR_NONE) {
                printk("%s: unable to read switch capabilities, "
                        "performance might suffer.\n",
                        mmc_hostname(host));
@@ -1239,33 +867,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
        if (status[13] & 0x02)
                host->card->sw_caps.hs_max_dtr = 50000000;
 
-       memset(&cmd, 0, sizeof(struct mmc_command));
-
-       cmd.opcode = SD_SWITCH;
-       cmd.arg = 0x80FFFFF1;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-       memset(&data, 0, sizeof(struct mmc_data));
-
-       mmc_set_data_timeout(&data, host->card, 0);
-
-       data.blksz = 64;
-       data.blocks = 1;
-       data.flags = MMC_DATA_READ;
-       data.sg = &sg;
-       data.sg_len = 1;
-
-       memset(&mrq, 0, sizeof(struct mmc_request));
-
-       mrq.cmd = &cmd;
-       mrq.data = &data;
-
-       sg_init_one(&sg, status, 64);
-
-       mmc_wait_for_req(host, &mrq);
-
-       if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE ||
-               (status[16] & 0xF) != 1) {
+       err = mmc_sd_switch(host->card, SD_SWITCH_SET,
+               SD_SWITCH_GRP_ACCESS, SD_SWITCH_ACCESS_HS, status);
+       if (err != MMC_ERR_NONE || (status[16] & 0xF) != 1) {
                printk(KERN_WARNING "%s: Problem switching card "
                        "into high-speed mode!\n",
                        mmc_hostname(host));
@@ -1314,16 +918,11 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host)
  */
 static void mmc_check_card(struct mmc_card *card)
 {
-       struct mmc_command cmd;
        int err;
 
        BUG_ON(!card);
 
-       cmd.opcode = MMC_SEND_STATUS;
-       cmd.arg = card->rca << 16;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-       err = mmc_wait_for_cmd(card->host, &cmd, CMD_RETRIES);
+       err = mmc_send_status(card, NULL);
        if (err == MMC_ERR_NONE)
                return;
 
@@ -1338,9 +937,9 @@ static void mmc_setup(struct mmc_host *host)
        host->mode = MMC_MODE_SD;
 
        mmc_power_up(host);
-       mmc_idle_cards(host);
+       mmc_go_idle(host);
 
-       err = mmc_send_if_cond(host, host->ocr_avail, NULL);
+       err = mmc_send_if_cond(host, host->ocr_avail);
        if (err != MMC_ERR_NONE) {
                return;
        }
@@ -1369,7 +968,7 @@ static void mmc_setup(struct mmc_host *host)
         * state.  We wait 1ms to give cards time to
         * respond.
         */
-       mmc_idle_cards(host);
+       mmc_go_idle(host);
 
        /*
         * Send the selected OCR multiple times... until the cards
@@ -1377,17 +976,17 @@ static void mmc_setup(struct mmc_host *host)
         * (My SanDisk card seems to need this.)
         */
        if (host->mode == MMC_MODE_SD) {
-               int err, sd2;
-               err = mmc_send_if_cond(host, host->ocr, &sd2);
-               if (err == MMC_ERR_NONE) {
-                       /*
-                       * If SD_SEND_IF_COND indicates an SD 2.0
-                       * compliant card and we should set bit 30
-                       * of the ocr to indicate that we can handle
-                       * block-addressed SDHC cards.
-                       */
-                       mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
-               }
+               /*
+                * If SD_SEND_IF_COND indicates an SD 2.0
+                * compliant card and we should set bit 30
+                * of the ocr to indicate that we can handle
+                * block-addressed SDHC cards.
+                */
+               err = mmc_send_if_cond(host, host->ocr);
+               if (err == MMC_ERR_NONE)
+                       ocr = host->ocr | (1 << 30);
+
+               mmc_send_app_op_cond(host, ocr, NULL);
        } else {
                /* The extra bit indicates that we support high capacity */
                mmc_send_op_cond(host, host->ocr | (1 << 30), NULL);
@@ -1409,6 +1008,24 @@ static void mmc_setup(struct mmc_host *host)
                        mmc_card_set_dead(host->card);
        }
 
+       /*
+        * The card is in 1 bit mode by default so
+        * we only need to change if it supports the
+        * wider version.
+        */
+       if (host->card && !mmc_card_dead(host->card) && 
+               mmc_card_sd(host->card) &&
+               (host->card->scr.bus_widths & SD_SCR_BUS_WIDTH_4) &&
+               (host->card->host->caps & MMC_CAP_4_BIT_DATA)) {
+               err = mmc_app_set_bus_width(host->card, SD_BUS_WIDTH_4);
+               if (err != MMC_ERR_NONE)
+                       mmc_card_set_dead(host->card);
+               else {
+                       host->ios.bus_width = MMC_BUS_WIDTH_4;
+                       mmc_set_ios(host);
+               }
+       }
+
        if (host->mode == MMC_MODE_SD) {
                mmc_read_scr(host);
                mmc_read_switch_caps(host);
index 076cb2f..1c10663 100644 (file)
@@ -2,24 +2,30 @@
  *  linux/drivers/mmc/core/core.h
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef _MMC_CORE_H
-#define _MMC_CORE_H
-/* core-internal functions */
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
-int mmc_register_card(struct mmc_card *card);
-void mmc_remove_card(struct mmc_card *card);
+#ifndef _MMC_CORE_CORE_H
+#define _MMC_CORE_CORE_H
 
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
-int mmc_add_host_sysfs(struct mmc_host *host);
-void mmc_remove_host_sysfs(struct mmc_host *host);
-void mmc_free_host_sysfs(struct mmc_host *host);
+#include <linux/delay.h>
+
+#define MMC_CMD_RETRIES        3
+
+void mmc_set_chip_select(struct mmc_host *host, int mode);
+
+static inline void mmc_delay(unsigned int ms)
+{
+       if (ms < 1000 / HZ) {
+               cond_resched();
+               mdelay(ms);
+       } else {
+               msleep(ms);
+       }
+}
 
-int mmc_schedule_work(struct work_struct *work);
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
-void mmc_flush_scheduled_work(void);
 #endif
+
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
new file mode 100644 (file)
index 0000000..7dd720f
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ *  linux/drivers/mmc/mmc_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "mmc_ops.h"
+
+static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SELECT_CARD;
+
+       if (card) {
+               cmd.arg = card->rca << 16;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+       } else {
+               cmd.arg = 0;
+               cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
+       }
+
+       err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_select_card(struct mmc_card *card)
+{
+       BUG_ON(!card);
+
+       return _mmc_select_card(card->host, card);
+}
+
+int mmc_deselect_cards(struct mmc_host *host)
+{
+       return _mmc_select_card(host, NULL);
+}
+
+int mmc_go_idle(struct mmc_host *host)
+{
+       int err;
+       struct mmc_command cmd;
+
+       mmc_set_chip_select(host, MMC_CS_HIGH);
+
+       mmc_delay(1);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_GO_IDLE_STATE;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+
+       mmc_delay(1);
+
+       mmc_set_chip_select(host, MMC_CS_DONTCARE);
+
+       mmc_delay(1);
+
+       return err;
+}
+
+int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+       struct mmc_command cmd;
+       int i, err = 0;
+
+       BUG_ON(!host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SEND_OP_COND;
+       cmd.arg = ocr;
+       cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+
+       for (i = 100; i; i--) {
+               err = mmc_wait_for_cmd(host, &cmd, 0);
+               if (err != MMC_ERR_NONE)
+                       break;
+
+               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+                       break;
+
+               err = MMC_ERR_TIMEOUT;
+
+               mmc_delay(10);
+       }
+
+       if (rocr)
+               *rocr = cmd.resp[0];
+
+       return err;
+}
+
+int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!host);
+       BUG_ON(!cid);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_ALL_SEND_CID;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
+
+       err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       memcpy(cid, cmd.resp, sizeof(u32) * 4);
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_set_relative_addr(struct mmc_card *card)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SET_RELATIVE_ADDR;
+       cmd.arg = card->rca << 16;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_csd(struct mmc_card *card, u32 *csd)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+       BUG_ON(!csd);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SEND_CSD;
+       cmd.arg = card->rca << 16;
+       cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       memcpy(csd, cmd.resp, sizeof(u32) * 4);
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
+{
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+       BUG_ON(!ext_csd);
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = MMC_SEND_EXT_CSD;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.blksz = 512;
+       data.blocks = 1;
+       data.flags = MMC_DATA_READ;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       sg_init_one(&sg, ext_csd, 512);
+
+       mmc_set_data_timeout(&data, card, 0);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error != MMC_ERR_NONE)
+               return cmd.error;
+       if (data.error != MMC_ERR_NONE)
+               return data.error;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SWITCH;
+       cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                 (index << 16) |
+                 (value << 8) |
+                 set;
+       cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_status(struct mmc_card *card, u32 *status)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SEND_STATUS;
+       cmd.arg = card->rca << 16;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       if (status)
+               *status = cmd.resp[0];
+
+       return MMC_ERR_NONE;
+}
+
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
new file mode 100644 (file)
index 0000000..7a481e8
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  linux/drivers/mmc/mmc_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _MMC_MMC_OPS_H
+#define _MMC_MMC_OPS_H
+
+int mmc_select_card(struct mmc_card *card);
+int mmc_deselect_cards(struct mmc_host *host);
+int mmc_go_idle(struct mmc_host *host);
+int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
+int mmc_set_relative_addr(struct mmc_card *card);
+int mmc_send_csd(struct mmc_card *card, u32 *csd);
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value);
+int mmc_send_status(struct mmc_card *card, u32 *status);
+
+#endif
+
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
new file mode 100644 (file)
index 0000000..9697ce5
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ *  linux/drivers/mmc/sd_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include "core.h"
+#include "sd_ops.h"
+
+/**
+ *     mmc_wait_for_app_cmd - start an application command and wait for
+                              completion
+ *     @host: MMC host to start command
+ *     @rca: RCA to send MMC_APP_CMD to
+ *     @cmd: MMC command to start
+ *     @retries: maximum number of retries
+ *
+ *     Sends a MMC_APP_CMD, checks the card response, sends the command
+ *     in the parameter and waits for it to complete. Return any error
+ *     that occurred while the command was executing.  Do not attempt to
+ *     parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
+       struct mmc_command *cmd, int retries)
+{
+       struct mmc_request mrq;
+
+       int i, err;
+
+       BUG_ON(!cmd);
+       BUG_ON(retries < 0);
+
+       err = MMC_ERR_INVALID;
+
+       /*
+        * We have to resend MMC_APP_CMD for each attempt so
+        * we cannot use the retries field in mmc_command.
+        */
+       for (i = 0;i <= retries;i++) {
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               err = mmc_app_cmd(host, card);
+               if (err != MMC_ERR_NONE)
+                       continue;
+
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               memset(cmd->resp, 0, sizeof(cmd->resp));
+               cmd->retries = 0;
+
+               mrq.cmd = cmd;
+               cmd->data = NULL;
+
+               mmc_wait_for_req(host, &mrq);
+
+               err = cmd->error;
+               if (cmd->error == MMC_ERR_NONE)
+                       break;
+       }
+
+       return err;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_app_cmd);
+
+int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!host);
+       BUG_ON(card && (card->host != host));
+
+       cmd.opcode = MMC_APP_CMD;
+
+       if (card) {
+               cmd.arg = card->rca << 16;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+       } else {
+               cmd.arg = 0;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR;
+       }
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       /* Check that card supported application commands */
+       if (!(cmd.resp[0] & R1_APP_CMD))
+               return MMC_ERR_FAILED;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_app_set_bus_width(struct mmc_card *card, int width)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = SD_APP_SET_BUS_WIDTH;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+       switch (width) {
+       case MMC_BUS_WIDTH_1:
+               cmd.arg = SD_BUS_WIDTH_1;
+               break;
+       case MMC_BUS_WIDTH_4:
+               cmd.arg = SD_BUS_WIDTH_4;
+               break;
+       default:
+               return MMC_ERR_INVALID;
+       }
+
+       err = mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+       struct mmc_command cmd;
+       int i, err = 0;
+
+       BUG_ON(!host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = SD_APP_OP_COND;
+       cmd.arg = ocr;
+       cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+
+       for (i = 100; i; i--) {
+               err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES);
+               if (err != MMC_ERR_NONE)
+                       break;
+
+               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+                       break;
+
+               err = MMC_ERR_TIMEOUT;
+
+               mmc_delay(10);
+       }
+
+       if (rocr)
+               *rocr = cmd.resp[0];
+
+       return err;
+}
+
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
+{
+       struct mmc_command cmd;
+       int err;
+       static const u8 test_pattern = 0xAA;
+
+       /*
+        * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
+        * before SD_APP_OP_COND. This command will harmlessly fail for
+        * SD 1.0 cards.
+        */
+       cmd.opcode = SD_SEND_IF_COND;
+       cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+       cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       if ((cmd.resp[0] & 0xFF) != test_pattern)
+               return MMC_ERR_FAILED;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!host);
+       BUG_ON(!rca);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = SD_SEND_RELATIVE_ADDR;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
+
+       err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       *rca = cmd.resp[0] >> 16;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
+{
+       int err;
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+       BUG_ON(!scr);
+
+       err = mmc_app_cmd(card->host, card);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = SD_APP_SEND_SCR;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.blksz = 8;
+       data.blocks = 1;
+       data.flags = MMC_DATA_READ;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       sg_init_one(&sg, scr, 8);
+
+       mmc_set_data_timeout(&data, card, 0);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error != MMC_ERR_NONE)
+               return cmd.error;
+       if (data.error != MMC_ERR_NONE)
+               return data.error;
+
+       scr[0] = ntohl(scr[0]);
+       scr[1] = ntohl(scr[1]);
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_sd_switch(struct mmc_card *card, int mode, int group,
+       u8 value, u8 *resp)
+{
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       mode = !!mode;
+       value &= 0xF;
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = SD_SWITCH;
+       cmd.arg = mode << 31 | 0x00FFFFFF;
+       cmd.arg &= ~(0xF << (group * 4));
+       cmd.arg |= value << (group * 4);
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.blksz = 64;
+       data.blocks = 1;
+       data.flags = MMC_DATA_READ;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       sg_init_one(&sg, resp, 64);
+
+       mmc_set_data_timeout(&data, card, 0);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error != MMC_ERR_NONE)
+               return cmd.error;
+       if (data.error != MMC_ERR_NONE)
+               return data.error;
+
+       return MMC_ERR_NONE;
+}
+
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
new file mode 100644 (file)
index 0000000..1240fdd
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  linux/drivers/mmc/sd_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _MMC_SD_OPS_H
+#define _MMC_SD_OPS_H
+
+int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
+int mmc_app_set_bus_width(struct mmc_card *card, int width);
+int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
+int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
+int mmc_app_send_scr(struct mmc_card *card, u32 *scr);
+int mmc_sd_switch(struct mmc_card *card, int mode, int group,
+       u8 value, u8 *resp);
+
+#endif
+
index bf9a5f8..5c9ce02 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 
-#include "core.h"
+#include "sysfs.h"
 
 #define dev_to_mmc_card(d)     container_of(d, struct mmc_card, dev)
 #define to_mmc_driver(d)       container_of(d, struct mmc_driver, drv)
diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h
new file mode 100644 (file)
index 0000000..80e29b3
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  linux/drivers/mmc/core/sysfs.h
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _MMC_CORE_SYSFS_H
+#define _MMC_CORE_SYSFS_H
+
+void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
+int mmc_register_card(struct mmc_card *card);
+void mmc_remove_card(struct mmc_card *card);
+
+struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
+int mmc_add_host_sysfs(struct mmc_host *host);
+void mmc_remove_host_sysfs(struct mmc_host *host);
+void mmc_free_host_sysfs(struct mmc_host *host);
+
+int mmc_schedule_work(struct work_struct *work);
+int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
+void mmc_flush_scheduled_work(void);
+
+#endif
index d8fd66c..04bbe12 100644 (file)
@@ -101,7 +101,7 @@ struct mmc_card;
 
 extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
 extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
-extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
+extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
        struct mmc_command *, int);
 
 extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
new file mode 100644 (file)
index 0000000..e3ed9b9
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Header for MultiMediaCard (MMC)
+ *
+ * Copyright 2002 Hewlett-Packard Company
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Many thanks to Alessandro Rubini and Jonathan Corbet!
+ *
+ * Based strongly on code by:
+ *
+ * Author: Yong-iL Joh <tolkien@mizi.com>
+ * Date  : $Date: 2002/06/18 12:37:30 $
+ *
+ * Author:  Andrew Christian
+ *          15 May 2002
+ */
+
+#ifndef MMC_MMC_H
+#define MMC_MMC_H
+
+/* Standard MMC commands (4.1)           type  argument     response */
+   /* class 1 */
+#define        MMC_GO_IDLE_STATE         0   /* bc                          */
+#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
+#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
+#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
+#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
+#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
+#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
+#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
+#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
+#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
+#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
+#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
+#define MMC_SEND_STATUS                 13   /* ac   [31:16] RCA        R1  */
+#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
+
+  /* class 2 */
+#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
+#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
+#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
+
+  /* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
+
+  /* class 4 */
+#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
+#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
+#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
+
+  /* class 6 */
+#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
+#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
+#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
+
+  /* class 5 */
+#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE                38   /* ac                      R1b */
+
+  /* class 9 */
+#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
+#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
+
+  /* class 7 */
+#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
+
+  /* class 8 */
+#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
+#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
+
+/*
+ * MMC_SWITCH argument format:
+ *
+ *     [31:26] Always 0
+ *     [25:24] Access Mode
+ *     [23:16] Location of target Byte in EXT_CSD
+ *     [15:08] Value Byte
+ *     [07:03] Always 0
+ *     [02:00] Command Set
+ */
+
+/*
+  MMC status in R1
+  Type
+       e : error bit
+       s : status bit
+       r : detected and set for the actual command response
+       x : detected and set during command execution. the host must poll
+            the card by sending status command in order to read these bits.
+  Clear condition
+       a : according to the card state
+       b : always related to the previous command. Reception of
+            a valid command will clear it (with a delay of one command)
+       c : clear by read
+ */
+
+#define R1_OUT_OF_RANGE                (1 << 31)       /* er, c */
+#define R1_ADDRESS_ERROR       (1 << 30)       /* erx, c */
+#define R1_BLOCK_LEN_ERROR     (1 << 29)       /* er, c */
+#define R1_ERASE_SEQ_ERROR      (1 << 28)      /* er, c */
+#define R1_ERASE_PARAM         (1 << 27)       /* ex, c */
+#define R1_WP_VIOLATION                (1 << 26)       /* erx, c */
+#define R1_CARD_IS_LOCKED      (1 << 25)       /* sx, a */
+#define R1_LOCK_UNLOCK_FAILED  (1 << 24)       /* erx, c */
+#define R1_COM_CRC_ERROR       (1 << 23)       /* er, b */
+#define R1_ILLEGAL_COMMAND     (1 << 22)       /* er, b */
+#define R1_CARD_ECC_FAILED     (1 << 21)       /* ex, c */
+#define R1_CC_ERROR            (1 << 20)       /* erx, c */
+#define R1_ERROR               (1 << 19)       /* erx, c */
+#define R1_UNDERRUN            (1 << 18)       /* ex, c */
+#define R1_OVERRUN             (1 << 17)       /* ex, c */
+#define R1_CID_CSD_OVERWRITE   (1 << 16)       /* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP       (1 << 15)       /* sx, c */
+#define R1_CARD_ECC_DISABLED   (1 << 14)       /* sx, a */
+#define R1_ERASE_RESET         (1 << 13)       /* sr, c */
+#define R1_STATUS(x)            (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x)            ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+#define R1_READY_FOR_DATA      (1 << 8)        /* sx, a */
+#define R1_APP_CMD             (1 << 5)        /* sr, c */
+
+/* These are unpacked versions of the actual responses */
+
+struct _mmc_csd {
+       u8  csd_structure;
+       u8  spec_vers;
+       u8  taac;
+       u8  nsac;
+       u8  tran_speed;
+       u16 ccc;
+       u8  read_bl_len;
+       u8  read_bl_partial;
+       u8  write_blk_misalign;
+       u8  read_blk_misalign;
+       u8  dsr_imp;
+       u16 c_size;
+       u8  vdd_r_curr_min;
+       u8  vdd_r_curr_max;
+       u8  vdd_w_curr_min;
+       u8  vdd_w_curr_max;
+       u8  c_size_mult;
+       union {
+               struct { /* MMC system specification version 3.1 */
+                       u8  erase_grp_size;
+                       u8  erase_grp_mult;
+               } v31;
+               struct { /* MMC system specification version 2.2 */
+                       u8  sector_size;
+                       u8  erase_grp_size;
+               } v22;
+       } erase;
+       u8  wp_grp_size;
+       u8  wp_grp_enable;
+       u8  default_ecc;
+       u8  r2w_factor;
+       u8  write_bl_len;
+       u8  write_bl_partial;
+       u8  file_format_grp;
+       u8  copy;
+       u8  perm_write_protect;
+       u8  tmp_write_protect;
+       u8  file_format;
+       u8  ecc;
+};
+
+/*
+ * OCR bits are mostly in host.h
+ */
+#define MMC_CARD_BUSY  0x80000000      /* Card Power up status bit */
+
+/*
+ * Card Command Classes (CCC)
+ */
+#define CCC_BASIC              (1<<0)  /* (0) Basic protocol functions */
+                                       /* (CMD0,1,2,3,4,7,9,10,12,13,15) */
+#define CCC_STREAM_READ                (1<<1)  /* (1) Stream read commands */
+                                       /* (CMD11) */
+#define CCC_BLOCK_READ         (1<<2)  /* (2) Block read commands */
+                                       /* (CMD16,17,18) */
+#define CCC_STREAM_WRITE       (1<<3)  /* (3) Stream write commands */
+                                       /* (CMD20) */
+#define CCC_BLOCK_WRITE                (1<<4)  /* (4) Block write commands */
+                                       /* (CMD16,24,25,26,27) */
+#define CCC_ERASE              (1<<5)  /* (5) Ability to erase blocks */
+                                       /* (CMD32,33,34,35,36,37,38,39) */
+#define CCC_WRITE_PROT         (1<<6)  /* (6) Able to write protect blocks */
+                                       /* (CMD28,29,30) */
+#define CCC_LOCK_CARD          (1<<7)  /* (7) Able to lock down card */
+                                       /* (CMD16,CMD42) */
+#define CCC_APP_SPEC           (1<<8)  /* (8) Application specific */
+                                       /* (CMD55,56,57,ACMD*) */
+#define CCC_IO_MODE            (1<<9)  /* (9) I/O mode */
+                                       /* (CMD5,39,40,52,53) */
+#define CCC_SWITCH             (1<<10) /* (10) High speed switch */
+                                       /* (CMD6,34,35,36,37,50) */
+                                       /* (11) Reserved */
+                                       /* (CMD?) */
+
+/*
+ * CSD field definitions
+ */
+
+#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
+#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
+#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
+
+#define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
+#define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
+#define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
+#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
+
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH      183     /* R/W */
+#define EXT_CSD_HS_TIMING      185     /* R/W */
+#define EXT_CSD_CARD_TYPE      196     /* RO */
+#define EXT_CSD_SEC_CNT                212     /* RO, 4 bytes */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+#define EXT_CSD_CMD_SET_NORMAL         (1<<0)
+#define EXT_CSD_CMD_SET_SECURE         (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
+
+#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
+
+#define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8    2       /* Card is in 8 bit mode */
+
+/*
+ * MMC_SWITCH access modes
+ */
+
+#define MMC_SWITCH_MODE_CMD_SET                0x00    /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS       0x01    /* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS     0x02    /* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE     0x03    /* Set target to value */
+
+#endif  /* MMC_MMC_PROTOCOL_H */
+
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
deleted file mode 100644 (file)
index 3ca91a6..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Header for MultiMediaCard (MMC)
- *
- * Copyright 2002 Hewlett-Packard Company
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
- * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
- * FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- * Many thanks to Alessandro Rubini and Jonathan Corbet!
- *
- * Based strongly on code by:
- *
- * Author: Yong-iL Joh <tolkien@mizi.com>
- * Date  : $Date: 2002/06/18 12:37:30 $
- *
- * Author:  Andrew Christian
- *          15 May 2002
- */
-
-#ifndef MMC_MMC_PROTOCOL_H
-#define MMC_MMC_PROTOCOL_H
-
-/* Standard MMC commands (4.1)           type  argument     response */
-   /* class 1 */
-#define        MMC_GO_IDLE_STATE         0   /* bc                          */
-#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
-#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
-#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
-#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
-#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
-#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
-#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
-#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
-#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
-#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
-#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
-#define MMC_SEND_STATUS                 13   /* ac   [31:16] RCA        R1  */
-#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
-
-  /* class 2 */
-#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
-#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
-#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
-
-  /* class 3 */
-#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
-
-  /* class 4 */
-#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
-#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
-#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
-#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
-#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
-
-  /* class 6 */
-#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
-#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
-#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
-
-  /* class 5 */
-#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
-#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
-#define MMC_ERASE                38   /* ac                      R1b */
-
-  /* class 9 */
-#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
-#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
-
-  /* class 7 */
-#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
-
-  /* class 8 */
-#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
-#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
-
-/* SD commands                           type  argument     response */
-  /* class 0 */
-/* This is basically the same command as for MMC with some quirks. */
-#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
-#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
-
-  /* class 10 */
-#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
-
-  /* Application commands */
-#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
-#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
-#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
-#define SD_APP_SEND_SCR          51   /* adtc                    R1  */
-
-/*
- * MMC_SWITCH argument format:
- *
- *     [31:26] Always 0
- *     [25:24] Access Mode
- *     [23:16] Location of target Byte in EXT_CSD
- *     [15:08] Value Byte
- *     [07:03] Always 0
- *     [02:00] Command Set
- */
-
-/*
- * SD_SWITCH argument format:
- *
- *      [31] Check (0) or switch (1)
- *      [30:24] Reserved (0)
- *      [23:20] Function group 6
- *      [19:16] Function group 5
- *      [15:12] Function group 4
- *      [11:8] Function group 3
- *      [7:4] Function group 2
- *      [3:0] Function group 1
- */
-
-/*
- * SD_SEND_IF_COND argument format:
- *
- *     [31:12] Reserved (0)
- *     [11:8] Host Voltage Supply Flags
- *     [7:0] Check Pattern (0xAA)
- */
-
-/*
-  MMC status in R1
-  Type
-       e : error bit
-       s : status bit
-       r : detected and set for the actual command response
-       x : detected and set during command execution. the host must poll
-            the card by sending status command in order to read these bits.
-  Clear condition
-       a : according to the card state
-       b : always related to the previous command. Reception of
-            a valid command will clear it (with a delay of one command)
-       c : clear by read
- */
-
-#define R1_OUT_OF_RANGE                (1 << 31)       /* er, c */
-#define R1_ADDRESS_ERROR       (1 << 30)       /* erx, c */
-#define R1_BLOCK_LEN_ERROR     (1 << 29)       /* er, c */
-#define R1_ERASE_SEQ_ERROR      (1 << 28)      /* er, c */
-#define R1_ERASE_PARAM         (1 << 27)       /* ex, c */
-#define R1_WP_VIOLATION                (1 << 26)       /* erx, c */
-#define R1_CARD_IS_LOCKED      (1 << 25)       /* sx, a */
-#define R1_LOCK_UNLOCK_FAILED  (1 << 24)       /* erx, c */
-#define R1_COM_CRC_ERROR       (1 << 23)       /* er, b */
-#define R1_ILLEGAL_COMMAND     (1 << 22)       /* er, b */
-#define R1_CARD_ECC_FAILED     (1 << 21)       /* ex, c */
-#define R1_CC_ERROR            (1 << 20)       /* erx, c */
-#define R1_ERROR               (1 << 19)       /* erx, c */
-#define R1_UNDERRUN            (1 << 18)       /* ex, c */
-#define R1_OVERRUN             (1 << 17)       /* ex, c */
-#define R1_CID_CSD_OVERWRITE   (1 << 16)       /* erx, c, CID/CSD overwrite */
-#define R1_WP_ERASE_SKIP       (1 << 15)       /* sx, c */
-#define R1_CARD_ECC_DISABLED   (1 << 14)       /* sx, a */
-#define R1_ERASE_RESET         (1 << 13)       /* sr, c */
-#define R1_STATUS(x)            (x & 0xFFFFE000)
-#define R1_CURRENT_STATE(x)            ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
-#define R1_READY_FOR_DATA      (1 << 8)        /* sx, a */
-#define R1_APP_CMD             (1 << 5)        /* sr, c */
-
-/* These are unpacked versions of the actual responses */
-
-struct _mmc_csd {
-       u8  csd_structure;
-       u8  spec_vers;
-       u8  taac;
-       u8  nsac;
-       u8  tran_speed;
-       u16 ccc;
-       u8  read_bl_len;
-       u8  read_bl_partial;
-       u8  write_blk_misalign;
-       u8  read_blk_misalign;
-       u8  dsr_imp;
-       u16 c_size;
-       u8  vdd_r_curr_min;
-       u8  vdd_r_curr_max;
-       u8  vdd_w_curr_min;
-       u8  vdd_w_curr_max;
-       u8  c_size_mult;
-       union {
-               struct { /* MMC system specification version 3.1 */
-                       u8  erase_grp_size;
-                       u8  erase_grp_mult;
-               } v31;
-               struct { /* MMC system specification version 2.2 */
-                       u8  sector_size;
-                       u8  erase_grp_size;
-               } v22;
-       } erase;
-       u8  wp_grp_size;
-       u8  wp_grp_enable;
-       u8  default_ecc;
-       u8  r2w_factor;
-       u8  write_bl_len;
-       u8  write_bl_partial;
-       u8  file_format_grp;
-       u8  copy;
-       u8  perm_write_protect;
-       u8  tmp_write_protect;
-       u8  file_format;
-       u8  ecc;
-};
-
-/*
- * OCR bits are mostly in host.h
- */
-#define MMC_CARD_BUSY  0x80000000      /* Card Power up status bit */
-
-/*
- * Card Command Classes (CCC)
- */
-#define CCC_BASIC              (1<<0)  /* (0) Basic protocol functions */
-                                       /* (CMD0,1,2,3,4,7,9,10,12,13,15) */
-#define CCC_STREAM_READ                (1<<1)  /* (1) Stream read commands */
-                                       /* (CMD11) */
-#define CCC_BLOCK_READ         (1<<2)  /* (2) Block read commands */
-                                       /* (CMD16,17,18) */
-#define CCC_STREAM_WRITE       (1<<3)  /* (3) Stream write commands */
-                                       /* (CMD20) */
-#define CCC_BLOCK_WRITE                (1<<4)  /* (4) Block write commands */
-                                       /* (CMD16,24,25,26,27) */
-#define CCC_ERASE              (1<<5)  /* (5) Ability to erase blocks */
-                                       /* (CMD32,33,34,35,36,37,38,39) */
-#define CCC_WRITE_PROT         (1<<6)  /* (6) Able to write protect blocks */
-                                       /* (CMD28,29,30) */
-#define CCC_LOCK_CARD          (1<<7)  /* (7) Able to lock down card */
-                                       /* (CMD16,CMD42) */
-#define CCC_APP_SPEC           (1<<8)  /* (8) Application specific */
-                                       /* (CMD55,56,57,ACMD*) */
-#define CCC_IO_MODE            (1<<9)  /* (9) I/O mode */
-                                       /* (CMD5,39,40,52,53) */
-#define CCC_SWITCH             (1<<10) /* (10) High speed switch */
-                                       /* (CMD6,34,35,36,37,50) */
-                                       /* (11) Reserved */
-                                       /* (CMD?) */
-
-/*
- * CSD field definitions
- */
-
-#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
-#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
-#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
-#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
-
-#define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
-#define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
-#define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
-#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
-#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
-
-/*
- * EXT_CSD fields
- */
-
-#define EXT_CSD_BUS_WIDTH      183     /* R/W */
-#define EXT_CSD_HS_TIMING      185     /* R/W */
-#define EXT_CSD_CARD_TYPE      196     /* RO */
-#define EXT_CSD_SEC_CNT                212     /* RO, 4 bytes */
-
-/*
- * EXT_CSD field definitions
- */
-
-#define EXT_CSD_CMD_SET_NORMAL         (1<<0)
-#define EXT_CSD_CMD_SET_SECURE         (1<<1)
-#define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
-
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
-
-#define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
-#define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
-#define EXT_CSD_BUS_WIDTH_8    2       /* Card is in 8 bit mode */
-
-/*
- * MMC_SWITCH access modes
- */
-
-#define MMC_SWITCH_MODE_CMD_SET                0x00    /* Change the command set */
-#define MMC_SWITCH_MODE_SET_BITS       0x01    /* Set bits which are 1 in value */
-#define MMC_SWITCH_MODE_CLEAR_BITS     0x02    /* Clear bits which are 1 in value */
-#define MMC_SWITCH_MODE_WRITE_BYTE     0x03    /* Set target to value */
-
-/*
- * SCR field definitions
- */
-
-#define SCR_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.01 */
-#define SCR_SPEC_VER_1      1           /* Implements system specification 1.10 */
-#define SCR_SPEC_VER_2      2           /* Implements system specification 2.00 */
-
-/*
- * SD bus widths
- */
-#define SD_BUS_WIDTH_1      0
-#define SD_BUS_WIDTH_4      2
-
-#endif  /* MMC_MMC_PROTOCOL_H */
-
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
new file mode 100644 (file)
index 0000000..f310062
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *  include/linux/mmc/sd.h
+ *
+ *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef MMC_SD_H
+#define MMC_SD_H
+
+/* SD commands                           type  argument     response */
+  /* class 0 */
+/* This is basically the same command as for MMC with some quirks. */
+#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
+
+  /* class 10 */
+#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
+
+  /* Application commands */
+#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
+#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
+#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
+#define SD_APP_SEND_SCR          51   /* adtc                    R1  */
+
+/*
+ * SD_SWITCH argument format:
+ *
+ *      [31] Check (0) or switch (1)
+ *      [30:24] Reserved (0)
+ *      [23:20] Function group 6
+ *      [19:16] Function group 5
+ *      [15:12] Function group 4
+ *      [11:8] Function group 3
+ *      [7:4] Function group 2
+ *      [3:0] Function group 1
+ */
+
+/*
+ * SD_SEND_IF_COND argument format:
+ *
+ *     [31:12] Reserved (0)
+ *     [11:8] Host Voltage Supply Flags
+ *     [7:0] Check Pattern (0xAA)
+ */
+
+/*
+ * SCR field definitions
+ */
+
+#define SCR_SPEC_VER_0         0       /* Implements system specification 1.0 - 1.01 */
+#define SCR_SPEC_VER_1         1       /* Implements system specification 1.10 */
+#define SCR_SPEC_VER_2         2       /* Implements system specification 2.00 */
+
+/*
+ * SD bus widths
+ */
+#define SD_BUS_WIDTH_1         0
+#define SD_BUS_WIDTH_4         2
+
+/*
+ * SD_SWITCH mode
+ */
+#define SD_SWITCH_CHECK                0
+#define SD_SWITCH_SET          1
+
+/*
+ * SD_SWITCH function groups
+ */
+#define SD_SWITCH_GRP_ACCESS   0
+
+/*
+ * SD_SWITCH access modes
+ */
+#define SD_SWITCH_ACCESS_DEF   0
+#define SD_SWITCH_ACCESS_HS    1
+
+#endif
+