#define RK29_SDMMC_WAIT_DTO_INTERNVAL 1500 //The time interval from the CMD_DONE_INT to DTO_INT
#define RK29_SDMMC_REMOVAL_DELAY 2000 //The time interval from the CD_INT to detect_timer react.
-#define RK29_SDMMC_VERSION "Ver.2.08 The last modify date is 2011-09-21,modifyed by XBW."
+#define RK29_SDMMC_VERSION "Ver.2.09 The last modify date is 2011-09-22,modifyed by XBW."
#define RK29_CTRL_SDMMC_ID 0 //mainly used by SDMMC
#define RK29_CTRL_SDIO1_ID 1 //mainly used by sdio-wifi
host->cmd = cmd;
host->old_cmd = cmd->opcode;
+ host->errorstep = 0;
rk29_sdmmc_write(host->regs, SDMMC_CMDARG, cmd->arg); // write to SDMMC_CMDARG register
rk29_sdmmc_write(host->regs, SDMMC_CMD, cmd_flags | SDMMC_CMD_START); // write to SDMMC_CMD register
static void send_stop_cmd(struct rk29_sdmmc *host)
{
+ int ret;
+
mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+600));
host->stopcmd.opcode = MMC_STOP_TRANSMISSION;
rk29_sdmmc_wait_unbusy(host);
- rk29_sdmmc_start_command(host, &host->stopcmd, host->cmdr);
+ ret = rk29_sdmmc_start_command(host, &host->stopcmd, host->cmdr);
+ if(SDM_SUCCESS != ret)
+ {
+ rk29_sdmmc_start_error(host);
+
+ host->state = STATE_IDLE;
+ host->complete_done = 4;
+ }
}
static void rk29_sdmmc_dma_cleanup(struct rk29_sdmmc *host)
}
else
{
- xbwprintk(3, "%s..%d... trace data, ======xbw=[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+ xbwprintk(7, "%s..%d... trace data, ======xbw=[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
output = rk29_sdmmc_submit_data_dma(host, data);
if(output)
{
rk29_sdmmc_write(host->regs, SDMMC_BYTCNT,data->blksz*data->blocks);
rk29_sdmmc_write(host->regs, SDMMC_BLKSIZ,data->blksz);
- xbwprintk(3, "%s..%d... trace data, CMD%d, data->blksz=%d, data->blocks=%d ======xbw=[%s]====\n", \
- __FUNCTION__, __LINE__, host->cmd->opcode,data->blksz, data->blocks, host->dma_name);
+ xbwprintk(3, "%s..%d..CMD%d(arg=0x%x), data->blksz=%d, data->blocks=%d ==xbw=[%s]==\n", \
+ __FUNCTION__, __LINE__, host->cmd->opcode,host->cmd->arg,data->blksz, data->blocks, host->dma_name);
if (data->flags & MMC_DATA_WRITE)
{
host->cmdr |= (SDMMC_CMD_DAT_WRITE | SDMMC_CMD_DAT_EXP);
- xbwprintk(3, "%s..%d... write data, len=%d ======xbw=[%s]====\n", \
+ xbwprintk(7, "%s..%d... write data, len=%d ======xbw=[%s]====\n", \
__FUNCTION__, __LINE__, data->blksz*data->blocks, host->dma_name);
ret = rk29_sdmmc_prepare_write_data(host, data);
else
{
host->cmdr |= (SDMMC_CMD_DAT_READ | SDMMC_CMD_DAT_EXP);
- xbwprintk(3, "%s..%d... read data len=%d ======xbw=[%s]====\n", \
+ xbwprintk(7, "%s..%d... read data len=%d ======xbw=[%s]====\n", \
__FUNCTION__, __LINE__, data->blksz*data->blocks, host->dma_name);
ret = rk29_sdmmc_prepare_read_data(host, data);
static void rk29_sdmmc_INT_CMD_DONE_timeout(unsigned long host_data)
{
struct rk29_sdmmc *host = (struct rk29_sdmmc *) host_data;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&host->lock, iflags);
if(STATE_SENDING_CMD == host->state)
{
rk29_sdmmc_dealwith_timeout(host);
}
+ spin_unlock_irqrestore(&host->lock, iflags);
}
static void rk29_sdmmc_INT_DTO_timeout(unsigned long host_data)
{
struct rk29_sdmmc *host = (struct rk29_sdmmc *) host_data;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&host->lock, iflags);
if( (host->cmdr & SDMMC_CMD_DAT_EXP) && (STATE_DATA_BUSY == host->state))
rk29_sdmmc_dealwith_timeout(host);
}
+ spin_unlock_irqrestore(&host->lock, iflags);
+
}
__FUNCTION__, __LINE__, host->state, host->cmd->opcode,mrq->cmd->opcode,mrq->cmd->arg, host->dma_name);
}
+ host->new_mrq = mrq;
spin_unlock_irqrestore(&host->lock, iflags);
- host->new_mrq = mrq;
rk29_sdmmc_start_request(mmc);
#else
}
+static int rk29_sdmmc_clear_fifo(struct rk29_sdmmc *host)
+{
+ unsigned int timeout, value;
+
+ if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+ {
+ rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF);
+ }
+
+ //stop DMA
+ if(host->dodma)
+ {
+ rk29_sdmmc_stop_dma(host);
+ rk29_sdmmc_control_host_dma(host, FALSE);
+ host->dodma = 0;
+ }
+
+ //Clean the fifo.
+ for(timeout=0; timeout<FIFO_DEPTH; timeout++)
+ {
+ if(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_FIFO_EMPTY)
+ break;
+
+ value = rk29_sdmmc_read(host->regs, SDMMC_DATA);
+ }
+
+ /* reset */
+ rk29_sdmmc_write(host->regs, SDMMC_CTRL,(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET ));
+
+ timeout = 1000;
+ value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
+ while (( value & (SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_RESET)) && (timeout > 0))
+ {
+ udelay(1);
+ timeout--;
+ value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
+ }
+
+ if (timeout == 0)
+ {
+ host->errorstep = 0x0A;
+ return SDM_WAIT_FOR_FIFORESET_TIMEOUT;
+ }
+}
+
+
static const struct mmc_host_ops rk29_sdmmc_ops[] = {
{
{
if(status & (SDMMC_INT_DCRC | SDMMC_INT_EBE))
{
- cmd->data->error = -EILSEQ;;//mrq->data->error = -EILSEQ;
+ cmd->data->error = -EILSEQ;
output = SDM_DATA_CRC_ERROR;
host->errorstep = 0x16;
}
struct mmc_data *data = host->cmd->data;
enum rk29_sdmmc_state state = host->state;
int pending_flag, stopflag;
+ unsigned long iflags;
- spin_lock(&host->lock);
+ spin_lock_irqsave(&host->lock, iflags);
state = host->state;
pending_flag = 0;
unlock:
if(0==host->complete_done)
{
- spin_unlock(&host->lock);
+ spin_unlock_irqrestore(&host->lock, iflags);
return;
}
if(host->mrq && host->mmc->doneflag)
{
host->mmc->doneflag = 0;
- spin_unlock(&host->lock);
+ spin_unlock_irqrestore(&host->lock, iflags);
mmc_request_done(host->mmc, host->mrq);
}
else
{
- spin_unlock(&host->lock);
+ spin_unlock_irqrestore(&host->lock, iflags);
}
}
}
else
{
- mmc->f_max = RK29_MAX_SDIO_FREQ;//SDHC_FPP_FREQ / 2;
+ mmc->f_max = RK29_MAX_SDIO_FREQ;
}
#endif