]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-mmc
authorTom Rini <trini@ti.com>
Fri, 20 Sep 2013 18:06:10 +0000 (14:06 -0400)
committerTom Rini <trini@ti.com>
Fri, 20 Sep 2013 18:06:10 +0000 (14:06 -0400)
12 files changed:
common/spl/spl_mmc.c
drivers/mmc/Makefile
drivers/mmc/dw_mmc.c
drivers/mmc/mmc.c
drivers/mmc/mmc_private.h [new file with mode: 0644]
drivers/mmc/mmc_write.c [new file with mode: 0644]
drivers/mmc/omap_hsmmc.c
drivers/mmc/s5p_sdhci.c
drivers/mmc/sdhci.c
include/common.h
include/mmc.h
include/sdhci.h

index f27b4c277b645ed0555a6df27fb3e04d9e9a240b..fc2f2260f888a308d26d7a63fb5db6e5b95b78df 100644 (file)
@@ -9,7 +9,6 @@
 #include <common.h>
 #include <spl.h>
 #include <asm/u-boot.h>
-#include <asm/utils.h>
 #include <mmc.h>
 #include <fat.h>
 #include <version.h>
@@ -45,8 +44,10 @@ static int mmc_load_image_raw(struct mmc *mmc, unsigned long sector)
                                        (void *)spl_image.load_addr);
 
 end:
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
        if (err == 0)
                printf("spl: mmc blk read err - %lu\n", err);
+#endif
 
        return (err == 0);
 }
@@ -58,7 +59,9 @@ static int mmc_load_image_raw_os(struct mmc *mmc)
                                       CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
                                       CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
                                       (void *)CONFIG_SYS_SPL_ARGS_ADDR)) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                printf("mmc args blk read error\n");
+#endif
                return -1;
        }
 
@@ -84,9 +87,11 @@ static int mmc_load_image_fat(struct mmc *mmc, const char *filename)
        err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0);
 
 end:
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
        if (err <= 0)
                printf("spl: error reading image %s, err - %d\n",
                       filename, err);
+#endif
 
        return (err <= 0);
 }
@@ -99,8 +104,10 @@ static int mmc_load_image_fat_os(struct mmc *mmc)
        err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME,
                            (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0);
        if (err <= 0) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                printf("spl: error reading image %s, err - %d\n",
                       CONFIG_SPL_FAT_LOAD_ARGS_NAME, err);
+#endif
                return -1;
        }
 
@@ -120,13 +127,17 @@ void spl_mmc_load_image(void)
        /* We register only one device. So, the dev id is always 0 */
        mmc = find_mmc_device(0);
        if (!mmc) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                puts("spl: mmc device not found!!\n");
+#endif
                hang();
        }
 
        err = mmc_init(mmc);
        if (err) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                printf("spl: mmc init failed: err - %d\n", err);
+#endif
                hang();
        }
 
@@ -145,7 +156,9 @@ void spl_mmc_load_image(void)
                err = fat_register_device(&mmc->block_dev,
                                          CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION);
                if (err) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                        printf("spl: fat register err - %d\n", err);
+#endif
                        hang();
                }
 
@@ -155,7 +168,9 @@ void spl_mmc_load_image(void)
                err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
 #endif
        } else {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                puts("spl: wrong MMC boot mode\n");
+#endif
                hang();
        }
 
index bedf833f70dfac17344af3195cfb33582c96ab34..06280d1fa6bb65d62b7873f04505992f85f371ec 100644 (file)
@@ -34,6 +34,8 @@ COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
 COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
 ifdef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
+else
+COBJS-$(CONFIG_GENERIC_MMC) += mmc_write.o
 endif
 
 COBJS  := $(COBJS-y)
index a82ee17a2503b51f8991f4171a1e9f45840dd80b..9a803a02d4f989b968e30cb076784bf04b6bba6e 100644 (file)
@@ -41,12 +41,11 @@ static void dwmci_set_idma_desc(struct dwmci_idmac *idmac,
 }
 
 static void dwmci_prepare_data(struct dwmci_host *host,
-               struct mmc_data *data)
+               struct mmc_data *data, struct dwmci_idmac *cur_idmac)
 {
        unsigned long ctrl;
        unsigned int i = 0, flags, cnt, blk_cnt;
        ulong data_start, data_end, start_addr;
-       ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, data->blocks);
 
 
        blk_cnt = data->blocks;
