Re: [RFC]: mmc bus width testing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Nov 23, 2010, at 7:56 AM, Philip Rakity wrote:

>
> A long time (2.6.2x days) I tried to submit a patch to do bus width testing on mmc and would appreciate some feedback before I do a formal submission.
>
> Bus width testing is defined in JEDEC Standard No. 84-A441: section A.8.3 Changing the data bus width
>
> The problem is that it does NOT work in all cases.  Some controllers do not handle the CMD19/CMD14 exchange.
> (BUSTEST_W/BUSTEST_R)
>
> When this failure happens it is not at all clear what to do....
>
> We could default to 1 bit mode and just do what we do today and take 4 bit bus width -- assuming CAPS are appropriately enabled.
>
> I was thinking of adding a new MMC_CAP saying controller supports bus width testing.      Any thoughts ?
>
> <snippet of code from today implementation == based on 2.6.32 but with DDR support back ported>
>
> look for mmc_test_bus_width()
>
> My thought was to replace
>
>                       if (err) {
>                               printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
>                                          "failed\n", mmc_hostname(card->host),
>                                          1 << bus_width, ddr);
>                               err = 0;
>                       } else {
>                               mmc_set_bus_width_ddr(card->host, bus_width, MMC_SDR_MODE);
>                               if (mmc_test_bus_width (card, 1<<bus_width))
>                                       break;
>                       }
>
> with
>
>                       if (err) {
>                               printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
>                                          "failed\n", mmc_hostname(card->host),
>                                          1 << bus_width, ddr);
>                               err = 0;
>                       } else {
>                               mmc_set_bus_width_ddr(card->host, bus_width, MMC_SDR_MODE);
>                               if ((mmc->caps & MMC_CAPS_CONTROLLER_SUPPORTS_BUSTEST) == 0)
>                                       break;
>                               if (mmc_test_bus_width (card, 1<<bus_width))
>                                       break;
>                       }
>
> and let the platform code set MMC_CAPS_CONTROLLER_SUPPORTS_BUSTEST
>
>
>
> from mmc.c
> ==========
>
> static int mmc_init_card(struct mmc_host *host, u32 ocr,
>       struct mmc_card *oldcard)
> {
>       struct mmc_card *card;
>       int err, ddr = 0;
>       u32 cid[4];
>       unsigned int max_dtr;
>       u32 rocr;
>
>       BUG_ON(!host);
>       WARN_ON(!host->claimed);
>
>       /*
>        * Since we're changing the OCR value, we seem to
>        * need to tell some cards to go back to the idle
>        * state.  We wait 1ms to give cards time to
>        * respond.
>        */
>       mmc_go_idle(host);
>
>       /* The extra bit indicates that we support high capacity */
>       err = mmc_send_op_cond(host, ocr | MMC_CARD_SECTOR_ADDR, &rocr);
>       if (err)
>               goto err;
>
>       /*
>        * For SPI, enable CRC as appropriate.
>        */
>       if (mmc_host_is_spi(host)) {
>               err = mmc_spi_set_crc(host, use_spi_crc);
>               if (err)
>                       goto err;
>       }
>
>       /*
>        * Fetch CID from card.
>        */
>       if (mmc_host_is_spi(host))
>               err = mmc_send_cid(host, cid);
>       else
>               err = mmc_all_send_cid(host, cid);
>       if (err)
>               goto err;
>
>       if (oldcard) {
>               if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
>                       err = -ENOENT;
>                       goto err;
>               }
>
>               card = oldcard;
>       } else {
>               /*
>                * Allocate card structure.
>                */
>               card = mmc_alloc_card(host, &mmc_type);
>               if (IS_ERR(card)) {
>                       err = PTR_ERR(card);
>                       goto err;
>               }
>
>               card->type = MMC_TYPE_MMC;
>               card->rca = 1;
>               memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
>       }
>
>       /*
>        * For native busses:  set card RCA and quit open drain mode.
>        */
>       if (!mmc_host_is_spi(host)) {
>               err = mmc_set_relative_addr(card);
>               if (err)
>                       goto free_card;
>
>               mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
>       }
>
>       if (!oldcard) {
>               /*
>                * Fetch CSD from card.
>                */
>               err = mmc_send_csd(card, card->raw_csd);
>               if (err)
>                       goto free_card;
>
>               err = mmc_decode_csd(card);
>               if (err)
>                       goto free_card;
>               err = mmc_decode_cid(card);
>               if (err)
>                       goto free_card;
>       }
>
>       /*
>        * Select card, as all following commands rely on that.
>        */
>       if (!mmc_host_is_spi(host)) {
>               err = mmc_select_card(card);
>               if (err)
>                       goto free_card;
>       }
>
> #if 0
>       if (mmc_card_mmc(card)) {
>               /* work around of Micorn 16G emmc */
>               /* set bus_width to 1 bit as init state */
>               mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                               EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
>
>       }
> #endif
>
>       if (!oldcard) {
>               /*
>                * Fetch and process extended CSD.
>                */
>               err = mmc_read_ext_csd(card);
>               if (err)
>                       goto free_card;
>
>               if (rocr & MMC_CARD_SECTOR_ADDR)
>                       mmc_card_set_blockaddr(card);
>       }
>
>
>       /* switch to user partition, emmc may stay in boot partition after boot */
>       mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                       EXT_CSD_PART_CONF, 0);
>
>       /*
>        * Activate high speed (if supported)
>        */
>       if ((card->ext_csd.hs_max_dtr != 0) &&
>               (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
>               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                       EXT_CSD_HS_TIMING, 1);
>               if (err && err != -EBADMSG)
>                       goto free_card;
>
>               if (err) {
>                       printk(KERN_WARNING "%s: switch to highspeed failed\n",
>                              mmc_hostname(card->host));
>                       err = 0;
>               } else {
>                       mmc_card_set_highspeed(card);
>                       mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
>               }
>       }
>
>       /*
>        * Compute bus speed.
>        */
>       max_dtr = (unsigned int)-1;
>
>       if (mmc_card_highspeed(card)) {
>               if (max_dtr > card->ext_csd.hs_max_dtr)
>                       max_dtr = card->ext_csd.hs_max_dtr;
>       } else if (max_dtr > card->csd.max_dtr) {
>               max_dtr = card->csd.max_dtr;
>       }
>
>       mmc_set_clock(host, max_dtr);
>
>       /*
>        * Indicate DDR mode (if supported).
>        */
>       if (mmc_card_highspeed(card)) {
>               if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
>                       && (host->caps & (MMC_CAP_1_8V_DDR)))
>                               ddr = MMC_1_8V_DDR_MODE;
>               else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
>                       && (host->caps & (MMC_CAP_1_2V_DDR)))
>                               ddr = MMC_1_2V_DDR_MODE;
>       }
>
>       /*
>        * Activate wide bus and DDR (if supported).
>        */
>       if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
>           (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
>               unsigned ext_csd_bit, bus_width;
>               int temp_caps = host->caps & (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA);
>
>               do {
>                       if (temp_caps & MMC_CAP_8_BIT_DATA) {
>                               ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
>                               bus_width = MMC_BUS_WIDTH_8;
>                       } else {
>                               ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
>                               bus_width = MMC_BUS_WIDTH_4;
>                       }
>
>                       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                                        EXT_CSD_BUS_WIDTH, ext_csd_bit);
>                       if (err) {
>                               printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
>                                          "failed\n", mmc_hostname(card->host),
>                                          1 << bus_width, ddr);
>                               err = 0;
>                       } else {
>                               mmc_set_bus_width_ddr(card->host, bus_width, MMC_SDR_MODE);
>                               if (mmc_test_bus_width (card, 1<<bus_width))
>                                       break;
>                       }
>
>                       if (bus_width == MMC_BUS_WIDTH_8)
>                               temp_caps &= ~MMC_CAP_8_BIT_DATA;
>                       else
>                               temp_caps &= ~MMC_CAP_4_BIT_DATA;
>
>                       if (temp_caps == 0) {
>                               ext_csd_bit = EXT_CSD_BUS_WIDTH_1;
>                               bus_width = MMC_BUS_WIDTH_1;
>                       }
>               } while (temp_caps);
>
>               if (temp_caps == 0) {
>                       ext_csd_bit = EXT_CSD_BUS_WIDTH_1;
>                       bus_width = MMC_BUS_WIDTH_1;
>               }
>               else if (temp_caps & MMC_CAP_8_BIT_DATA) {
>                       if (ddr)
>                               ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8;
>                       else
>                               ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
>                       bus_width = MMC_BUS_WIDTH_8;
>               } else {
>                       if (ddr)
>                               ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4;
>                       else
>                               ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
>                       bus_width = MMC_BUS_WIDTH_4;
>               }
>
>               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                                EXT_CSD_BUS_WIDTH, ext_csd_bit);
>
>               if (ddr) {
>                       mmc_card_set_ddr_mode(card);
>                       mmc_set_bus_width_ddr(card->host, bus_width, ddr);
>               } else
>                       mmc_set_bus_width_ddr(card->host, bus_width, MMC_SDR_MODE);
>
>               if (err && err != -EBADMSG)
>                       goto free_card;
>       }
>
>       if (!oldcard)
>               host->card = card;
>
>       return 0;
>
> free_card:
>       if (!oldcard)
>               mmc_remove_card(card);
> err:
>
>       return err;
> }
>
>
> from mmc_ops.c
> =============
> int mmc_test_bus_width(struct mmc_card *card, int bits)
> {
>       struct mmc_request mrq;
>       struct mmc_command cmd;
>       struct mmc_data data;
>       struct scatterlist sg;
>       int len;
>       u8 test_data_write[8];
>       u8 test_data_read[64];
>
>       switch (bits) {
>       case 8:
>               test_data_write[0] = 0x55;
>               test_data_write[1] = 0xaa;
>               test_data_write[2] = 0x00;
>               test_data_write[3] = 0x00;
>               test_data_write[4] = 0x00;
>               test_data_write[5] = 0x00;
>               test_data_write[6] = 0x00;
>               test_data_write[7] = 0x00;
>               len = 8;
>               break;
>       case 4:
>               test_data_write[0] = 0x5a;
>               test_data_write[1] = 0x00;
>               test_data_write[2] = 0x00;
>               test_data_write[3] = 0x00;
>               len = 4;
>               break;
>       default:
>               return 0;
>       }
>
>       memset(&mrq, 0, sizeof(struct mmc_request));
>       memset(&cmd, 0, sizeof(struct mmc_command));
>       memset(&data, 0, sizeof(struct mmc_data));
>
>       cmd.opcode = MMC_BUSTEST_W;
>       cmd.arg = 0;
>       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
>
>       data.flags = MMC_DATA_WRITE;
>       data.blksz = 64;
>       data.blocks = 1;
>       data.sg = &sg;
>       data.sg_len = 1;
>
>       mrq.cmd = &cmd;
>       mrq.data = &data;
>
>       sg_init_one(&sg, &test_data_write, 64);
>
>       /*
>        * The spec states that MMC_BUSTEST_W and BUSTEST_R accesses have a timeout
>        * of 64 clock cycles.
>        */
>       data.timeout_ns = 0;
>       data.timeout_clks = 64;
>
>       mmc_wait_for_req(card->host, &mrq);
>
>       if (cmd.error || data.error ) {
>               printk(KERN_INFO "Failed to send CMD19: %d %d\n", cmd.error, data.error);
>               return 0;
>       }
>
>       /* Now read back */
>       memset(&mrq, 0, sizeof(struct mmc_request));
>       memset(&cmd, 0, sizeof(struct mmc_command));
>       memset(&data, 0, sizeof(struct mmc_data));
>       memset (&test_data_read, 0, sizeof(test_data_read));
>
>       cmd.opcode = MMC_BUSTEST_R;
>       cmd.arg = 0;
>       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
>
>       data.flags = MMC_DATA_READ;
>       data.blksz = sizeof(test_data_read);
>       data.blocks = 1;
>       data.sg = &sg;
>       data.sg_len = 1;
>
>       mrq.cmd = &cmd;
>       mrq.data = &data;
>
>       sg_init_one(&sg, &test_data_read, sizeof(test_data_read));
>
>       /*
>        * The spec states that MMC_BUSTEST_W and BUSTEST_R accesses have a timeout
>        * of 64 clock cycles.
>        */
>       data.timeout_ns = 0;
>       data.timeout_clks = 64;
>
>       mmc_wait_for_req(card->host, &mrq);
>
>       if (cmd.error) {
>               printk(KERN_INFO "Failed to send CMD14: %d %d\n", cmd.error, data.error);
>               return 0;
>       }
>
> #if 0
> #warning PRINT RESULTS FROM CMD14
>       printk (KERN_INFO "%s: Got %02X %02X %02X %02X\n", __FUNCTION__,
>               test_data_read[0],
>               test_data_read[1],
>               test_data_read[2],
>               test_data_read[3]);
> #endif
>
>       switch (bits) {
>       case 8:
>               return (test_data_read[0] == 0xaa && test_data_read[1] == 0x55);
>       case 4:
>               return (test_data_read[0] == 0xa5);
>       }
>       return 0;
> }



