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

This commit is contained in:
Tom Rini 2012-09-12 10:26:06 -07:00
commit a9ae14fce3
17 changed files with 129 additions and 49 deletions

View File

@ -64,11 +64,11 @@
#define SDHCI_CTRL4_DRIVE_MASK(_x) ((_x) << 16)
#define SDHCI_CTRL4_DRIVE_SHIFT (16)
int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks);
int s5p_sdhci_init(u32 regbase, int index, int bus_width);
static inline unsigned int s5p_mmc_init(int index, int bus_width)
{
unsigned int base = samsung_get_base_mmc() + (0x10000 * index);
return s5p_sdhci_init(base, 52000000, 400000, index);
return s5p_sdhci_init(base, index, bus_width);
}
#endif

View File

@ -64,11 +64,11 @@
#define SDHCI_CTRL4_DRIVE_MASK(_x) ((_x) << 16)
#define SDHCI_CTRL4_DRIVE_SHIFT (16)
int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks);
int s5p_sdhci_init(u32 regbase, int index, int bus_width);
static inline unsigned int s5p_mmc_init(int index, int bus_width)
{
unsigned int base = samsung_get_base_mmc() + (0x10000 * index);
return s5p_sdhci_init(base, 52000000, 400000, index);
return s5p_sdhci_init(base, index, bus_width);
}
#endif

View File

@ -144,8 +144,7 @@ int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
U_BOOT_CMD(
mmcinfo, 1, 0, do_mmcinfo,
"display MMC info",
" - device number of the device to dislay info of\n"
""
"- dislay info of the current MMC device"
);
int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

View File

@ -75,9 +75,28 @@ static int init_mmc_for_env(struct mmc *mmc)
return -1;
}
#ifdef CONFIG_SYS_MMC_ENV_PART
if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) {
if (mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV,
CONFIG_SYS_MMC_ENV_PART)) {
puts("MMC partition switch failed\n");
return -1;
}
}
#endif
return 0;
}
static void fini_mmc_for_env(struct mmc *mmc)
{
#ifdef CONFIG_SYS_MMC_ENV_PART
if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num)
mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV,
mmc->part_num);
#endif
}
#ifdef CONFIG_CMD_SAVEENV
static inline int write_env(struct mmc *mmc, unsigned long size,
unsigned long offset, const void *buffer)
@ -100,26 +119,38 @@ int saveenv(void)
char *res;
struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
u32 offset;
int ret;
if (init_mmc_for_env(mmc) || mmc_get_env_addr(mmc, &offset))
if (init_mmc_for_env(mmc))
return 1;
if (mmc_get_env_addr(mmc, &offset)) {
ret = 1;
goto fini;
}
res = (char *)&env_new->data;
len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
if (len < 0) {
error("Cannot export environment: errno = %d\n", errno);
return 1;
ret = 1;
goto fini;
}
env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE);
printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV);
if (write_env(mmc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) {
puts("failed\n");
return 1;
ret = 1;
goto fini;
}
puts("done\n");
return 0;
ret = 0;
fini:
fini_mmc_for_env(mmc);
return ret;
}
#endif /* CONFIG_CMD_SAVEENV */
@ -143,13 +174,30 @@ void env_relocate_spec(void)
ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
u32 offset;
int ret;
if (init_mmc_for_env(mmc) || mmc_get_env_addr(mmc, &offset))
return set_default_env(NULL);
if (init_mmc_for_env(mmc)) {
ret = 1;
goto err;
}
if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf))
return set_default_env(NULL);
if (mmc_get_env_addr(mmc, &offset)) {
ret = 1;
goto fini;
}
if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) {
ret = 1;
goto fini;
}
env_import(buf, 1);
ret = 0;
fini:
fini_mmc_for_env(mmc);
err:
if (ret)
set_default_env(NULL);
#endif
}

View File

@ -52,7 +52,7 @@ static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
debug("CMD%d time out\n", cmd->cmdidx);
return TIMEOUT;
} else if ((hoststatus & SDI_STA_CCRCFAIL) &&
(cmd->flags & MMC_RSP_CRC)) {
(cmd->resp_type & MMC_RSP_CRC)) {
printf("CMD%d CRC error\n", cmd->cmdidx);
return -EILSEQ;
}

View File

@ -236,7 +236,7 @@ int mmc_send_status(struct mmc *mmc, int timeout)
status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
printf("CURR STATE:%d\n", status);
#endif
if (!timeout) {
if (timeout <= 0) {
printf("Timeout waiting card ready\n");
return TIMEOUT;
}
@ -658,7 +658,7 @@ int mmc_send_op_cond(struct mmc *mmc)
}
int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
{
struct mmc_cmd cmd;
struct mmc_data data;
@ -669,7 +669,7 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 0;
data.dest = ext_csd;
data.dest = (char *)ext_csd;
data.blocks = 1;
data.blocksize = 512;
data.flags = MMC_DATA_READ;
@ -704,7 +704,7 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
int mmc_change_freq(struct mmc *mmc)
{
ALLOC_CACHE_ALIGN_BUFFER(char, ext_csd, 512);
ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, 512);
char cardtype;
int err;
@ -963,8 +963,8 @@ int mmc_startup(struct mmc *mmc)
uint mult, freq;
u64 cmult, csize, capacity;
struct mmc_cmd cmd;
ALLOC_CACHE_ALIGN_BUFFER(char, ext_csd, 512);
ALLOC_CACHE_ALIGN_BUFFER(char, test_csd, 512);
ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, 512);
ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, 512);
int timeout = 1000;
#ifdef CONFIG_MMC_SPI_CRC_ON
@ -1137,7 +1137,8 @@ int mmc_startup(struct mmc *mmc)
}
/* store the partition info of emmc */
if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT)
if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
ext_csd[EXT_CSD_BOOT_MULT])
mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
}
@ -1232,7 +1233,9 @@ int mmc_startup(struct mmc *mmc)
(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
sprintf(mmc->block_dev.revision, "%d.%d", mmc->cid[2] >> 28,
(mmc->cid[2] >> 24) & 0xf);
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
init_part(&mmc->block_dev);
#endif
return 0;
}
@ -1283,10 +1286,9 @@ int mmc_register(struct mmc *mmc)
block_dev_desc_t *mmc_get_dev(int dev)
{
struct mmc *mmc = find_mmc_device(dev);
if (!mmc)
if (!mmc || mmc_init(mmc))
return NULL;
mmc_init(mmc);
return &mmc->block_dev;
}
#endif

View File

