#include <mmc.h>
#include <asm/io.h>
#include <asm/arch/mmc.h>
-
-#ifdef DEBUG_S5P_HSMMC
-#define dbg(x...) printf(x)
-#else
-#define dbg(x...) do { } while (0)
-#endif
+#include <asm/arch/clk.h>
/* support 4 mmc hosts */
struct mmc mmc_dev[4];
static inline struct s5p_mmc *s5p_get_base_mmc(int dev_index)
{
unsigned long offset = dev_index * sizeof(struct s5p_mmc);
-
- if (cpu_is_s5pc100())
- return (struct s5p_mmc *)(S5PC100_MMC_BASE + offset);
- else
- return (struct s5p_mmc *)(S5PC110_MMC_BASE + offset);
+ return (struct s5p_mmc *)(samsung_get_base_mmc() + offset);
}
static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data)
{
unsigned char ctrl;
- dbg("data->dest: %08x\n", (u32)data->dest);
+ debug("data->dest: %08x\n", (u32)data->dest);
writel((u32)data->dest, &host->reg->sysad);
/*
* DMASEL[4:3]
writeb(ctrl, &host->reg->hostctl);
/* We do not handle DMA boundaries, so set it to max (512 KiB) */
- writew((7 << 12) | (512 << 0), &host->reg->blksize);
+ writew((7 << 12) | (data->blocksize & 0xFFF), &host->reg->blksize);
writew(data->blocks, &host->reg->blkcnt);
}
if (data)
mmc_prepare_data(host, data);
- dbg("cmd->arg: %08x\n", cmd->cmdarg);
+ debug("cmd->arg: %08x\n", cmd->cmdarg);
writel(cmd->cmdarg, &host->reg->argument);
if (data)
if (data)
flags |= (1 << 5);
- dbg("cmd: %d\n", cmd->cmdidx);
+ debug("cmd: %d\n", cmd->cmdidx);
writew((cmd->cmdidx << 8) | flags, &host->reg->cmdreg);
if (mask & (1 << 16)) {
/* Timeout Error */
- dbg("timeout: %08x cmd %d\n", mask, cmd->cmdidx);
+ debug("timeout: %08x cmd %d\n", mask, cmd->cmdidx);
return TIMEOUT;
} else if (mask & (1 << 15)) {
/* Error Interrupt */
- dbg("error: %08x cmd %d\n", mask, cmd->cmdidx);
+ debug("error: %08x cmd %d\n", mask, cmd->cmdidx);
return -1;
}
cmd->response[i] |=
readb(offset - 1);
}
- dbg("cmd->resp[%d]: %08x\n",
+ debug("cmd->resp[%d]: %08x\n",
i, cmd->response[i]);
}
} else if (cmd->resp_type & MMC_RSP_BUSY) {
}
cmd->response[0] = readl(&host->reg->rspreg0);
- dbg("cmd->resp[0]: %08x\n", cmd->response[0]);
+ debug("cmd->resp[0]: %08x\n", cmd->response[0]);
} else {
cmd->response[0] = readl(&host->reg->rspreg0);
- dbg("cmd->resp[0]: %08x\n", cmd->response[0]);
+ debug("cmd->resp[0]: %08x\n", cmd->response[0]);
}
}
__func__, mask);
return -1;
} else if (mask & (1 << 3)) {
- /* DMA Interrupt */
- dbg("DMA end\n");
- break;
+ /*
+ * DMA Interrupt, restart the transfer where
+ * it was interrupted.
+ */
+ unsigned int address = readl(&host->reg->sysad);
+
+ debug("DMA end\n");
+ writel((1 << 3), &host->reg->norintsts);
+ writel(address, &host->reg->sysad);
} else if (mask & (1 << 1)) {
/* Transfer Complete */
- dbg("r/w is done\n");
+ debug("r/w is done\n");
break;
}
}
div = 2;
else
div = 1;
- dbg("div: %d\n", div);
+ debug("div: %d\n", div);
div >>= 1;
/*
clk = (div << 8) | (1 << 0);
writew(clk, &host->reg->clkcon);
+ set_mmc_clk(host->dev_index, div);
+
/* Wait max 10 ms */
timeout = 10;
while (!(readw(&host->reg->clkcon) & (1 << 1))) {
unsigned char ctrl;
unsigned long val;
- dbg("set_ios: bus_width: %x, clock: %d\n", mmc->bus_width, mmc->clock);
+ debug("bus_width: %x, clock: %d\n", mmc->bus_width, mmc->clock);
/*
* SELCLKPADDS[17:16]
ctrl = readb(&host->reg->hostctl);
/*
+ * WIDE8[5]
+ * 0 = Depend on WIDE4
+ * 1 = 8-bit mode
* WIDE4[1]
* 1 = 4-bit mode
* 0 = 1-bit mode
*/
- if (mmc->bus_width == 4)
+ if (mmc->bus_width == 8)
+ ctrl |= (1 << 5);
+ else if (mmc->bus_width == 4)
ctrl |= (1 << 1);
else
ctrl &= ~(1 << 1);
* NORMAL Interrupt Status Enable Register init
* [5] ENSTABUFRDRDY : Buffer Read Ready Status Enable
* [4] ENSTABUFWTRDY : Buffer write Ready Status Enable
+ * [3] ENSTADMAINT : DMA Interrupt Status Enable
* [1] ENSTASTANSCMPLT : Transfre Complete Status Enable
* [0] ENSTACMDCMPLT : Command Complete Status Enable
- */
+ */
mask = readl(&host->reg->norintstsen);
mask &= ~(0xffff);
- mask |= (1 << 5) | (1 << 4) | (1 << 1) | (1 << 0);
+ mask |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1) | (1 << 0);
writel(mask, &host->reg->norintstsen);
/*
return 0;
}
-static int s5p_mmc_initialize(int dev_index)
+static int s5p_mmc_initialize(int dev_index, int bus_width)
{
struct mmc *mmc;
mmc->send_cmd = mmc_send_cmd;
mmc->set_ios = mmc_set_ios;
mmc->init = mmc_core_init;
+ mmc->getcd = NULL;
mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
- mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS;
+ if (bus_width == 8)
+ mmc->host_caps = MMC_MODE_8BIT;
+ else
+ mmc->host_caps = MMC_MODE_4BIT;
+ mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
mmc->f_min = 400000;
mmc->f_max = 52000000;
+ mmc_host[dev_index].dev_index = dev_index;
mmc_host[dev_index].clock = 0;
mmc_host[dev_index].reg = s5p_get_base_mmc(dev_index);
+ mmc->b_max = 0;
mmc_register(mmc);
return 0;
}
-int s5p_mmc_init(int dev_index)
+int s5p_mmc_init(int dev_index, int bus_width)
{
- return s5p_mmc_initialize(dev_index);
+ return s5p_mmc_initialize(dev_index, bus_width);
}