X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmmc%2Fs5p_mmc.c;h=7786ecf2be87e02ed5727082326f8b15d5632ddf;hb=4d28db8a1e8b90e1e3ffd95d7f949b849e33fa2f;hp=669b1d0d2f91c2755689c9ce1d857761dc802c6a;hpb=201532a69cf7e7a84bff354fdab45947425d22b4;p=u-boot diff --git a/drivers/mmc/s5p_mmc.c b/drivers/mmc/s5p_mmc.c index 669b1d0d2f..7786ecf2be 100644 --- a/drivers/mmc/s5p_mmc.c +++ b/drivers/mmc/s5p_mmc.c @@ -22,12 +22,7 @@ #include #include #include - -#ifdef DEBUG_S5P_HSMMC -#define dbg(x...) printf(x) -#else -#define dbg(x...) do { } while (0) -#endif +#include /* support 4 mmc hosts */ struct mmc mmc_dev[4]; @@ -36,18 +31,14 @@ struct mmc_host mmc_host[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] @@ -61,7 +52,7 @@ static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data) 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); } @@ -128,7 +119,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, 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) @@ -165,7 +156,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, 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); @@ -186,11 +177,11 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, 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; } @@ -206,7 +197,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, 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) { @@ -223,10 +214,10 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } 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]); } } @@ -241,12 +232,18 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, __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; } } @@ -288,7 +285,7 @@ static void mmc_change_clock(struct mmc_host *host, uint clock) div = 2; else div = 1; - dbg("div: %d\n", div); + debug("div: %d\n", div); div >>= 1; /* @@ -301,6 +298,8 @@ static void mmc_change_clock(struct mmc_host *host, uint clock) 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))) { @@ -325,7 +324,7 @@ static void mmc_set_ios(struct mmc *mmc) 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] @@ -362,11 +361,16 @@ static void mmc_set_ios(struct mmc *mmc) 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); @@ -427,12 +431,13 @@ static int mmc_core_init(struct mmc *mmc) * 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); /* @@ -447,7 +452,7 @@ static int mmc_core_init(struct mmc *mmc) return 0; } -static int s5p_mmc_initialize(int dev_index) +static int s5p_mmc_initialize(int dev_index, int bus_width) { struct mmc *mmc; @@ -460,19 +465,25 @@ static int s5p_mmc_initialize(int dev_index) mmc->init = mmc_core_init; 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); }