Commit 18c83588 authored by Tom Rini's avatar Tom Rini

Merge branch 'master' of git://git.denx.de/u-boot-mmc

parents 22a240c3 b818d9ab
......@@ -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)
......
......@@ -23,6 +23,10 @@
#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
......
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
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
......@@ -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"
);
......
......@@ -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
......
......@@ -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 {
......
......@@ -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)
......
......@@ -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
......@@ -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;
......
......@@ -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
......
......@@ -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
......
......@@ -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 {
......
......@@ -187,6 +187,9 @@
#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
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment