summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/Makefile4
-rw-r--r--drivers/mmc/arm_pl180_mmci.c2
-rw-r--r--drivers/mmc/mmc.c45
-rw-r--r--drivers/mmc/pxa_mmc_gen.c8
-rw-r--r--drivers/mmc/s5p_sdhci.c18
-rw-r--r--drivers/mmc/sdhci.c30
-rw-r--r--drivers/mmc/sh_mmcif.c2
-rw-r--r--drivers/mmc/spl_mmc.c136
-rw-r--r--drivers/mmc/spl_mmc_load.c62
9 files changed, 186 insertions, 121 deletions
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 2b96cdc..565ba6a 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -25,8 +25,8 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libmmc.o
-ifdef CONFIG_SPL_MMC_LOAD
-COBJS-$(CONFIG_SPL_MMC_LOAD) += spl_mmc_load.o
+ifdef CONFIG_SPL_BUILD
+COBJS-$(CONFIG_SPL_MMC_SUPPORT) += spl_mmc.o
endif
COBJS-$(CONFIG_BFIN_SDH) += bfin_sdh.o
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index db2c7ab..af1380a 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -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;
}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 551d6a9..a60cfe1 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -151,7 +151,6 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
printf("CMD_SEND:%d\n", cmd->cmdidx);
printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
- printf("\t\tFLAG\t\t\t %d\n", cmd->flags);
ret = mmc->send_cmd(mmc, cmd, data);
switch (cmd->resp_type) {
case MMC_RSP_NONE:
@@ -213,7 +212,6 @@ int mmc_send_status(struct mmc *mmc, int timeout)
cmd.resp_type = MMC_RSP_R1;
if (!mmc_host_is_spi(mmc))
cmd.cmdarg = mmc->rca << 16;
- cmd.flags = 0;
do {
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -238,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;
}
@@ -253,7 +251,6 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = len;
- cmd.flags = 0;
return mmc_send_cmd(mmc, &cmd, NULL);
}
@@ -299,7 +296,6 @@ static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
cmd.cmdidx = start_cmd;
cmd.cmdarg = start;
cmd.resp_type = MMC_RSP_R1;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
@@ -386,7 +382,6 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
cmd.cmdarg = start * mmc->write_bl_len;
cmd.resp_type = MMC_RSP_R1;
- cmd.flags = 0;
data.src = src;
data.blocks = blkcnt;
@@ -405,7 +400,6 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
- cmd.flags = 0;
if (mmc_send_cmd(mmc, &cmd, NULL)) {
printf("mmc fail to send stop cmd\n");
return 0;
@@ -459,7 +453,6 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
cmd.cmdarg = start * mmc->read_bl_len;
cmd.resp_type = MMC_RSP_R1;
- cmd.flags = 0;
data.dest = dst;
data.blocks = blkcnt;
@@ -473,7 +466,6 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
- cmd.flags = 0;
if (mmc_send_cmd(mmc, &cmd, NULL)) {
printf("mmc fail to send stop cmd\n");
return 0;
@@ -525,7 +517,6 @@ int mmc_go_idle(struct mmc* mmc)
cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_NONE;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -548,7 +539,6 @@ sd_send_op_cond(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_APP_CMD;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 0;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -589,7 +579,6 @@ sd_send_op_cond(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
cmd.resp_type = MMC_RSP_R3;
cmd.cmdarg = 0;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -618,7 +607,6 @@ int mmc_send_op_cond(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_SEND_OP_COND;
cmd.resp_type = MMC_RSP_R3;
cmd.cmdarg = 0;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -638,8 +626,6 @@ int mmc_send_op_cond(struct mmc *mmc)
if (mmc->host_caps & MMC_MODE_HC)
cmd.cmdarg |= OCR_HCS;
- cmd.flags = 0;
-
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
@@ -655,7 +641,6 @@ int mmc_send_op_cond(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
cmd.resp_type = MMC_RSP_R3;
cmd.cmdarg = 0;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -673,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;
@@ -683,9 +668,8 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 0;
- cmd.flags = 0;
- data.dest = ext_csd;
+ data.dest = (char *)ext_csd;
data.blocks = 1;
data.blocksize = 512;
data.flags = MMC_DATA_READ;
@@ -707,7 +691,6 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
(index << 16) |
(value << 8);
- cmd.flags = 0;
ret = mmc_send_cmd(mmc, &cmd, NULL);
@@ -721,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;
@@ -800,7 +783,6 @@ int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
cmd.cmdarg = (mode << 31) | 0xffffff;
cmd.cmdarg &= ~(0xf << (group * 4));
cmd.cmdarg |= value << (group * 4);
- cmd.flags = 0;
data.dest = (char *)resp;
data.blocksize = 64;
@@ -829,7 +811,6 @@ int sd_change_freq(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_APP_CMD;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = mmc->rca << 16;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -839,7 +820,6 @@ int sd_change_freq(struct mmc *mmc)
cmd.cmdidx = SD_CMD_APP_SEND_SCR;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 0;
- cmd.flags = 0;
timeout = 3;
@@ -983,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
@@ -992,7 +972,6 @@ int mmc_startup(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 1;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
@@ -1005,7 +984,6 @@ int mmc_startup(struct mmc *mmc)
MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
cmd.resp_type = MMC_RSP_R2;
cmd.cmdarg = 0;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -1023,7 +1001,6 @@ int mmc_startup(struct mmc *mmc)
cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
cmd.cmdarg = mmc->rca << 16;
cmd.resp_type = MMC_RSP_R6;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -1038,7 +1015,6 @@ int mmc_startup(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_SEND_CSD;
cmd.resp_type = MMC_RSP_R2;
cmd.cmdarg = mmc->rca << 16;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -1115,7 +1091,6 @@ int mmc_startup(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_SELECT_CARD;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = mmc->rca << 16;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
@@ -1183,7 +1158,6 @@ int mmc_startup(struct mmc *mmc)
cmd.cmdidx = MMC_CMD_APP_CMD;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = mmc->rca << 16;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
@@ -1192,7 +1166,6 @@ int mmc_startup(struct mmc *mmc)
cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 2;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
@@ -1260,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;
}
@@ -1274,7 +1249,6 @@ int mmc_send_if_cond(struct mmc *mmc)
/* We set the bit if the host supports voltages between 2.7 and 3.6 V */
cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
cmd.resp_type = MMC_RSP_R7;
- cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -1312,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
diff --git a/drivers/mmc/pxa_mmc_gen.c b/drivers/mmc/pxa_mmc_gen.c
index 2c5bf17..b3ec441 100644
--- a/drivers/mmc/pxa_mmc_gen.c
+++ b/drivers/mmc/pxa_mmc_gen.c
@@ -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
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index 1d4481b..b978236 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -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->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;
}
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 1709643..2e3c408 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -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;
diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c
index 2835e24..4588568 100644
--- a/drivers/mmc/sh_mmcif.c
+++ b/drivers/mmc/sh_mmcif.c
@@ -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;
diff --git a/drivers/mmc/spl_mmc.c b/drivers/mmc/spl_mmc.c
new file mode 100644
index 0000000..753c6a0
--- /dev/null
+++ b/drivers/mmc/spl_mmc.c
@@ -0,0 +1,136 @@
+/*
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *
+ * Aneesh V <aneesh@ti.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <spl.h>
+#include <asm/u-boot.h>
+#include <asm/utils.h>
+#include <mmc.h>
+#include <fat.h>
+#include <version.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void mmc_load_image_raw(struct mmc *mmc)
+{
+ u32 image_size_sectors, err;
+ const struct image_header *header;
+
+ header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
+ sizeof(struct image_header));
+
+ /* read image header to find the image size & load address */
+ err = mmc->block_dev.block_read(0,
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 1,
+ (void *)header);
+
+ if (err <= 0)
+ goto end;
+
+ spl_parse_image_header(header);
+
+ /* convert size to sectors - round up */
+ image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) /
+ mmc->read_bl_len;
+
+ /* Read the header too to avoid extra memcpy */
+ err = mmc->block_dev.block_read(0,
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
+ image_size_sectors, (void *)spl_image.load_addr);
+
+end:
+ if (err <= 0) {
+ printf("spl: mmc blk read err - %d\n", err);
+ hang();
+ }
+}
+
+#ifdef CONFIG_SPL_FAT_SUPPORT
+static void mmc_load_image_fat(struct mmc *mmc)
+{
+ s32 err;
+ struct image_header *header;
+
+ header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
+ sizeof(struct image_header));
+
+ err = fat_register_device(&mmc->block_dev,
+ CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION);
+ if (err) {
+ printf("spl: fat register err - %d\n", err);
+ hang();
+ }
+
+ err = file_fat_read(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME,
+ (u8 *)header, sizeof(struct image_header));
+ if (err <= 0)
+ goto end;
+
+ spl_parse_image_header(header);
+
+ err = file_fat_read(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME,
+ (u8 *)spl_image.load_addr, 0);
+
+end:
+ if (err <= 0) {
+ printf("spl: error reading image %s, err - %d\n",
+ CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME, err);
+ hang();
+ }
+}
+#endif
+
+void spl_mmc_load_image(void)
+{
+ struct mmc *mmc;
+ int err;
+ u32 boot_mode;
+
+ mmc_initialize(gd->bd);
+ /* We register only one device. So, the dev id is always 0 */
+ mmc = find_mmc_device(0);
+ if (!mmc) {
+ puts("spl: mmc device not found!!\n");
+ hang();
+ }
+
+ err = mmc_init(mmc);
+ if (err) {
+ printf("spl: mmc init failed: err - %d\n", err);
+ hang();
+ }
+ boot_mode = spl_boot_mode();
+ if (boot_mode == MMCSD_MODE_RAW) {
+ debug("boot mode - RAW\n");
+ mmc_load_image_raw(mmc);
+#ifdef CONFIG_SPL_FAT_SUPPORT
+ } else if (boot_mode == MMCSD_MODE_FAT) {
+ debug("boot mode - FAT\n");
+ mmc_load_image_fat(mmc);
+#endif
+ } else {
+ puts("spl: wrong MMC boot mode\n");
+ hang();
+ }
+}
diff --git a/drivers/mmc/spl_mmc_load.c b/drivers/mmc/spl_mmc_load.c
deleted file mode 100644
index 79a68fb..0000000
--- a/drivers/mmc/spl_mmc_load.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <common.h>
-#include <mmc.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static void mmc_load_image(struct mmc *mmc)
-{
- s32 err;
- void (*uboot)(void) __noreturn;
-
- err = mmc->block_dev.block_read(0, CONFIG_SYS_MMC_U_BOOT_OFFS,
- CONFIG_SYS_MMC_U_BOOT_SIZE/512,
- (u32 *)CONFIG_SYS_TEXT_BASE);
-
- if (err <= 0) {
- printf("spl: error reading image %s, err - %d\n",
- "u-boot.img", err);
- hang();
- }
- uboot = (void *) CONFIG_SYS_TEXT_BASE;
- (*uboot)();
-}
-
-void spl_mmc_load(void)
-{
- struct mmc *mmc;
- int err;
- void (mmc_load_image)(struct mmc *mmc) __noreturn;
-
- mmc_initialize(gd->bd);
- mmc = find_mmc_device(0);
- if (!mmc) {
- puts("spl: mmc device not found!!\n");
- hang();
- } else {
- puts("spl: mmc device found\n");
- }
- err = mmc_init(mmc);
- if (err) {
- printf("spl: mmc init failed: err - %d\n", err);
- hang();
- }
- mmc_load_image(mmc);
-}