]> err.no Git - linux-2.6/commitdiff
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>
13 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 [moved from include/linux/mmc/protocol.h with 85% similarity]
include/linux/mmc/sd.h [new file with mode: 0644]

index 8a84e4dc1b2ab3658ec78a4fa12c05c0c7a9b95d..d24ab234394cc31d30233938d6f8d6ed7c215506 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 f911fbd2845bac335f7ad43e5e5ed2a74309b814..5977abf3e41b74c0f3d6eba52bcbf5ff2ca35b3b 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 334e663e465b6fc4eee89247119d11ce036faef3..310be2fe194493aa8f80b6968e132965f776cac1 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 076cb2f49a0f8233a8dc720d212da7c837f7043f..1c1066342fbab4350ecb1a578412ae28f676b3ad 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 bf9a5f8beb868dc9a4f48fec3a796fbd2b279132..5c9ce02e7e551b3f9f44cea18243636996a3af57 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 d8fd66cf28becc26fe08ff21c1e2075ef8304a18..04bbe12fae8db5ddf4ef4c673164a70f182e408b 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);
similarity index 85%
rename from include/linux/mmc/protocol.h
rename to include/linux/mmc/mmc.h
index 3ca91a6fc23fd96071d522329f550d9313ead4e4..e3ed9b95040ee51a4c5fac786b66736df2150b63 100644 (file)
@@ -22,8 +22,8 @@
  *          15 May 2002
  */
 
-#ifndef MMC_MMC_PROTOCOL_H
-#define MMC_MMC_PROTOCOL_H
+#ifndef MMC_MMC_H
+#define MMC_MMC_H
 
 /* Standard MMC commands (4.1)           type  argument     response */
    /* class 1 */
 #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:
  *
  *     [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
@@ -289,19 +253,5 @@ struct _mmc_csd {
 #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
+