@@ -73,7 +72,7 @@ static void dwmci_prepare_data(struct dwmci_host *host,
                dwmci_set_idma_desc(cur_idmac, flags, cnt,
                                start_addr + (i * PAGE_SIZE));
 
-               if(blk_cnt < 8)
+               if (blk_cnt <= 8)
                        break;
                blk_cnt -= 8;
                cur_idmac++;
@@ -111,6 +110,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
                struct mmc_data *data)
 {
        struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
+       ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
+                                data ? DIV_ROUND_UP(data->blocks, 8) : 0);
        int flags = 0, i;
        unsigned int timeout = 100000;
        u32 retry = 10000;
@@ -127,7 +128,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
 
        if (data)
-               dwmci_prepare_data(host, data);
+               dwmci_prepare_data(host, data, cur_idmac);
 
        dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
index 55026759ede4d41cbb26e2096a965e87e9b812b6..84dae4d8bd8055d9f5cd78a6b421d7413a61f24c 100644 (file)
@@ -15,6 +15,7 @@
 #include <malloc.h>
 #include <linux/list.h>
 #include <div64.h>
+#include "mmc_private.h"
 
 /* Set block count limit because of 16 bit register limit on some hardware*/
 #ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
@@ -52,14 +53,10 @@ int __board_mmc_getcd(struct mmc *mmc) {
 int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
        alias("__board_mmc_getcd")));
 
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
-                       struct mmc_data *data)
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
-       struct mmc_data backup;
        int ret;
 
-       memset(&backup, 0, sizeof(backup));
-
 #ifdef CONFIG_MMC_TRACE
        int i;
        u8 *ptr;
@@ -114,7 +111,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        return ret;
 }
 
-static int mmc_send_status(struct mmc *mmc, int timeout)
+int mmc_send_status(struct mmc *mmc, int timeout)
 {
        struct mmc_cmd cmd;
        int err, retries = 5;
@@ -135,8 +132,10 @@ static int mmc_send_status(struct mmc *mmc, int timeout)
                             MMC_STATE_PRG)
                                break;
                        else if (cmd.response[0] & MMC_STATUS_MASK) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                                printf("Status Error: 0x%08X\n",
                                        cmd.response[0]);
+#endif
                                return COMM_ERR;
                        }
                } else if (--retries < 0)
@@ -151,14 +150,16 @@ static int mmc_send_status(struct mmc *mmc, int timeout)
        printf("CURR STATE:%d\n", status);
 #endif
        if (timeout <= 0) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                printf("Timeout waiting card ready\n");
+#endif
                return TIMEOUT;
        }
 
        return 0;
 }
 
-static int mmc_set_blocklen(struct mmc *mmc, int len)
+int mmc_set_blocklen(struct mmc *mmc, int len)
 {
        struct mmc_cmd cmd;
 
@@ -181,179 +182,13 @@ struct mmc *find_mmc_device(int dev_num)
                        return m;
        }
 
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
        printf("MMC Device %d not found\n", dev_num);
+#endif
 
        return NULL;
 }
 
-static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
-{
-       struct mmc_cmd cmd;
-       ulong end;
-       int err, start_cmd, end_cmd;
-
-       if (mmc->high_capacity)
-               end = start + blkcnt - 1;
-       else {
-               end = (start + blkcnt - 1) * mmc->write_bl_len;
-               start *= mmc->write_bl_len;
-       }
-
-       if (IS_SD(mmc)) {
-               start_cmd = SD_CMD_ERASE_WR_BLK_START;
-               end_cmd = SD_CMD_ERASE_WR_BLK_END;
-       } else {
-               start_cmd = MMC_CMD_ERASE_GROUP_START;
-               end_cmd = MMC_CMD_ERASE_GROUP_END;
-       }
-
-       cmd.cmdidx = start_cmd;
-       cmd.cmdarg = start;
-       cmd.resp_type = MMC_RSP_R1;
-
-       err = mmc_send_cmd(mmc, &cmd, NULL);
-       if (err)
-               goto err_out;
-
-       cmd.cmdidx = end_cmd;
-       cmd.cmdarg = end;
-
-       err = mmc_send_cmd(mmc, &cmd, NULL);
-       if (err)
-               goto err_out;
-
-       cmd.cmdidx = MMC_CMD_ERASE;
-       cmd.cmdarg = SECURE_ERASE;
-       cmd.resp_type = MMC_RSP_R1b;
-
-       err = mmc_send_cmd(mmc, &cmd, NULL);
-       if (err)
-               goto err_out;
-
-       return 0;
-
-err_out:
-       puts("mmc erase failed\n");
-       return err;
-}
-
-static unsigned long
-mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
-{
-       int err = 0;
-       struct mmc *mmc = find_mmc_device(dev_num);
-       lbaint_t blk = 0, blk_r = 0;
-       int timeout = 1000;
-
-       if (!mmc)
-               return -1;
-
-       if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
-               printf("\n\nCaution! Your devices Erase group is 0x%x\n"
-                      "The erase range would be change to "
-                      "0x" LBAF "~0x" LBAF "\n\n",
-                      mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
-                      ((start + blkcnt + mmc->erase_grp_size)
-                      & ~(mmc->erase_grp_size - 1)) - 1);
-
-       while (blk < blkcnt) {
-               blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
-                       mmc->erase_grp_size : (blkcnt - blk);
-               err = mmc_erase_t(mmc, start + blk, blk_r);
-               if (err)
-                       break;
-
-               blk += blk_r;
-
-               /* Waiting for the ready status */
-               if (mmc_send_status(mmc, timeout))
-                       return 0;
-       }
-
-       return blk;
-}
-
-static ulong
-mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
-{
-       struct mmc_cmd cmd;
-       struct mmc_data data;
-       int timeout = 1000;
-
-       if ((start + blkcnt) > mmc->block_dev.lba) {
-               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
-                       start + blkcnt, mmc->block_dev.lba);
-               return 0;
-       }
-
-       if (blkcnt == 0)
-               return 0;
-       else if (blkcnt == 1)
-               cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
-       else
-               cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
-
-       if (mmc->high_capacity)
-               cmd.cmdarg = start;
-       else
-               cmd.cmdarg = start * mmc->write_bl_len;
-
-       cmd.resp_type = MMC_RSP_R1;
-
-       data.src = src;
-       data.blocks = blkcnt;
-       data.blocksize = mmc->write_bl_len;
-       data.flags = MMC_DATA_WRITE;
-
-       if (mmc_send_cmd(mmc, &cmd, &data)) {
-               printf("mmc write failed\n");
-               return 0;
-       }
-
-       /* SPI multiblock writes terminate using a special
-        * token, not a STOP_TRANSMISSION request.
-        */
-       if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
-               cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
-               cmd.cmdarg = 0;
-               cmd.resp_type = MMC_RSP_R1b;
-               if (mmc_send_cmd(mmc, &cmd, NULL)) {
-                       printf("mmc fail to send stop cmd\n");
-                       return 0;
-               }
-       }
-
-       /* Waiting for the ready status */
-       if (mmc_send_status(mmc, timeout))
-               return 0;
-
-       return blkcnt;
-}
-
-static ulong
-mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
-{
-       lbaint_t cur, blocks_todo = blkcnt;
-
-       struct mmc *mmc = find_mmc_device(dev_num);
-       if (!mmc)
-               return 0;
-
-       if (mmc_set_blocklen(mmc, mmc->write_bl_len))
-               return 0;
-
-       do {
-               cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
-               if(mmc_write_blocks(mmc, start, cur, src) != cur)
-                       return 0;
-               blocks_todo -= cur;
-               start += cur;
-               src += cur * mmc->write_bl_len;
-       } while (blocks_todo > 0);
-
-       return blkcnt;
-}
-
 static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
                           lbaint_t blkcnt)
 {
@@ -385,7 +220,9 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
                cmd.cmdarg = 0;
                cmd.resp_type = MMC_RSP_R1b;
                if (mmc_send_cmd(mmc, &cmd, NULL)) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                        printf("mmc fail to send stop cmd\n");
+#endif
                        return 0;
                }
        }
