]> 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>
Mon, 17 Feb 2014 19:16:08 +0000 (14:16 -0500)
committerTom Rini <trini@ti.com>
Mon, 17 Feb 2014 19:16:08 +0000 (14:16 -0500)
15 files changed:
arch/arm/cpu/armv7/omap-common/boot-common.c
arch/arm/include/asm/arch-exynos/dwmmc.h
board/ti/dra7xx/README [new file with mode: 0644]
board/ti/omap5_uevm/README [new file with mode: 0644]
common/cmd_mmc.c
common/spl/spl_mmc.c
drivers/mmc/dw_mmc.c
drivers/mmc/exynos_dw_mmc.c
drivers/mmc/mmc.c
drivers/mmc/zynq_sdhci.c
include/configs/dra7xx_evm.h
include/configs/omap5_uevm.h
include/dwmmc.h
include/mmc.h
include/spl.h

index 69fff323d3602163784da3898b6c2e0c16ba0dc9..52e0f4a6cf52a21e8b78d52f5b87c6fae3965d57 100644 (file)
@@ -66,7 +66,18 @@ u32 spl_boot_device(void)
 
 u32 spl_boot_mode(void)
 {
-       return gd->arch.omap_boot_params.omap_bootmode;
+       u32 val = gd->arch.omap_boot_params.omap_bootmode;
+
+       if (val == MMCSD_MODE_RAW)
+               return MMCSD_MODE_RAW;
+       else if (val == MMCSD_MODE_FAT)
+               return MMCSD_MODE_FAT;
+       else
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+               return MMCSD_MODE_EMMCBOOT;
+#else
+               return MMCSD_MODE_UNDEFINED;
+#endif
 }
 
 void spl_board_init(void)
index 09d739dfca998a5e1ddd3e2fa5e05bad2158fbfc..a7ca12c477e2689e361085286f6d20f581f4358f 100644 (file)
 #define MPSCTRL_ENCRYPTION             (0x1<<1)
 #define MPSCTRL_VALID                  (0x1<<0)
 
+/* CLKSEL Register */
+#define DWMCI_DIVRATIO_BIT             24
+#define DWMCI_DIVRATIO_MASK            0x7
+
 #ifdef CONFIG_OF_CONTROL
 int exynos_dwmmc_init(const void *blob);
 #endif
diff --git a/board/ti/dra7xx/README b/board/ti/dra7xx/README
new file mode 100644 (file)
index 0000000..2fdaeac
--- /dev/null
@@ -0,0 +1,25 @@
+Summary
+=======
+
+This document covers various features of the 'dra7xx_evm' build and some
+related uses.
+
+eMMC boot partition use
+=======================
+
+It is possible, depending on SYSBOOT configuration to boot from the eMMC
+boot partitions using (name depending on documentation referenced)
+Alternative Boot operation mode or Boot Sequence Option 1/2.  In this
+example we load MLO and u-boot.img from the build into DDR and then use
+'mmc bootbus' to set the required rate (see TRM) and 'mmc partconfig' to
+set boot0 as the boot device.
+U-Boot # setenv autoload no
+U-Boot # usb start
+U-Boot # dhcp
+U-Boot # mmc dev 1 1
+U-Boot # tftp ${loadaddr} dra7xx/MLO
+U-Boot # mmc write ${loadaddr} 0 100
+U-Boot # tftp ${loadaddr} dra7xx/u-boot.img
+U-Boot # mmc write ${loadaddr} 300 400
+U-Boot # mmc bootbus 1 2 0 2
+U-Boot # mmc partconf 1 1 1 0
diff --git a/board/ti/omap5_uevm/README b/board/ti/omap5_uevm/README
new file mode 100644 (file)
index 0000000..970e2ec
--- /dev/null
@@ -0,0 +1,25 @@
+Summary
+=======
+
+This document covers various features of the 'omap5_uevm' build and some
+related uses.
+
+eMMC boot partition use
+=======================
+
+It is possible, depending on SYSBOOT configuration to boot from the eMMC
+boot partitions using (name depending on documentation referenced)
+Alternative Boot operation mode or Boot Sequence Option 1/2.  In this
+example we load MLO and u-boot.img from the build into DDR and then use
+'mmc bootbus' to set the required rate (see TRM) and 'mmc partconfig' to
+set boot0 as the boot device.
+U-Boot # setenv autoload no
+U-Boot # usb start
+U-Boot # dhcp
+U-Boot # mmc dev 1 1
+U-Boot # tftp ${loadaddr} omap5uevm/MLO
+U-Boot # mmc write ${loadaddr} 0 100
+U-Boot # tftp ${loadaddr} omap5uevm/u-boot.img
+U-Boot # mmc write ${loadaddr} 300 400
+U-Boot # mmc bootbus 1 2 0 2
+U-Boot # mmc partconf 1 1 1 0
index da5fef9db9dd936a995a92e04826a69fe0521635..2d51927060280bfc0289f00b5514131075829dd7 100644 (file)
@@ -131,36 +131,6 @@ U_BOOT_CMD(
        "- display info of the current MMC device"
 );
 