Diff made against linux-next (see below) and tested against marvell mmp2 controller using mmp2
marvell linux

eMMC cards do not have a card specific field indicating the bus width that they support.
The bus width needs to be figured out by probing the bus.

JEDEC STANDARD
Embedded MultiMediaCard(e•MMC) e•MMC/Card Product Standard, High Capacity,
including Reliable Write, Boot, Sleep Modes, Dual Data Rate, Multiple Partitions Supports,
Security Enhancement, Background Operation and High Priority Interrupt (MMCA, 4.41)
JESD84-A441

defines what needs to be done in Annex A.8.3.

In earlier testing (2.6.2x) this code did not work on some PCIe SD controllers.
We define a new MMC_CAP: MMC_CAP_BUS_WIDTH_WORKS that the host adaptation
layer can set if the controller can support bus width testing.  If the CAP is not defined the
behavior defaults to what is done today; the largest bit width is selected.

Transcend 1GB and 2GB  MMC cards work when this code is enabled and fail otherwise.

Signed-off-by: Philip Rakity <prakity@xxxxxxxxxxx>

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 77f93c3..d20237b 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -531,12 +531,57 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,

        /*
         * Activate wide bus and DDR (if supported).
+        * Determine mmc bus width supported by probing card (if supported)
         */
        if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
            (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
                unsigned ext_csd_bit, bus_width;
+               int temp_caps = host->caps & (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA);

-               if (host->caps & MMC_CAP_8_BIT_DATA) {
+               do {
+                       if (temp_caps & MMC_CAP_8_BIT_DATA) {
+                               ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
+                               bus_width = MMC_BUS_WIDTH_8;
+                       } else {
+                               ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
+                               bus_width = MMC_BUS_WIDTH_4;
+                       }
+
+                       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                                        EXT_CSD_BUS_WIDTH, ext_csd_bit);
+                       if (err) {
+                               printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
+                                          "failed\n", mmc_hostname(card->host),
+                                          1 << bus_width, ddr);
+                               err = 0;
+                       } else {
+                               mmc_set_bus_width_ddr(card->host, bus_width, MMC_SDR_MODE);
+                               /*
+                                * if controller can't handle bus width test
+                                * try to use the highest bus width to
+                                * maintain compatibility with previous linux
+                                */
+                               if ((host->caps & MMC_CAP_BUS_WIDTH_WORKS) == 0)
+                                       break;
+                               if (mmc_test_bus_width (card, 1<<bus_width))
+                                       break;
+                       }
+
+                       if (bus_width == MMC_BUS_WIDTH_8)
+                               temp_caps &= ~MMC_CAP_8_BIT_DATA;
+                       else
+                               temp_caps &= ~MMC_CAP_4_BIT_DATA;
+
+                       if (temp_caps == 0) {
+                               ext_csd_bit = EXT_CSD_BUS_WIDTH_1;
+                               bus_width = MMC_BUS_WIDTH_1;
+                       }
+               } while (temp_caps);
+
+               if (temp_caps == 0) {
+                       ext_csd_bit = EXT_CSD_BUS_WIDTH_1;
+                       bus_width = MMC_BUS_WIDTH_1;
+               } else if (temp_caps & MMC_CAP_8_BIT_DATA) {
                        if (ddr)
                                ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8;
                        else
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 326447c..5795e1b 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -20,6 +20,126 @@
 #include "core.h"
 #include "mmc_ops.h"

+int mmc_test_bus_width(struct mmc_card *card, int bits)
+{
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+       int len;
+       u8 test_data_write[8];
+       u8 test_data_read[64];
+
+       switch (bits) {
+       case 8:
+               test_data_write[0] = 0x55;
+               test_data_write[1] = 0xaa;
+               test_data_write[2] = 0x00;
+               test_data_write[3] = 0x00;
+               test_data_write[4] = 0x00;
+               test_data_write[5] = 0x00;
+               test_data_write[6] = 0x00;
+               test_data_write[7] = 0x00;
+               len = 8;
+               break;
+       case 4:
+               test_data_write[0] = 0x5a;
+               test_data_write[1] = 0x00;
+               test_data_write[2] = 0x00;
+               test_data_write[3] = 0x00;
+               len = 4;
+               break;
+       default:
+               /* 1 bit bus cards ALWAYS work */
+               return 1;
+       }
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       cmd.opcode = MMC_BUSTEST_W;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.flags = MMC_DATA_WRITE;
+       data.blksz = len;
+       data.blocks = 1;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       sg_init_one(&sg, &test_data_write, len);
+
+       /*
+        * The spec states that MMC_BUSTEST_W and BUSTEST_R accesses
+        * have a maximum timeout of 64 clock cycles.
+        */
+       data.timeout_ns = 0;
+       data.timeout_clks = 64;
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error || data.error ) {
+               printk(KERN_INFO "%s: Failed to send (BUSTEST_W) CMD19: %d %d\n",
+                       mmc_hostname(card->host), cmd.error, data.error);
+       }
+
+       /* Now read back */
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+       memset (&test_data_read, 0, sizeof(test_data_read));
+
+       cmd.opcode = MMC_BUSTEST_R;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.flags = MMC_DATA_READ;
+       data.blksz = len;
+       data.blocks = 1;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       sg_init_one(&sg, &test_data_read, len);
+
+       data.timeout_ns = 0;
+       data.timeout_clks = 64;
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error) {
+               printk(KERN_INFO "%s: Failed to send CMD14: %d %d\n",
+                       mmc_hostname(card->host), cmd.error, data.error);
+               return 0;
+       }
+
+#if 0
+#warning PRINT RESULTS FROM CMD14
+       printk (KERN_INFO "%s: Bits = %d, Got %02X %02X %02X %02X\n", __FUNCTION__,
+               bits,
+               test_data_read[0],
+               test_data_read[1],
+               test_data_read[2],
+               test_data_read[3]);
+#endif
+
+       switch (bits) {
+       case 8:
+               return (test_data_read[0] == 0xaa && test_data_read[1] == 0x55);
+       case 4:
+               return (test_data_read[0] == 0xa5);
+       case 1:
+               return (test_data_read[0] == 0x80);
+       }
+       return 0;
+}
+
 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 {
        int err;
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 653eb8e..c08b9ad 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -26,6 +26,7 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid);
 int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
 int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
 int mmc_card_sleepawake(struct mmc_host *host, int sleep);
+int mmc_test_bus_width(struct mmc_card *card, int bits);

 #endif

diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 53496bb..1e3d9d2 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -169,6 +169,7 @@ struct mmc_host {
 #define MMC_CAP_1_2V_DDR       (1 << 12)       /* can support */
                                                /* DDR mode at 1.2V */

+#define MMC_CAP_BUS_WIDTH_WORKS        (1 << 13)       /* CMD14/CMD19 bus width ok */
        mmc_pm_flag_t           pm_caps;        /* supported pm features */

 #ifdef CONFIG_MMC_CLKGATE
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 956fbd8..8e0d047 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -40,7 +40,9 @@
 #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_BUSTEST_R            14   /* adtc                    R1  */
 #define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
+#define MMC_BUSTEST_W            19   /* adtc                    R1  */
 #define MMC_SPI_READ_OCR         58   /* spi                  spi_R3 */
 #define MMC_SPI_CRC_ON_OFF       59   /* spi  [0:0] flag      spi_R1 */


>

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux