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.c131
-rw-r--r--drivers/mmc/arm_pl180_mmci.h27
-rw-r--r--drivers/mmc/fsl_esdhc.c5
-rw-r--r--drivers/mmc/mxsmmc.c204
-rw-r--r--drivers/mmc/spl_mmc_load.c62
-rw-r--r--drivers/mmc/tegra_mmc.c32
-rw-r--r--drivers/mmc/tegra_mmc.h12
8 files changed, 279 insertions, 198 deletions
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index c567737..2b96cdc 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -25,6 +25,10 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libmmc.o
+ifdef CONFIG_SPL_MMC_LOAD
+COBJS-$(CONFIG_SPL_MMC_LOAD) += spl_mmc_load.o
+endif
+
COBJS-$(CONFIG_BFIN_SDH) += bfin_sdh.o
COBJS-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o
COBJS-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 09d443e..db2c7ab 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -32,14 +32,10 @@
#include "arm_pl180_mmci.h"
#include <malloc.h>
-struct mmc_host {
- struct sdi_registers *base;
-};
-
static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
{
u32 hoststatus, statusmask;
- struct mmc_host *host = dev->priv;
+ struct pl180_mmc_host *host = dev->priv;
statusmask = SDI_STA_CTIMEOUT | SDI_STA_CCRCFAIL;
if ((cmd->resp_type & MMC_RSP_PRESENT))
@@ -53,8 +49,8 @@ static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
writel(statusmask, &host->base->status_clear);
if (hoststatus & SDI_STA_CTIMEOUT) {
- printf("CMD%d time out\n", cmd->cmdidx);
- return -ETIMEDOUT;
+ debug("CMD%d time out\n", cmd->cmdidx);
+ return TIMEOUT;
} else if ((hoststatus & SDI_STA_CCRCFAIL) &&
(cmd->flags & MMC_RSP_CRC)) {
printf("CMD%d CRC error\n", cmd->cmdidx);
@@ -80,7 +76,7 @@ static int do_command(struct mmc *dev, struct mmc_cmd *cmd)
{
int result;
u32 sdi_cmd = 0;
- struct mmc_host *host = dev->priv;
+ struct pl180_mmc_host *host = dev->priv;
sdi_cmd = ((cmd->cmdidx & SDI_CMD_CMDINDEX_MASK) | SDI_CMD_CPSMEN);
@@ -112,7 +108,7 @@ static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize)
{
u32 *tempbuff = dest;
u64 xfercount = blkcount * blksize;
- struct mmc_host *host = dev->priv;
+ struct pl180_mmc_host *host = dev->priv;
u32 status, status_err;
debug("read_bytes: blkcount=%u blksize=%u\n", blkcount, blksize);
@@ -168,7 +164,7 @@ static int write_bytes(struct mmc *dev, u32 *src, u32 blkcount, u32 blksize)
u32 *tempbuff = src;
int i;
u64 xfercount = blkcount * blksize;
- struct mmc_host *host = dev->priv;
+ struct pl180_mmc_host *host = dev->priv;
u32 status, status_err;
debug("write_bytes: blkcount=%u blksize=%u\n", blkcount, blksize);
@@ -227,14 +223,19 @@ static int do_data_transfer(struct mmc *dev,
struct mmc_data *data)
{
int error = -ETIMEDOUT;
- struct mmc_host *host = dev->priv;
+ struct pl180_mmc_host *host = dev->priv;
u32 blksz = 0;
u32 data_ctrl = 0;
u32 data_len = (u32) (data->blocks * data->blocksize);
- blksz = (ffs(data->blocksize) - 1);
- data_ctrl |= ((blksz << 4) & SDI_DCTRL_DBLKSIZE_MASK);
- data_ctrl |= SDI_DCTRL_DTEN;
+ if (!host->version2) {
+ blksz = (ffs(data->blocksize) - 1);
+ data_ctrl |= ((blksz << 4) & SDI_DCTRL_DBLKSIZE_MASK);
+ } else {
+ blksz = data->blocksize;
+ data_ctrl |= (blksz << SDI_DCTRL_DBLOCKSIZE_V2_SHIFT);
+ }
+ data_ctrl |= SDI_DCTRL_DTEN | SDI_DCTRL_BUSYMODE;
writel(SDI_DTIMER_DEFAULT, &host->base->datatimer);
writel(data_len, &host->base->datalength);
@@ -257,7 +258,7 @@ static int do_data_transfer(struct mmc *dev,
writel(data_ctrl, &host->base->datactrl);
error = write_bytes(dev, (u32 *)data->src, (u32)data->blocks,
- (u32)data->blocksize);
+ (u32)data->blocksize);
}
return error;
@@ -280,17 +281,16 @@ static int host_request(struct mmc *dev,
/* MMC uses open drain drivers in the enumeration phase */
static int mmc_host_reset(struct mmc *dev)
{
- struct mmc_host *host = dev->priv;
- u32 sdi_u32 = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON;
+ struct pl180_mmc_host *host = dev->priv;
- writel(sdi_u32, &host->base->power);
+ writel(host->pwr_init, &host->base->power);
return 0;
}
static void host_set_ios(struct mmc *dev)
{
- struct mmc_host *host = dev->priv;
+ struct pl180_mmc_host *host = dev->priv;
u32 sdi_clkcr;
sdi_clkcr = readl(&host->base->clock);
@@ -298,15 +298,26 @@ static void host_set_ios(struct mmc *dev)
/* Ramp up the clock rate */
if (dev->clock) {
u32 clkdiv = 0;
+ u32 tmp_clock;
- if (dev->clock >= dev->f_max)
+ if (dev->clock >= dev->f_max) {
+ clkdiv = 0;
dev->clock = dev->f_max;
+ } else {
+ clkdiv = (host->clock_in / dev->clock) - 2;
+ }
- clkdiv = ((ARM_MCLK / dev->clock) / 2) - 1;
+ tmp_clock = host->clock_in / (clkdiv + 2);
+ while (tmp_clock > dev->clock) {
+ clkdiv++;
+ tmp_clock = host->clock_in / (clkdiv + 2);
+ }
if (clkdiv > SDI_CLKCR_CLKDIV_MASK)
clkdiv = SDI_CLKCR_CLKDIV_MASK;
+ tmp_clock = host->clock_in / (clkdiv + 2);
+ dev->clock = tmp_clock;
sdi_clkcr &= ~(SDI_CLKCR_CLKDIV_MASK);
sdi_clkcr |= clkdiv;
}
@@ -322,8 +333,11 @@ static void host_set_ios(struct mmc *dev)
case 4:
buswidth |= SDI_CLKCR_WIDBUS_4;
break;
+ case 8:
+ buswidth |= SDI_CLKCR_WIDBUS_8;
+ break;
default:
- printf("Invalid bus width\n");
+ printf("Invalid bus width: %d\n", dev->bus_width);
break;
}
sdi_clkcr &= ~(SDI_CLKCR_WIDBUS_MASK);
@@ -334,83 +348,40 @@ static void host_set_ios(struct mmc *dev)
udelay(CLK_CHANGE_DELAY);
}
-struct mmc *alloc_mmc_struct(void)
-{
- struct mmc_host *host = NULL;
- struct mmc *mmc_device = NULL;
-
- host = malloc(sizeof(struct mmc_host));
- if (!host)
- return NULL;
-
- mmc_device = malloc(sizeof(struct mmc));
- if (!mmc_device)
- goto err;
-
- mmc_device->priv = host;
- return mmc_device;
-
-err:
- free(host);
- return NULL;
-}
-
/*
* mmc_host_init - initialize the mmc controller.
* Set initial clock and power for mmc slot.
* Initialize mmc struct and register with mmc framework.
*/
-static int arm_pl180_mmci_host_init(struct mmc *dev)
+int arm_pl180_mmci_init(struct pl180_mmc_host *host)
{
- struct mmc_host *host = dev->priv;
+ struct mmc *dev;
u32 sdi_u32;
- host->base = (struct sdi_registers *)CONFIG_ARM_PL180_MMCI_BASE;
+ dev = malloc(sizeof(struct mmc));
+ if (!dev)
+ return -ENOMEM;
- /* Initially set power-on, full voltage & MMCI read */
- sdi_u32 = INIT_PWR;
- writel(sdi_u32, &host->base->power);
+ memset(dev, 0, sizeof(struct mmc));
+ dev->priv = host;
- /* setting clk freq 505KHz */
- sdi_u32 = SDI_CLKCR_CLKDIV_INIT | SDI_CLKCR_CLKEN;
- writel(sdi_u32, &host->base->clock);
+ writel(host->pwr_init, &host->base->power);
+ writel(host->clkdiv_init, &host->base->clock);
udelay(CLK_CHANGE_DELAY);
/* Disable mmc interrupts */
sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
writel(sdi_u32, &host->base->mask0);
-
- sprintf(dev->name, "MMC");
- dev->clock = ARM_MCLK / (2 * (SDI_CLKCR_CLKDIV_INIT + 1));
+ strncpy(dev->name, host->name, sizeof(dev->name));
dev->send_cmd = host_request;
dev->set_ios = host_set_ios;
dev->init = mmc_host_reset;
dev->getcd = NULL;
- dev->host_caps = 0;
- dev->voltages = VOLTAGE_WINDOW_MMC;
- dev->f_min = dev->clock;
- dev->f_max = CONFIG_ARM_PL180_MMCI_CLOCK_FREQ;
-
- return 0;
-}
-
-int arm_pl180_mmci_init(void)
-{
- int error;
- struct mmc *dev;
-
- dev = alloc_mmc_struct();
- if (!dev)
- return -1;
-
- error = arm_pl180_mmci_host_init(dev);
- if (error) {
- printf("mmci_host_init error - %d\n", error);
- return -1;
- }
-
- dev->b_max = 0;
-
+ dev->host_caps = host->caps;
+ dev->voltages = host->voltages;
+ dev->f_min = host->clock_min;
+ dev->f_max = host->clock_max;
+ dev->b_max = host->b_max;
mmc_register(dev);
debug("registered mmc interface number is:%d\n", dev->block_dev.dev);
diff --git a/drivers/mmc/arm_pl180_mmci.h b/drivers/mmc/arm_pl180_mmci.h
index 42fbe3e..06709ed 100644
--- a/drivers/mmc/arm_pl180_mmci.h
+++ b/drivers/mmc/arm_pl180_mmci.h
@@ -26,8 +26,6 @@
#ifndef __ARM_PL180_MMCI_H__
#define __ARM_PL180_MMCI_H__
-int arm_pl180_mmci_init(void);
-
#define COMMAND_REG_DELAY 300
#define DATA_REG_DELAY 1000
#define CLK_CHANGE_DELAY 2000
@@ -59,8 +57,13 @@ int arm_pl180_mmci_init(void);
#define SDI_CLKCR_WIDBUS_MASK 0x00001800
#define SDI_CLKCR_WIDBUS_1 0x00000000
#define SDI_CLKCR_WIDBUS_4 0x00000800
+/* V2 only */
+#define SDI_CLKCR_WIDBUS_8 0x00001000
+#define SDI_CLKCR_NEDGE 0x00002000
+#define SDI_CLKCR_HWFC_EN 0x00004000
-#define SDI_CLKCR_CLKDIV_INIT 0x000000C6 /* MCLK/(2*(0xC6+1)) => 505KHz */
+#define SDI_CLKCR_CLKDIV_INIT_V1 0x000000C6 /* MCLK/(2*(0xC6+1)) => 505KHz */
+#define SDI_CLKCR_CLKDIV_INIT_V2 0x000000FD
/* SDI command register bits */
#define SDI_CMD_CMDINDEX_MASK 0x000000FF
@@ -144,6 +147,8 @@ int arm_pl180_mmci_init(void);
#define SDI_DCTRL_DBOOTMODEEN 0x00002000
#define SDI_DCTRL_BUSYMODE 0x00004000
#define SDI_DCTRL_DDR_MODE 0x00008000
+#define SDI_DCTRL_DBLOCKSIZE_V2_MASK 0x7fff0000
+#define SDI_DCTRL_DBLOCKSIZE_V2_SHIFT 16
#define SDI_FIFO_BURST_SIZE 8
@@ -180,4 +185,20 @@ struct sdi_registers {
u32 pcell_id3; /* 0xFFC*/
};
+struct pl180_mmc_host {
+ struct sdi_registers *base;
+ char name[32];
+ unsigned int b_max;
+ unsigned int voltages;
+ unsigned int caps;
+ unsigned int clock_in;
+ unsigned int clock_min;
+ unsigned int clock_max;
+ unsigned int clkdiv_init;
+ unsigned int pwr_init;
+ int version2;
+};
+
+int arm_pl180_mmci_init(struct pl180_mmc_host *);
+
#endif
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index b6c969d..3f8d30d 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -479,9 +479,10 @@ static int esdhc_init(struct mmc *mmc)
while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
udelay(1000);
+#ifndef ARCH_MXC
/* Enable cache snooping */
- if (cfg && !cfg->no_snoop)
- esdhc_write32(&regs->scr, 0x00000040);
+ esdhc_write32(&regs->scr, 0x00000040);
+#endif
esdhc_write32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 4187a94..9a98c6b 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -43,16 +43,9 @@
#include <asm/arch/sys_proto.h>
#include <asm/arch/dma.h>
-/*
- * CONFIG_MXS_MMC_DMA: This feature is highly experimental and has no
- * performance benefit unless you operate the platform with
- * data cache enabled. This is disabled by default, enable
- * only if you know what you're doing.
- */
-
struct mxsmmc_priv {
int id;
- struct mx28_ssp_regs *regs;
+ struct mxs_ssp_regs *regs;
uint32_t clkseq_bypass;
uint32_t *clkctrl_ssp;
uint32_t buswidth;
@@ -61,6 +54,87 @@ struct mxsmmc_priv {
};
#define MXSMMC_MAX_TIMEOUT 10000
+#define MXSMMC_SMALL_TRANSFER 512
+
+static int mxsmmc_send_cmd_pio(struct mxsmmc_priv *priv, struct mmc_data *data)
+{
+ struct mxs_ssp_regs *ssp_regs = priv->regs;
+ uint32_t *data_ptr;
+ int timeout = MXSMMC_MAX_TIMEOUT;
+ uint32_t reg;
+ uint32_t data_count = data->blocksize * data->blocks;
+
+ if (data->flags & MMC_DATA_READ) {
+ data_ptr = (uint32_t *)data->dest;
+ while (data_count && --timeout) {
+ reg = readl(&ssp_regs->hw_ssp_status);
+ if (!(reg & SSP_STATUS_FIFO_EMPTY)) {
+ *data_ptr++ = readl(&ssp_regs->hw_ssp_data);
+ data_count -= 4;
+ timeout = MXSMMC_MAX_TIMEOUT;
+ } else
+ udelay(1000);
+ }
+ } else {
+ data_ptr = (uint32_t *)data->src;
+ timeout *= 100;
+ while (data_count && --timeout) {
+ reg = readl(&ssp_regs->hw_ssp_status);
+ if (!(reg & SSP_STATUS_FIFO_FULL)) {
+ writel(*data_ptr++, &ssp_regs->hw_ssp_data);
+ data_count -= 4;
+ timeout = MXSMMC_MAX_TIMEOUT;
+ } else
+ udelay(1000);
+ }
+ }
+
+ return timeout ? 0 : COMM_ERR;
+}
+
+static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
+{
+ uint32_t data_count = data->blocksize * data->blocks;
+ uint32_t cache_data_count;
+ int dmach;
+ struct mxs_dma_desc *desc = priv->desc;
+
+ memset(desc, 0, sizeof(struct mxs_dma_desc));
+ desc->address = (dma_addr_t)desc;
+
+ if (data_count % ARCH_DMA_MINALIGN)
+ cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN);
+ else
+ cache_data_count = data_count;
+
+ if (data->flags & MMC_DATA_READ) {
+ priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_WRITE;
+ priv->desc->cmd.address = (dma_addr_t)data->dest;
+ } else {
+ priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ;
+ priv->desc->cmd.address = (dma_addr_t)data->src;
+
+ /* Flush data to DRAM so DMA can pick them up */
+ flush_dcache_range((uint32_t)priv->desc->cmd.address,
+ (uint32_t)(priv->desc->cmd.address + cache_data_count));
+ }
+
+ priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM |
+ (data_count << MXS_DMA_DESC_BYTES_OFFSET);
+
+ dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id;
+ mxs_dma_desc_append(dmach, priv->desc);
+ if (mxs_dma_go(dmach))
+ return COMM_ERR;
+
+ /* The data arrived into DRAM, invalidate cache over them */
+ if (data->flags & MMC_DATA_READ) {
+ invalidate_dcache_range((uint32_t)priv->desc->cmd.address,
+ (uint32_t)(priv->desc->cmd.address + cache_data_count));
+ }
+
+ return 0;
+}
/*
* Sends a command out on the bus. Takes the mmc pointer,
@@ -70,16 +144,11 @@ static int
mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
- struct mx28_ssp_regs *ssp_regs = priv->regs;
+ struct mxs_ssp_regs *ssp_regs = priv->regs;
uint32_t reg;
int timeout;
- uint32_t data_count;
uint32_t ctrl0;
-#ifndef CONFIG_MXS_MMC_DMA
- uint32_t *data_ptr;
-#else
- uint32_t cache_data_count;
-#endif
+ int ret;
debug("MMC%d: CMD%d\n", mmc->block_dev.dev, cmd->cmdidx);
@@ -117,6 +186,11 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
if (cmd->resp_type & MMC_RSP_136) /* It's a 136 bits response */
ctrl0 |= SSP_CTRL0_LONG_RESP;
+ if (data && (data->blocksize * data->blocks < MXSMMC_SMALL_TRANSFER))
+ writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
+ else
+ writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
+
/* Command index */
reg = readl(&ssp_regs->hw_ssp_cmd0);
reg &= ~(SSP_CMD0_CMD_MASK | SSP_CMD0_APPEND_8CYC);
@@ -197,75 +271,23 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
if (!data)
return 0;
- data_count = data->blocksize * data->blocks;
- timeout = MXSMMC_MAX_TIMEOUT;
-
-#ifdef CONFIG_MXS_MMC_DMA
- if (data_count % ARCH_DMA_MINALIGN)
- cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN);
- else
- cache_data_count = data_count;
-
- if (data->flags & MMC_DATA_READ) {
- priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_WRITE;
- priv->desc->cmd.address = (dma_addr_t)data->dest;
- } else {
- priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ;
- priv->desc->cmd.address = (dma_addr_t)data->src;
-
- /* Flush data to DRAM so DMA can pick them up */
- flush_dcache_range((uint32_t)priv->desc->cmd.address,
- (uint32_t)(priv->desc->cmd.address + cache_data_count));
- }
-
- priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM |
- (data_count << MXS_DMA_DESC_BYTES_OFFSET);
-
-
- mxs_dma_desc_append(MXS_DMA_CHANNEL_AHB_APBH_SSP0, priv->desc);
- if (mxs_dma_go(MXS_DMA_CHANNEL_AHB_APBH_SSP0)) {
- printf("MMC%d: DMA transfer failed\n", mmc->block_dev.dev);
- return COMM_ERR;
- }
-
- /* The data arrived into DRAM, invalidate cache over them */
- if (data->flags & MMC_DATA_READ) {
- invalidate_dcache_range((uint32_t)priv->desc->cmd.address,
- (uint32_t)(priv->desc->cmd.address + cache_data_count));
- }
-#else
- if (data->flags & MMC_DATA_READ) {
- data_ptr = (uint32_t *)data->dest;
- while (data_count && --timeout) {
- reg = readl(&ssp_regs->hw_ssp_status);
- if (!(reg & SSP_STATUS_FIFO_EMPTY)) {
- *data_ptr++ = readl(&ssp_regs->hw_ssp_data);
- data_count -= 4;
- timeout = MXSMMC_MAX_TIMEOUT;
- } else
- udelay(1000);
+ if (data->blocksize * data->blocks < MXSMMC_SMALL_TRANSFER) {
+ ret = mxsmmc_send_cmd_pio(priv, data);
+ if (ret) {
+ printf("MMC%d: Data timeout with command %d "
+ "(status 0x%08x)!\n",
+ mmc->block_dev.dev, cmd->cmdidx, reg);
+ return ret;
}
} else {
- data_ptr = (uint32_t *)data->src;
- timeout *= 100;
- while (data_count && --timeout) {
- reg = readl(&ssp_regs->hw_ssp_status);
- if (!(reg & SSP_STATUS_FIFO_FULL)) {
- writel(*data_ptr++, &ssp_regs->hw_ssp_data);
- data_count -= 4;
- timeout = MXSMMC_MAX_TIMEOUT;
- } else
- udelay(1000);
+ ret = mxsmmc_send_cmd_dma(priv, data);
+ if (ret) {
+ printf("MMC%d: DMA transfer failed\n",
+ mmc->block_dev.dev);
+ return ret;
}
}
- if (!timeout) {
- printf("MMC%d: Data timeout with command %d (status 0x%08x)!\n",
- mmc->block_dev.dev, cmd->cmdidx, reg);
- return COMM_ERR;
- }
-#endif
-
/* Check data errors */
reg = readl(&ssp_regs->hw_ssp_status);
if (reg &
@@ -282,7 +304,7 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
static void mxsmmc_set_ios(struct mmc *mmc)
{
struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
- struct mx28_ssp_regs *ssp_regs = priv->regs;
+ struct mxs_ssp_regs *ssp_regs = priv->regs;
/* Set the clock speed */
if (mmc->clock)
@@ -311,16 +333,16 @@ static void mxsmmc_set_ios(struct mmc *mmc)
static int mxsmmc_init(struct mmc *mmc)
{
struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv;
- struct mx28_ssp_regs *ssp_regs = priv->regs;
+ struct mxs_ssp_regs *ssp_regs = priv->regs;
/* Reset SSP */
- mx28_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
+ mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
/* 8 bits word length in MMC mode */
clrsetbits_le32(&ssp_regs->hw_ssp_ctrl1,
- SSP_CTRL1_SSP_MODE_MASK | SSP_CTRL1_WORD_LENGTH_MASK,
- SSP_CTRL1_SSP_MODE_SD_MMC | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS |
- SSP_CTRL1_DMA_ENABLE);
+ SSP_CTRL1_SSP_MODE_MASK | SSP_CTRL1_WORD_LENGTH_MASK |
+ SSP_CTRL1_DMA_ENABLE,
+ SSP_CTRL1_SSP_MODE_SD_MMC | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS);
/* Set initial bit clock 400 KHz */
mx28_set_ssp_busclock(priv->id, 400);
@@ -335,8 +357,8 @@ static int mxsmmc_init(struct mmc *mmc)
int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
struct mmc *mmc = NULL;
struct mxsmmc_priv *priv = NULL;
int ret;
@@ -366,22 +388,22 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))
priv->id = id;
switch (id) {
case 0:
- priv->regs = (struct mx28_ssp_regs *)MXS_SSP0_BASE;
+ priv->regs = (struct mxs_ssp_regs *)MXS_SSP0_BASE;
priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP0;
priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp0;
break;
case 1:
- priv->regs = (struct mx28_ssp_regs *)MXS_SSP1_BASE;
+ priv->regs = (struct mxs_ssp_regs *)MXS_SSP1_BASE;
priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP1;
priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp1;
break;
case 2:
- priv->regs = (struct mx28_ssp_regs *)MXS_SSP2_BASE;
+ priv->regs = (struct mxs_ssp_regs *)MXS_SSP2_BASE;
priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP2;
priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp2;
break;
case 3:
- priv->regs = (struct mx28_ssp_regs *)MXS_SSP3_BASE;
+ priv->regs = (struct mxs_ssp_regs *)MXS_SSP3_BASE;
priv->clkseq_bypass = CLKCTRL_CLKSEQ_BYPASS_SSP3;
priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp3;
break;
diff --git a/drivers/mmc/spl_mmc_load.c b/drivers/mmc/spl_mmc_load.c
new file mode 100644
index 0000000..79a68fb
--- /dev/null
+++ b/drivers/mmc/spl_mmc_load.c
@@ -0,0 +1,62 @@
+/*
+ * 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);
+}
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 29bf583..ddfa727 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -39,31 +39,31 @@ struct mmc_host mmc_host[4];
* @param host Structure to fill in (base, reg, mmc_id)
* @param dev_index Device index (0-3)
*/
-static void tegra2_get_setup(struct mmc_host *host, int dev_index)
+static void tegra20_get_setup(struct mmc_host *host, int dev_index)
{
- debug("tegra2_get_base_mmc: dev_index = %d\n", dev_index);
+ debug("tegra20_get_base_mmc: dev_index = %d\n", dev_index);
switch (dev_index) {
case 1:
- host->base = TEGRA2_SDMMC3_BASE;
+ host->base = TEGRA20_SDMMC3_BASE;
host->mmc_id = PERIPH_ID_SDMMC3;
break;
case 2:
- host->base = TEGRA2_SDMMC2_BASE;
+ host->base = TEGRA20_SDMMC2_BASE;
host->mmc_id = PERIPH_ID_SDMMC2;
break;
case 3:
- host->base = TEGRA2_SDMMC1_BASE;
+ host->base = TEGRA20_SDMMC1_BASE;
host->mmc_id = PERIPH_ID_SDMMC1;
break;
case 0:
default:
- host->base = TEGRA2_SDMMC4_BASE;
+ host->base = TEGRA20_SDMMC4_BASE;
host->mmc_id = PERIPH_ID_SDMMC4;
break;
}
- host->reg = (struct tegra2_mmc *)host->base;
+ host->reg = (struct tegra20_mmc *)host->base;
}
static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data)
@@ -345,7 +345,7 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
debug(" mmc_change_clock called\n");
/*
- * Change Tegra2 SDMMCx clock divisor here. Source is 216MHz,
+ * Change Tegra20 SDMMCx clock divisor here. Source is 216MHz,
* PLLP_OUT0
*/
if (clock == 0)
@@ -494,11 +494,11 @@ static int mmc_core_init(struct mmc *mmc)
return 0;
}
-int tegra2_mmc_getcd(struct mmc *mmc)
+int tegra20_mmc_getcd(struct mmc *mmc)
{
struct mmc_host *host = (struct mmc_host *)mmc->priv;
- debug("tegra2_mmc_getcd called\n");
+ debug("tegra20_mmc_getcd called\n");
if (host->cd_gpio >= 0)
return !gpio_get_value(host->cd_gpio);
@@ -506,13 +506,13 @@ int tegra2_mmc_getcd(struct mmc *mmc)
return 1;
}
-int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
+int tegra20_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
{
struct mmc_host *host;
char gpusage[12]; /* "SD/MMCn PWR" or "SD/MMCn CD" */
struct mmc *mmc;
- debug(" tegra2_mmc_init: index %d, bus width %d "
+ debug(" tegra20_mmc_init: index %d, bus width %d "
"pwr_gpio %d cd_gpio %d\n",
dev_index, bus_width, pwr_gpio, cd_gpio);
@@ -521,7 +521,7 @@ int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
host->clock = 0;
host->pwr_gpio = pwr_gpio;
host->cd_gpio = cd_gpio;
- tegra2_get_setup(host, dev_index);
+ tegra20_get_setup(host, dev_index);
clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000);
@@ -539,12 +539,12 @@ int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
mmc = &mmc_dev[dev_index];
- sprintf(mmc->name, "Tegra2 SD/MMC");
+ sprintf(mmc->name, "Tegra20 SD/MMC");
mmc->priv = host;
mmc->send_cmd = mmc_send_cmd;
mmc->set_ios = mmc_set_ios;
mmc->init = mmc_core_init;
- mmc->getcd = tegra2_mmc_getcd;
+ mmc->getcd = tegra20_mmc_getcd;
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
if (bus_width == 8)
@@ -559,7 +559,7 @@ int tegra2_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
* max freq is highest HS eMMC clock as per the SD/MMC spec
* (actually 52MHz)
* Both of these are the closest equivalents w/216MHz source
- * clock and Tegra2 SDMMC divisors.
+ * clock and Tegra20 SDMMC divisors.
*/
mmc->f_min = 375000;
mmc->f_max = 48000000;
diff --git a/drivers/mmc/tegra_mmc.h b/drivers/mmc/tegra_mmc.h
index f9cdcaa..b1f2564 100644
--- a/drivers/mmc/tegra_mmc.h
+++ b/drivers/mmc/tegra_mmc.h
@@ -22,13 +22,13 @@
#ifndef __TEGRA_MMC_H_
#define __TEGRA_MMC_H_
-#define TEGRA2_SDMMC1_BASE 0xC8000000
-#define TEGRA2_SDMMC2_BASE 0xC8000200
-#define TEGRA2_SDMMC3_BASE 0xC8000400
-#define TEGRA2_SDMMC4_BASE 0xC8000600
+#define TEGRA20_SDMMC1_BASE 0xC8000000
+#define TEGRA20_SDMMC2_BASE 0xC8000200
+#define TEGRA20_SDMMC3_BASE 0xC8000400
+#define TEGRA20_SDMMC4_BASE 0xC8000600
#ifndef __ASSEMBLY__
-struct tegra2_mmc {
+struct tegra20_mmc {
unsigned int sysad; /* _SYSTEM_ADDRESS_0 */
unsigned short blksize; /* _BLOCK_SIZE_BLOCK_COUNT_0 15:00 */
unsigned short blkcnt; /* _BLOCK_SIZE_BLOCK_COUNT_0 31:16 */
@@ -118,7 +118,7 @@ struct tegra2_mmc {
#define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE (1 << 1)
struct mmc_host {
- struct tegra2_mmc *reg;
+ struct tegra20_mmc *reg;
unsigned int version; /* SDHCI spec. version */
unsigned int clock; /* Current clock (MHz) */
unsigned int base; /* Base address, SDMMC1/2/3/4 */