@@ -405,8 +242,10 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
                return 0;
 
        if ((start + blkcnt) > mmc->block_dev.lba) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
                        start + blkcnt, mmc->block_dev.lba);
+#endif
                return 0;
        }
 
@@ -1268,6 +1107,7 @@ static int mmc_startup(struct mmc *mmc)
        mmc->block_dev.blksz = mmc->read_bl_len;
        mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
        mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
        sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
                mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
                (mmc->cid[3] >> 16) & 0xffff);
@@ -1277,6 +1117,11 @@ static int mmc_startup(struct mmc *mmc)
                (mmc->cid[2] >> 24) & 0xff);
        sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
                (mmc->cid[2] >> 16) & 0xf);
+#else
+       mmc->block_dev.vendor[0] = 0;
+       mmc->block_dev.product[0] = 0;
+       mmc->block_dev.revision[0] = 0;
+#endif
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
        init_part(&mmc->block_dev);
 #endif
@@ -1343,7 +1188,9 @@ int mmc_start_init(struct mmc *mmc)
 
        if (mmc_getcd(mmc) == 0) {
                mmc->has_init = 0;
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                printf("MMC: no card present\n");
+#endif
                return NO_CARD_ERR;
        }
 
@@ -1378,7 +1225,9 @@ int mmc_start_init(struct mmc *mmc)
                err = mmc_send_op_cond(mmc);
 
                if (err && err != IN_PROGRESS) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                        printf("Card did not respond to voltage select!\n");
+#endif
                        return UNUSABLE_ERR;
                }
        }
@@ -1434,6 +1283,8 @@ static int __def_mmc_init(bd_t *bis)
 int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
 int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
 
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+
 void print_mmc_devices(char separator)
 {
        struct mmc *m;
@@ -1451,6 +1302,10 @@ void print_mmc_devices(char separator)
        printf("\n");
 }
 
+#else
+void print_mmc_devices(char separator) { }
+#endif
+
 int get_mmc_num(void)
 {
        return cur_dev_num;
diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
new file mode 100644 (file)
index 0000000..16dcf9f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008,2010 Freescale Semiconductor, Inc
+ * Andy Fleming
+ *
+ * Based (loosely) on the Linux code
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _MMC_PRIVATE_H_
+#define _MMC_PRIVATE_H_
+
+#include <mmc.h>
+
+extern int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+                       struct mmc_data *data);
+extern int mmc_send_status(struct mmc *mmc, int timeout);
+extern int mmc_set_blocklen(struct mmc *mmc, int len);
+
+#ifndef CONFIG_SPL_BUILD
+
+extern unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt);
+
+extern ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt,
+               const void *src);
+
+#else /* CONFIG_SPL_BUILD */
+
+/* SPL will never write or erase, declare dummies to reduce code size. */
+
+static inline unsigned long mmc_berase(int dev_num, lbaint_t start,
+               lbaint_t blkcnt)
+{
+       return 0;
+}
+
+static inline ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt,
+               const void *src)
+{
+       return 0;
+}
+
+#endif /* CONFIG_SPL_BUILD */
+
+#endif /* _MMC_PRIVATE_H_ */
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
new file mode 100644 (file)
index 0000000..aa2fdef
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2008, Freescale Semiconductor, Inc
+ * Andy Fleming
+ *
+ * Based vaguely on the Linux code
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <part.h>
+#include "mmc_private.h"
+
+static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
+{
+       struct mmc_cmd cmd;
+       ulong end;
+       int err, start_cmd, end_cmd;
+
+       if (mmc->high_capacity) {
+               end = start + blkcnt - 1;
+       } else {
+               end = (start + blkcnt - 1) * mmc->write_bl_len;
+               start *= mmc->write_bl_len;
+       }
+
+       if (IS_SD(mmc)) {
+               start_cmd = SD_CMD_ERASE_WR_BLK_START;
+               end_cmd = SD_CMD_ERASE_WR_BLK_END;
+       } else {
+               start_cmd = MMC_CMD_ERASE_GROUP_START;
+               end_cmd = MMC_CMD_ERASE_GROUP_END;
+       }
+
+       cmd.cmdidx = start_cmd;
+       cmd.cmdarg = start;
+       cmd.resp_type = MMC_RSP_R1;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err)
+               goto err_out;
+
+       cmd.cmdidx = end_cmd;
+       cmd.cmdarg = end;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err)
+               goto err_out;
+
+       cmd.cmdidx = MMC_CMD_ERASE;
+       cmd.cmdarg = SECURE_ERASE;
+       cmd.resp_type = MMC_RSP_R1b;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err)
+               goto err_out;
+
+       return 0;
+
+err_out:
+       puts("mmc erase failed\n");
+       return err;
+}
+
+unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
+{
+       int err = 0;
+       struct mmc *mmc = find_mmc_device(dev_num);
+       lbaint_t blk = 0, blk_r = 0;
+       int timeout = 1000;
+
+       if (!mmc)
+               return -1;
+
+       if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
+               printf("\n\nCaution! Your devices Erase group is 0x%x\n"
+                      "The erase range would be change to "
+                      "0x" LBAF "~0x" LBAF "\n\n",
+                      mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
+                      ((start + blkcnt + mmc->erase_grp_size)
+                      & ~(mmc->erase_grp_size - 1)) - 1);
+
+       while (blk < blkcnt) {
+               blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
+                       mmc->erase_grp_size : (blkcnt - blk);
+               err = mmc_erase_t(mmc, start + blk, blk_r);
+               if (err)
+                       break;
+
+               blk += blk_r;
+
+               /* Waiting for the ready status */
+               if (mmc_send_status(mmc, timeout))
+                       return 0;
+       }
+
+       return blk;
+}
+
+static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
+               lbaint_t blkcnt, const void *src)
+{
+       struct mmc_cmd cmd;
+       struct mmc_data data;
+       int timeout = 1000;
+
+       if ((start + blkcnt) > mmc->block_dev.lba) {
+               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
+                      start + blkcnt, mmc->block_dev.lba);
+               return 0;
+       }
+
+       if (blkcnt == 0)
+               return 0;
+       else if (blkcnt == 1)
+               cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
+       else
+               cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
+
+       if (mmc->high_capacity)
+               cmd.cmdarg = start;
+       else
+               cmd.cmdarg = start * mmc->write_bl_len;
+
+       cmd.resp_type = MMC_RSP_R1;
+
+       data.src = src;
+       data.blocks = blkcnt;
+       data.blocksize = mmc->write_bl_len;
+       data.flags = MMC_DATA_WRITE;
+
+       if (mmc_send_cmd(mmc, &cmd, &data)) {
+               printf("mmc write failed\n");
+               return 0;
+       }
+
+       /* SPI multiblock writes terminate using a special
+        * token, not a STOP_TRANSMISSION request.
+        */
+       if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
+               cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
+               cmd.cmdarg = 0;
+               cmd.resp_type = MMC_RSP_R1b;
+               if (mmc_send_cmd(mmc, &cmd, NULL)) {
+                       printf("mmc fail to send stop cmd\n");
+                       return 0;
+               }
+       }
+
+       /* Waiting for the ready status */
+       if (mmc_send_status(mmc, timeout))
+               return 0;
+
+       return blkcnt;
+}
+
+ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src)
+{
+       lbaint_t cur, blocks_todo = blkcnt;
+
+       struct mmc *mmc = find_mmc_device(dev_num);
+       if (!mmc)
+               return 0;
+
+       if (mmc_set_blocklen(mmc, mmc->write_bl_len))
+               return 0;
+
+       do {
+               cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
+               if (mmc_write_blocks(mmc, start, cur, src) != cur)
+                       return 0;
+               blocks_todo -= cur;
+               start += cur;
+               src += cur * mmc->write_bl_len;
+       } while (blocks_todo > 0);
+
+       return blkcnt;
+}
index 975b2c5ba4d74b1ae875a205341efec5bd233e82..d3a8b5303d534efbfc68fd412635e5e082798a27 100644 (file)
@@ -288,6 +288,30 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit)
 
        mmc_reg_out(&mmc_base->sysctl, bit, bit);
 
