]> git.sur5r.net Git - u-boot/commitdiff
mmc: add a library function to send tuning command
authorJean-Jacques Hiblot <jjhiblot@ti.com>
Thu, 21 Sep 2017 14:30:12 +0000 (16:30 +0200)
committerJaehoon Chung <jh80.chung@samsung.com>
Fri, 12 Jan 2018 09:11:04 +0000 (18:11 +0900)
HS200/SDR104 requires tuning command to be sent to the card.
Add a simple function to send tuning command and to read and
compare the received data with the tuning block pattern.
This function can be used by platform driver to perform DLL
tuning.
This patch is similar to
commit 996903de92f0 ("mmc: core: add core-level function for
sending tuning commands") added in linux kernel.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
drivers/mmc/mmc.c
include/mmc.h

index 877ce1757da38bce892e0d6c319e29d39a5e7bf9..ab2483e9dbade19baa2d276750ea3a6c896c3fb6 100644 (file)
@@ -308,6 +308,74 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
        return err;
 }
 
+static const u8 tuning_blk_pattern_4bit[] = {
+       0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
+       0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
+       0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
+       0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
+       0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
+       0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
+       0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
+       0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
+};
+
+static const u8 tuning_blk_pattern_8bit[] = {
+       0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+       0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
+       0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
+       0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
+       0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
+       0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
+       0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
+       0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
+       0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
+       0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
+       0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
+       0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
+       0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
+       0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
+       0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
+       0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
+};
+
+int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error)
+{
+       struct mmc_cmd cmd;
+       struct mmc_data data;
+       const u8 *tuning_block_pattern;
+       int size, err;
+
+       if (mmc->bus_width == 8) {
+               tuning_block_pattern = tuning_blk_pattern_8bit;
+               size = sizeof(tuning_blk_pattern_8bit);
+       } else if (mmc->bus_width == 4) {
+               tuning_block_pattern = tuning_blk_pattern_4bit;
+               size = sizeof(tuning_blk_pattern_4bit);
+       } else {
+               return -EINVAL;
+       }
+
+       ALLOC_CACHE_ALIGN_BUFFER(u8, data_buf, size);
+
+       cmd.cmdidx = opcode;
+       cmd.cmdarg = 0;
+       cmd.resp_type = MMC_RSP_R1;
+
+       data.dest = (void *)data_buf;
+       data.blocks = 1;
+       data.blocksize = size;
+       data.flags = MMC_DATA_READ;
+
+       err = mmc_send_cmd(mmc, &cmd, &data);
+       if (err)
+               return err;
+
+       if (memcmp(data_buf, tuning_block_pattern, size))
+               return -EIO;
+
+       return 0;
+}
+
 static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
                           lbaint_t blkcnt)
 {
index c11f69859ed708e77f033b54c66d1030a7da08f8..79be6b4bc34b61cf082906712d7a666a8a81d84b 100644 (file)
@@ -650,6 +650,7 @@ void mmc_destroy(struct mmc *mmc);
 int mmc_unbind(struct udevice *dev);
 int mmc_initialize(bd_t *bis);
 int mmc_init(struct mmc *mmc);
+int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
 
 /**