@ -118,7 +118,7 @@ static int pxa_mmc_start_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
int ret;
/* The card can send a "busy" response */
if (cmd->flags & MMC_RSP_BUSY)
if (cmd->resp_type & MMC_RSP_BUSY)
cmdat |= MMC_CMDAT_BUSY;
/* Inform the controller about response type */
@ -181,9 +181,11 @@ static int pxa_mmc_cmd_done(struct mmc *mmc, struct mmc_cmd *cmd)
/* The command response didn't arrive */
if (stat & MMC_STAT_TIME_OUT_RESPONSE)
return -ETIMEDOUT;
else if (stat & MMC_STAT_RES_CRC_ERROR && cmd->flags & MMC_RSP_CRC) {
else if (stat & MMC_STAT_RES_CRC_ERROR
&& cmd->resp_type & MMC_RSP_CRC) {
#ifdef PXAMMC_CRC_SKIP
if (cmd->flags & MMC_RSP_136 && cmd->response[0] & (1 << 31))
if (cmd->resp_type & MMC_RSP_136
&& cmd->response[0] & (1 << 31))
printf("Ignoring CRC, this may be dangerous!\n");
else
#endif

View File

@ -21,6 +21,7 @@
#include <malloc.h>
#include <sdhci.h>
#include <asm/arch/mmc.h>
#include <asm/arch/clk.h>
static char *S5P_NAME = "SAMSUNG SDHCI";
static void s5p_sdhci_set_control_reg(struct sdhci_host *host)
@ -54,7 +55,7 @@ static void s5p_sdhci_set_control_reg(struct sdhci_host *host)
* 00 = Delay3 (inverter delay)
* 10 = Delay4 (inverter delay + 2ns)
*/
val = SDHCI_CTRL3_FCSEL3 | SDHCI_CTRL3_FCSEL1;
val = SDHCI_CTRL3_FCSEL0 | SDHCI_CTRL3_FCSEL1;
sdhci_writel(host, val, SDHCI_CONTROL3);
/*
@ -69,7 +70,7 @@ static void s5p_sdhci_set_control_reg(struct sdhci_host *host)
sdhci_writel(host, ctrl, SDHCI_CONTROL2);
}
int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks)
int s5p_sdhci_init(u32 regbase, int index, int bus_width)
{
struct sdhci_host *host = NULL;
host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
@ -80,19 +81,18 @@ int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks)
host->name = S5P_NAME;
host->ioaddr = (void *)regbase;
host->quirks = quirks;
host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE;
host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR;
host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
if (quirks & SDHCI_QUIRK_REG32_RW)
host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
else
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
host->set_control_reg = &s5p_sdhci_set_control_reg;
host->set_clock = set_mmc_clk;
host->index = index;
host->host_caps = MMC_MODE_HC;
add_sdhci(host, max_clk, min_clk);
add_sdhci(host, 52000000, 400000);
return 0;
}

View File

@ -260,7 +260,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
if (clock == 0)
return 0;
if (host->version >= SDHCI_SPEC_300) {
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
/* Version 3.00 divisors must be a multiple of 2. */
if (mmc->f_max <= clock)
div = 1;
@ -279,6 +279,9 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
}
div >>= 1;
if (host->set_clock)
host->set_clock(host->index, div);
clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
<< SDHCI_DIVIDER_HI_SHIFT;
@ -347,10 +350,10 @@ 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_300)
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
ctrl |= SDHCI_CTRL_8BITBUS;
} else {
if (host->version >= SDHCI_SPEC_300)
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
ctrl &= ~SDHCI_CTRL_8BITBUS;
if (mmc->bus_width == 4)
ctrl |= SDHCI_CTRL_4BITBUS;
@ -381,12 +384,25 @@ int sdhci_init(struct mmc *mmc)
}
}
sdhci_set_power(host, fls(mmc->voltages) - 1);
if (host->quirks & SDHCI_QUIRK_NO_CD) {
unsigned int status;
sdhci_writel(host, SDHCI_CTRL_CD_TEST_INS | SDHCI_CTRL_CD_TEST,
SDHCI_HOST_CONTROL);
status = sdhci_readl(host, SDHCI_PRESENT_STATE);
while ((!(status & SDHCI_CARD_PRESENT)) ||
(!(status & SDHCI_CARD_STATE_STABLE)) ||
(!(status & SDHCI_CARD_DETECT_PIN_LEVEL)))
status = sdhci_readl(host, SDHCI_PRESENT_STATE);
}
/* Eable all state */
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_ENABLE);
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_SIGNAL_ENABLE);
sdhci_set_power(host, fls(mmc->voltages) - 1);
return 0;
}
@ -421,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_300)
if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
mmc->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
>> SDHCI_CLOCK_BASE_SHIFT;
else
@ -436,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_300)
if ((host->version & SDHCI_SPEC_VER_MASK) >= 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;

View File

@ -593,7 +593,7 @@ int mmcif_mmc_init(void)
mmc->f_max = CLKDEV_EMMC_DATA;
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
MMC_MODE_8BIT;
MMC_MODE_8BIT | MMC_MODE_HC;
memcpy(mmc->name, DRIVER_NAME, sizeof(DRIVER_NAME));
mmc->send_cmd = sh_mmcif_request;
mmc->set_ios = sh_mmcif_set_ios;

View File

@ -51,8 +51,9 @@
/* Environment in eMMC, at the end of 2nd "boot sector" */
#define CONFIG_ENV_IS_IN_MMC
#define CONFIG_ENV_OFFSET ((2 * 1024 * 1024) - CONFIG_ENV_SIZE)
#define CONFIG_ENV_OFFSET ((1024 * 1024) - CONFIG_ENV_SIZE)
#define CONFIG_SYS_MMC_ENV_DEV 0
#define CONFIG_SYS_MMC_ENV_PART 2
/* USB Host support */
#define CONFIG_USB_EHCI

View File

@ -77,8 +77,9 @@
/* Environment in eMMC, at the end of 2nd "boot sector" */
#define CONFIG_ENV_IS_IN_MMC
#define CONFIG_ENV_OFFSET ((2 * 512 * 1024) - CONFIG_ENV_SIZE)
#define CONFIG_ENV_OFFSET ((512 * 1024) - CONFIG_ENV_SIZE)
#define CONFIG_SYS_MMC_ENV_DEV 0
#define CONFIG_SYS_MMC_ENV_PART 2
/* USB Host support */
#define CONFIG_USB_EHCI

View File

@ -78,6 +78,7 @@
#define CONFIG_MMC
#define CONFIG_S5P_SDHCI
#define CONFIG_SDHCI
#define CONFIG_MMC_SDMA
/* PWM */
#define CONFIG_PWM

View File

@ -58,8 +58,9 @@
/* Environment in eMMC, at the end of 2nd "boot sector" */
#define CONFIG_ENV_IS_IN_MMC
#define CONFIG_ENV_OFFSET ((2 * 1024 * 1024) - CONFIG_ENV_SIZE)
#define CONFIG_ENV_OFFSET ((1024 * 1024) - CONFIG_ENV_SIZE)
#define CONFIG_SYS_MMC_ENV_DEV 0
#define CONFIG_SYS_MMC_ENV_PART 2
/* USB Host support */
#define CONFIG_USB_EHCI

View File

@ -72,8 +72,9 @@
* particular card is standard practice as far as I know.
*/
#define CONFIG_ENV_IS_IN_MMC
#define CONFIG_ENV_OFFSET ((2 * 512 * 1024) - CONFIG_ENV_SIZE)
#define CONFIG_ENV_OFFSET ((512 * 1024) - CONFIG_ENV_SIZE)
#define CONFIG_SYS_MMC_ENV_DEV 0
#define CONFIG_SYS_MMC_ENV_PART 2
/* USB Host support */
#define CONFIG_USB_EHCI

View File

@ -160,6 +160,7 @@
#define EXT_CSD_CARD_TYPE 196 /* RO */
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
#define EXT_CSD_BOOT_MULT 226 /* RO */
/*
* EXT_CSD field definitions

View File

@ -76,6 +76,8 @@
#define SDHCI_SPACE_AVAILABLE 0x00000400
#define SDHCI_DATA_AVAILABLE 0x00000800
#define SDHCI_CARD_PRESENT 0x00010000
#define SDHCI_CARD_STATE_STABLE 0x00020000
#define SDHCI_CARD_DETECT_PIN_LEVEL 0x00040000
#define SDHCI_WRITE_PROTECT 0x00080000
#define SDHCI_HOST_CONTROL 0x28
@ -88,6 +90,8 @@
#define SDHCI_CTRL_ADMA32 0x10
#define SDHCI_CTRL_ADMA64 0x18
#define SDHCI_CTRL_8BITBUS 0x20
#define SDHCI_CTRL_CD_TEST_INS 0x40
#define SDHCI_CTRL_CD_TEST 0x80
#define SDHCI_POWER_CONTROL 0x29
#define SDHCI_POWER_ON 0x01
@ -219,6 +223,7 @@
#define SDHCI_QUIRK_BROKEN_R1B (1 << 2)
#define SDHCI_QUIRK_NO_HISPD_BIT (1 << 3)
#define SDHCI_QUIRK_BROKEN_VOLTAGE (1 << 4)
#define SDHCI_QUIRK_NO_CD (1 << 5)
/* to make gcc happy */
struct sdhci_host;
@ -248,8 +253,10 @@ struct sdhci_host {
unsigned int clock;
struct mmc *mmc;
const struct sdhci_ops *ops;
int index;
void (*set_control_reg)(struct sdhci_host *host);
void (*set_clock)(int dev_index, unsigned int div);
uint voltages;
};