+       /*
+        * CMD(DAT) lines reset procedures are slightly different
+        * for OMAP3 and OMAP4(AM335x,OMAP5,DRA7xx).
+        * According to OMAP3 TRM:
+        * Set SRC(SRD) bit in MMCHS_SYSCTL register to 0x1 and wait until it
+        * returns to 0x0.
+        * According to OMAP4(AM335x,OMAP5,DRA7xx) TRMs, CMD(DATA) lines reset
+        * procedure steps must be as follows:
+        * 1. Initiate CMD(DAT) line reset by writing 0x1 to SRC(SRD) bit in
+        *    MMCHS_SYSCTL register (SD_SYSCTL for AM335x).
+        * 2. Poll the SRC(SRD) bit until it is set to 0x1.
+        * 3. Wait until the SRC (SRD) bit returns to 0x0
+        *    (reset procedure is completed).
+        */
+#if defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
+       defined(CONFIG_AM33XX)
+       if (!(readl(&mmc_base->sysctl) & bit)) {
+               start = get_timer(0);
+               while (!(readl(&mmc_base->sysctl) & bit)) {
+                       if (get_timer(0) - start > MAX_RETRY_MS)
+                               return;
+               }
+       }
+#endif
        start = get_timer(0);
        while ((readl(&mmc_base->sysctl) & bit) != 0) {
                if (get_timer(0) - start > MAX_RETRY_MS) {
@@ -376,6 +400,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        }
 
        writel(cmd->cmdarg, &mmc_base->arg);
+       udelay(20);             /* To fix "No status update" error on eMMC */
        writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd);
 
        start = get_timer(0);
@@ -480,7 +505,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
        unsigned int count;
 
        /*
-        * Start Polled Read
+        * Start Polled Write
         */
        count = (size > MMCSD_SECTOR_SIZE) ? MMCSD_SECTOR_SIZE : size;
        count /= 4;
@@ -586,6 +611,8 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 {
        struct mmc *mmc = &hsmmc_dev[dev_index];
        struct omap_hsmmc_data *priv_data = &hsmmc_dev_data[dev_index];
+       uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
+                            MMC_MODE_HC;
 
        sprintf(mmc->name, "OMAP SD/MMC");
        mmc->send_cmd = mmc_send_cmd;
@@ -600,11 +627,20 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 #ifdef OMAP_HSMMC2_BASE
        case 1:
                priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE;
+#if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
+     defined(CONFIG_DRA7XX)) && defined(CONFIG_HSMMC2_8BIT)
+               /* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */
+               host_caps_val |= MMC_MODE_8BIT;
+#endif
                break;
 #endif
 #ifdef OMAP_HSMMC3_BASE
        case 2:
                priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE;
+#if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT)
+               /* Enable 8-bit interface for eMMC on DRA7XX */
+               host_caps_val |= MMC_MODE_8BIT;
+#endif
                break;
 #endif
        default:
@@ -620,8 +656,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
                mmc->getwp = omap_mmc_getwp;
 
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
-       mmc->host_caps = (MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
-                               MMC_MODE_HC) & ~host_caps_mask;
+       mmc->host_caps = host_caps_val & ~host_caps_mask;
 
        mmc->f_min = 400000;
 
index 7f89403b432f87155d95d8ef4618a8a5b18e1968..40ff8739bfeae6ba48bb2f9497d61f8d8061afb3 100644 (file)
@@ -72,7 +72,7 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
 
        host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
                SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR |
-               SDHCI_QUIRK_WAIT_SEND_CMD;
+               SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8;
        host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
        host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
@@ -81,6 +81,8 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
        host->index = index;
 
        host->host_caps = MMC_MODE_HC;
+       if (bus_width == 8)
+               host->host_caps |= MMC_MODE_8BIT;
 
        return add_sdhci(host, 52000000, 400000);
 }
index 42619916e5c3a80afa6b4579877a48667a88fd2c..dfb2eeeb4de8321004afeddf8358ea9909ed62b1 100644 (file)
@@ -68,10 +68,9 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
        unsigned int stat, rdy, mask, timeout, block = 0;
 #ifdef CONFIG_MMC_SDMA
        unsigned char ctrl;