-#ifdef CONFIG_SUPPORT_EMMC_BOOT
-static int boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
-{
-       int err;
-       err = mmc_boot_part_access(mmc, ack, part_num, access);
-
-       if ((err == 0) && (access != 0)) {
-               printf("\t\t\t!!!Notice!!!\n");
-
-               printf("!You must close EMMC boot Partition");
-               printf("after all images are written\n");
-
-               printf("!EMMC boot partition has continuity");
-               printf("at image writing time.\n");
-
-               printf("!So, do not close the boot partition");
-               printf("before all images are written.\n");
-               return 0;
-       } else if ((err == 0) && (access == 0))
-               return 0;
-       else if ((err != 0) && (access != 0)) {
-               printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
-               return 1;
-       } else {
-               printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
-               return 1;
-       }
-}
-#endif
-
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        enum mmc_state state;
@@ -195,7 +165,7 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        return 1;
                else
                        return 0;
-       } else if (strncmp(argv[1], "part", 4) == 0) {
+       } else if (strcmp(argv[1], "part") == 0) {
                block_dev_desc_t *mmc_dev;
                struct mmc *mmc;
 
@@ -273,15 +243,16 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
                return 0;
 #ifdef CONFIG_SUPPORT_EMMC_BOOT
-       } else if ((strcmp(argv[1], "open") == 0) ||
-                       (strcmp(argv[1], "close") == 0)) {
+       } else if (strcmp(argv[1], "partconf") == 0) {
                int dev;
                struct mmc *mmc;
-               u8 part_num, access = 0;
+               u8 ack, part_num, access;
 
-               if (argc == 4) {
+               if (argc == 6) {
                        dev = simple_strtoul(argv[2], NULL, 10);
-                       part_num = simple_strtoul(argv[3], NULL, 10);
+                       ack = simple_strtoul(argv[3], NULL, 10);
+                       part_num = simple_strtoul(argv[4], NULL, 10);
+                       access = simple_strtoul(argv[5], NULL, 10);
                } else {
                        return CMD_RET_USAGE;
                }
@@ -293,32 +264,53 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                }
 
                if (IS_SD(mmc)) {
-                       printf("SD device cannot be opened/closed\n");
+                       puts("PARTITION_CONFIG only exists on eMMC\n");
                        return 1;
                }
 
-               if ((part_num <= 0) || (part_num > MMC_NUM_BOOT_PARTITION)) {
-                       printf("Invalid boot partition number:\n");
-                       printf("Boot partition number cannot be <= 0\n");
-                       printf("EMMC44 supports only 2 boot partitions\n");
+               /* acknowledge to be sent during boot operation */
+               return mmc_set_part_conf(mmc, ack, part_num, access);
+       } else if (strcmp(argv[1], "bootbus") == 0) {
+               int dev;
+               struct mmc *mmc;
+               u8 width, reset, mode;
+
+               if (argc == 6) {
+                       dev = simple_strtoul(argv[2], NULL, 10);
+                       width = simple_strtoul(argv[3], NULL, 10);
+                       reset = simple_strtoul(argv[4], NULL, 10);
+                       mode = simple_strtoul(argv[5], NULL, 10);
+               } else {
+                       return CMD_RET_USAGE;
+               }
+
+               mmc = find_mmc_device(dev);
+               if (!mmc) {
+                       printf("no mmc device at slot %x\n", dev);
                        return 1;
                }
 
-               if (strcmp(argv[1], "open") == 0)
-                       access = part_num; /* enable R/W access to boot part*/
-               else
-                       access = 0; /* No access to boot partition */
+               if (IS_SD(mmc)) {
+                       puts("BOOT_BUS_WIDTH only exists on eMMC\n");
+                       return 1;
+               }
 
                /* acknowledge to be sent during boot operation */
-               return boot_part_access(mmc, 1, part_num, access);
-
-       } else if (strcmp(argv[1], "bootpart") == 0) {
+               return mmc_set_boot_bus_width(mmc, width, reset, mode);
+       } else if (strcmp(argv[1], "bootpart-resize") == 0) {
                int dev;
-               dev = simple_strtoul(argv[2], NULL, 10);
+               struct mmc *mmc;
+               u32 bootsize, rpmbsize;
 
-               u32 bootsize = simple_strtoul(argv[3], NULL, 10);
-               u32 rpmbsize = simple_strtoul(argv[4], NULL, 10);
-               struct mmc *mmc = find_mmc_device(dev);
+               if (argc == 5) {
+                       dev = simple_strtoul(argv[2], NULL, 10);
+                       bootsize = simple_strtoul(argv[3], NULL, 10);
+                       rpmbsize = simple_strtoul(argv[4], NULL, 10);
+               } else {
+                       return CMD_RET_USAGE;
+               }
+
+               mmc = find_mmc_device(dev);
                if (!mmc) {
                        printf("no mmc device at slot %x\n", dev);
                        return 1;
@@ -438,12 +430,12 @@ U_BOOT_CMD(
        "mmc dev [dev] [part] - show or set current mmc device [partition]\n"
        "mmc list - lists available devices\n"
 #ifdef CONFIG_SUPPORT_EMMC_BOOT
-       "mmc open <dev> <boot_partition>\n"
-       " - Enable boot_part for booting and enable R/W access of boot_part\n"
-       "mmc close <dev> <boot_partition>\n"
-       " - Enable boot_part for booting and disable access to boot_part\n"
-       "mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n"
-       " - change sizes of boot and RPMB partitions of specified device\n"
+       "mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
+       " - Set the BOOT_BUS_WIDTH field of the specified device\n"
+       "mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
+       " - Change sizes of boot and RPMB partitions of specified device\n"
+       "mmc partconf dev boot_ack boot_partition partition_access\n"
+       " - Change the bits of the PARTITION_CONFIG field of the specified device\n"
 #endif
        "mmc setdsr - set DSR register value\n"
        );
index 13fbff082cfe48bc4b846228d6463db3e7b342f0..fa6f891bc805e30bd64723a9ca98f352cf38af45 100644 (file)
@@ -110,6 +110,30 @@ void spl_mmc_load_image(void)
                err = spl_load_image_fat(&mmc->block_dev,
                                        CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION,
                                        CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
+#endif
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+       } else if (boot_mode == MMCSD_MODE_EMMCBOOT) {
+               /*
+                * We need to check what the partition is configured to.
+                * 1 and 2 match up to boot0 / boot1 and 7 is user data
+                * which is the first physical partition (0).
+                */
+               int part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
+
+               if (part == 7)
+                       part = 0;
+
+               if (mmc_switch_part(0, part)) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
+                       puts("MMC partition switch failed\n");
+#endif
+                       hang();
+               }
+#ifdef CONFIG_SPL_OS_BOOT
+               if (spl_start_uboot() || mmc_load_image_raw_os(mmc))
+#endif
+               err = mmc_load_image_raw(mmc,
+                       CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
 #endif
        } else {
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
index 4cec5aaa604b0fdba8bedbfed149e2405a6e7ded..d45c15cfa4e539887cd2500cf12ee4c85efb9cd6 100644 (file)
@@ -237,7 +237,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
         * host->bus_hz should be set from user.
         */
        if (host->get_mmc_clk)
-               sclk = host->get_mmc_clk(host->dev_index);
+               sclk = host->get_mmc_clk(host);
        else if (host->bus_hz)
                sclk = host->bus_hz;
        else {
index b3e5c5e5e09b5db5d04bfac1b8bd3093b9d3d655..de8cdcc42b3db83f631b358f24e90cc1d2c5dbed 100644 (file)
@@ -29,9 +29,22 @@ static void exynos_dwmci_clksel(struct dwmci_host *host)
        dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val);
 }
 
-unsigned int exynos_dwmci_get_clk(int dev_index)
+unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
 {
-       return get_mmc_clk(dev_index);
+       unsigned long sclk;
+       int8_t clk_div;
+
+       /*
+        * Since SDCLKIN is divided inside controller by the DIVRATIO
+        * value set in the CLKSEL register, we need to use the same output
+        * clock value to calculate the CLKDIV value.
+        * as per user manual:cclk_in = SDCLKIN / (DIVRATIO + 1)
+        */
+       clk_div = ((dwmci_readl(host, DWMCI_CLKSEL) >> DWMCI_DIVRATIO_BIT)
+                       & DWMCI_DIVRATIO_MASK) + 1;
+       sclk = get_mmc_clk(host->dev_index);
+
+       return sclk / clk_div;
 }
 
 static void exynos_dwmci_board_init(struct dwmci_host *host)
index c6a1c23fbf1cdf268d79bf1da3a7a3ed80dd220c..8ab0bc948f5f22c8fa3827c5d6fdb8af9c397eaf 100644 (file)
@@ -430,7 +430,7 @@ int mmc_complete_op_cond(struct mmc *mmc)
        mmc->ocr = cmd.response[0];
 
        mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
-       mmc->rca = 0;
+       mmc->rca = 1;
 
        return 0;
 }
@@ -1442,67 +1442,44 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
 }
 
 /*
- * This function shall form and send the commands to open / close the
- * boot partition specified by user.
- *
- * Input Parameters:
- * ack: 0x0 - No boot acknowledge sent (default)
- *     0x1 - Boot acknowledge sent during boot operation
- * part_num: User selects boot data that will be sent to master
- *     0x0 - Device not boot enabled (default)
- *     0x1 - Boot partition 1 enabled for boot
- *     0x2 - Boot partition 2 enabled for boot
- * access: User selects partitions to access
- *     0x0 : No access to boot partition (default)
- *     0x1 : R/W boot partition 1
- *     0x2 : R/W boot partition 2
- *     0x3 : R/W Replay Protected Memory Block (RPMB)
+ * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
+ * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
+ * and BOOT_MODE.
  *
  * Returns 0 on success.
  */
-int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
 {
        int err;
-       struct mmc_cmd cmd;
 
-       /* Boot ack enable, boot partition enable , boot partition access */
-       cmd.cmdidx = MMC_CMD_SWITCH;
-       cmd.resp_type = MMC_RSP_R1b;
-
-       cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                       (EXT_CSD_PART_CONF << 16) |
-                       ((EXT_CSD_BOOT_ACK(ack) |
-                       EXT_CSD_BOOT_PART_NUM(part_num) |
-                       EXT_CSD_PARTITION_ACCESS(access)) << 8);
+       err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
+                        EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
+                        EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
+                        EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
 
-       err = mmc_send_cmd(mmc, &cmd, NULL);
-       if (err) {
-               if (access) {
-                       debug("mmc boot partition#%d open fail:Error1 = %d\n",
-                             part_num, err);
-               } else {
-                       debug("mmc boot partition#%d close fail:Error = %d\n",
-                             part_num, err);
-               }
+       if (err)
                return err;
-       }
+       return 0;
+}
 
-       if (access) {
-               /* 4bit transfer mode at booting time. */
-               cmd.cmdidx = MMC_CMD_SWITCH;
-               cmd.resp_type = MMC_RSP_R1b;
+/*
+ * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
+ * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
+ * PARTITION_ACCESS.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+       int err;
 
-               cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                               (EXT_CSD_BOOT_BUS_WIDTH << 16) |
-                               ((1 << 0) << 8);
+       err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+                        EXT_CSD_BOOT_ACK(ack) |
+                        EXT_CSD_BOOT_PART_NUM(part_num) |
+                        EXT_CSD_PARTITION_ACCESS(access));
 
-               err = mmc_send_cmd(mmc, &cmd, NULL);
-               if (err) {
-                       debug("mmc boot partition#%d open fail:Error2 = %d\n",
-                             part_num, err);
-                       return err;
-               }
-       }
+       if (err)
+               return err;
        return 0;
 }
 #endif
index 610bef5cbaeff45c37f70031017fba83b5accb14..72a272f2ba0ee0c63d674b11c28881b477b1ebd7 100644 (file)
@@ -23,7 +23,8 @@ int zynq_sdhci_init(u32 regbase)
 
        host->name = "zynq_sdhci";
        host->ioaddr = (void *)regbase;
-       host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD;
+       host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD |
+                      SDHCI_QUIRK_BROKEN_R1B;
        host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
        host->host_caps = MMC_MODE_HC;
index f210ed8b92429bd8be1b40d21c8155d0c3b5ba3c..3c53f0af10ba222da4680430cc65ba3158139c90 100644 (file)
@@ -73,6 +73,8 @@
 #define CONFIG_SPL_SPI_CS              0
 #define CONFIG_SYS_SPI_U_BOOT_OFFS     0x20000
 
+#define CONFIG_SUPPORT_EMMC_BOOT
+
 /* USB xHCI HOST */
 #define CONFIG_CMD_USB
 #define CONFIG_USB_HOST
index 76c5106b45eaaf55a682083f0fc1bfa9eab2511a..3df502eda02e628d27980c7e5f904cc4b3392102 100644 (file)
@@ -37,6 +37,7 @@
 #define CONFIG_PARTITION_UUIDS
 #define CONFIG_CMD_PART
 #define CONFIG_HSMMC2_8BIT
+#define CONFIG_SUPPORT_EMMC_BOOT
 
 /* Required support for the TCA642X GPIO we have on the uEVM */
 #define CONFIG_TCA642X
index a02dd67c1370f05cdc5b6571d2070ec5dc0e66cb..b64155851d6491a5093068848c8fe5627d62e363 100644 (file)
@@ -142,7 +142,7 @@ struct dwmci_host {
 
        void (*clksel)(struct dwmci_host *host);
        void (*board_init)(struct dwmci_host *host);
-       unsigned int (*get_mmc_clk)(int dev_index);
+       unsigned int (*get_mmc_clk)(struct dwmci_host *host);
 };
 
 struct dwmci_idmac {
index e1060b9ff2794f5b3ebb77b14321ccad1c499d54..e95a2376d20001ff71e667daf4505e92afc688a7 100644 (file)
 #define EXT_CSD_BOOT_PART_NUM(x)       (x << 3)
 #define EXT_CSD_PARTITION_ACCESS(x)    (x << 0)
 
+#define EXT_CSD_BOOT_BUS_WIDTH_MODE(x) (x << 3)
+#define EXT_CSD_BOOT_BUS_WIDTH_RESET(x)        (x << 2)
+#define EXT_CSD_BOOT_BUS_WIDTH_WIDTH(x)        (x)
 
 #define R1_ILLEGAL_COMMAND             (1 << 22)
 #define R1_APP_CMD                     (1 << 5)
@@ -310,8 +313,10 @@ int mmc_set_dsr(struct mmc *mmc, u16 val);
 /* Function to change the size of boot partition and rpmb partitions */
 int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
                                        unsigned long rpmbsize);
-/* Function to send commands to open/close the specified boot partition */
-int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access);
+/* Function to modify the PARTITION_CONFIG field of EXT_CSD */
+int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access);
+/* Function to modify the BOOT_BUS_WIDTH field of EXT_CSD */
+int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode);
 
 /**
  * Start device initialization and return immediately; it does not block on
index 5e248561f13791ade05d69dea96f5315410cb20c..dad00c0075d9b6904d1db8248c8464e6cd7e2e03 100644 (file)
@@ -16,6 +16,7 @@
 #define MMCSD_MODE_UNDEFINED   0
 #define MMCSD_MODE_RAW         1
 #define MMCSD_MODE_FAT         2
+#define MMCSD_MODE_EMMCBOOT    3
 
 struct spl_image_info {
        const char *name;