-       ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
+       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
        ctrl &= ~SDHCI_CTRL_DMA_MASK;
-       ctrl |= SDHCI_CTRL_SDMA;
-       sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
+       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 #endif
 
        timeout = 1000000;
@@ -254,7 +253,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
        if (clock == 0)
                return 0;
 
-       if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
+       if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
                /* Version 3.00 divisors must be a multiple of 2. */
                if (mmc->f_max <= clock)
                        div = 1;
@@ -347,10 +346,11 @@ void sdhci_set_ios(struct mmc *mmc)
        ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
        if (mmc->bus_width == 8) {
                ctrl &= ~SDHCI_CTRL_4BITBUS;
-               if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
+               if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) ||
+                               (host->quirks & SDHCI_QUIRK_USE_WIDE8))
                        ctrl |= SDHCI_CTRL_8BITBUS;
        } else {
-               if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
+               if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
                        ctrl &= ~SDHCI_CTRL_8BITBUS;
                if (mmc->bus_width == 4)
                        ctrl |= SDHCI_CTRL_4BITBUS;
@@ -437,7 +437,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
        if (max_clk)
                mmc->f_max = max_clk;
        else {
-               if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
+               if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
                        mmc->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
                                >> SDHCI_CLOCK_BASE_SHIFT;
                else
@@ -452,7 +452,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
        if (min_clk)
                mmc->f_min = min_clk;
        else {
-               if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
+               if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
                        mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_300;
                else
                        mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_200;
@@ -470,7 +470,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
                mmc->voltages |= host->voltages;
 
        mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
-       if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
+       if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
                if (caps & SDHCI_CAN_DO_8BIT)
                        mmc->host_caps |= MMC_MODE_8BIT;
        }
index 6aa2398229381c54f746e53879c76f1712ae3060..0d40fab0410a1d075c65a3c052b8bc7658a2b584 100644 (file)
@@ -1015,10 +1015,10 @@ static inline phys_addr_t map_to_sysmem(void *ptr)
  * of a function scoped static buffer.  It can not be used to create a cache
  * line aligned global buffer.
  */
-#define PAD_COUNT(s, pad) ((s - 1) / pad + 1)
+#define PAD_COUNT(s, pad) (((s) - 1) / (pad) + 1)
 #define PAD_SIZE(s, pad) (PAD_COUNT(s, pad) * pad)
 #define ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, pad)           \
-       char __##name[ROUND(PAD_SIZE(size * sizeof(type), pad), align)  \
+       char __##name[ROUND(PAD_SIZE((size) * sizeof(type), pad), align)  \
                      + (align - 1)];                                   \
                                                                        \
        type *name = (type *) ALIGN((uintptr_t)__##name, align)
index 228d77139d5682e9f249a0f8ff21e8bee9625150..214b9edc8d22144b009178af3e13829ccc92ebe5 100644 (file)
@@ -335,7 +335,11 @@ int mmc_start_init(struct mmc *mmc);
 void mmc_set_preinit(struct mmc *mmc, int preinit);
 
 #ifdef CONFIG_GENERIC_MMC
+#ifdef CONFIG_MMC_SPI
 #define mmc_host_is_spi(mmc)   ((mmc)->host_caps & MMC_MODE_SPI)
+#else
+#define mmc_host_is_spi(mmc)   0
+#endif
 struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
 #else
 int mmc_legacy_init(int verbose);
index b18b87312b7ae2d5605b2d6724e3ee56729136c2..74d06ae18a229ff7182249815ba53ec17cdfb166 100644 (file)
 #define   SDHCI_SPEC_200       1
 #define   SDHCI_SPEC_300       2
 
+#define SDHCI_GET_VERSION(x) (x->version & SDHCI_SPEC_VER_MASK)
+
 /*
  * End of controller registers.
  */
 #define SDHCI_QUIRK_NO_CD              (1 << 5)
 #define SDHCI_QUIRK_WAIT_SEND_CMD      (1 << 6)
 #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 7)
+#define SDHCI_QUIRK_USE_WIDE8          (1 << 8)
 
 /* to make gcc happy */
 struct sdhci_host;