static void dw_mci_disable_low_power(struct dw_mci_slot *slot);
/*printk the all register of current host*/
+#if 0
static int dw_mci_regs_printk(struct dw_mci *host)
{
struct sdmmc_reg *regs = dw_mci_regs;
printk("=======printk %s-register end =========\n", mmc_hostname(host->mmc));
return 0;
}
-
+#endif
#if defined(CONFIG_DEBUG_FS)
static int dw_mci_req_show(struct seq_file *s, void *v)
return cmdr;
}
+#if 0
static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
{
struct mmc_command *stop;
return cmdr;
}
-
+#endif
static void dw_mci_start_command(struct dw_mci *host,
struct mmc_command *cmd, u32 cmd_flags)
{
- unsigned long time_loop = jiffies + msecs_to_jiffies(5000);
- unsigned int status;
- bool ret=0;
-
- host->pre_cmd = host->cmd;
+ struct dw_mci_slot *slot = host->slot[0];
+ /*temporality fix slot[0] due to host->num_slots equal to 1*/
+
+ host->pre_cmd = host->cmd;
host->cmd = cmd;
dev_vdbg(host->dev,
- "start command: ARGR=0x%08x CMDR=0x%08x\n",
- cmd->arg, cmd_flags);
-
- if(SD_SWITCH_VOLTAGE == cmd->opcode){
- /*confirm non-low-power mode*/
- struct dw_mci_slot *slot = host->slot[0];//temporality fix slot[0] due to host->num_slots equal to 1;
- mci_writel(host, CMDARG, 0);
- dw_mci_disable_low_power(slot);
- MMC_DBG_INFO_FUNC(host->mmc,"Line%d..%s before start cmd=11,[%s]",
- __LINE__, __FUNCTION__,mmc_hostname(host->mmc));
-
- cmd_flags |= SDMMC_CMD_VOLT_SWITCH;
- }
+ "start command: ARGR=0x%08x CMDR=0x%08x\n",
+ cmd->arg, cmd_flags);
+
+ if(SD_SWITCH_VOLTAGE == cmd->opcode){
+ /*confirm non-low-power mode*/
+ mci_writel(host, CMDARG, 0);
+ dw_mci_disable_low_power(slot);
+
+ MMC_DBG_INFO_FUNC(host->mmc,"Line%d..%s before start cmd=11,[%s]",
+ __LINE__, __FUNCTION__,mmc_hostname(host->mmc));
+
+ cmd_flags |= SDMMC_CMD_VOLT_SWITCH;
+ }
mci_writel(host, CMDARG, cmd->arg);
wmb();
- if(host->mmc->hold_reg_flag)
- cmd_flags |= SDMMC_CMD_USE_HOLD_REG;//fix the value to 1 in some Soc,for example RK3188.
-
- mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
- wmb();
+
+ /* fix the value to 1 in some Soc,for example RK3188. */
+ if(host->mmc->hold_reg_flag)
+ cmd_flags |= SDMMC_CMD_USE_HOLD_REG;
-#if 0//test
- while ((time_before(jiffies, time_loop))&&(test_bit(DW_MMC_CARD_PRESENT, &host->cur_slot->flags))){
- status = mci_readl(host, STATUS);
- if (!(status & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY))){
- ret = 1 ;//card is unbusy
- break;
- }
- } ;
- if(!ret)
- MMC_DBG_ERR_FUNC(host->mmc,"Line%d..%s start cmd=%d(arg=0x%x), cmd_reg=0x%x, unbusy=%d,card-present=%d. [%s]",
- __LINE__, __FUNCTION__,cmd->opcode, cmd->arg,cmd_flags,
- ret,test_bit(DW_MMC_CARD_PRESENT, &host->cur_slot->flags), mmc_hostname(host->mmc));
-#endif
+ mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
+ wmb();
}
static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data)
}
}
-static int mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
+static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
{
struct dw_mci *host = slot->host;
unsigned long timeout = jiffies + msecs_to_jiffies(500);//msecs_to_jiffies(5000);
unsigned int cmd_status = 0;
#ifdef SDMMC_WAIT_FOR_UNBUSY
+ bool ret = true;
timeout = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY);
- bool ret=0;
+
if(test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) {
- while (ret=time_before(jiffies, timeout)) {
+ while (ret) {
+ ret = time_before(jiffies, timeout);
cmd_status = mci_readl(host, STATUS);
if (!(cmd_status & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY)))
break;
} ;
- if(!ret)
+ if(false == ret)
printk("%d..%s: wait for unbusy timeout.......[%s]\n", \
__LINE__, __FUNCTION__, mmc_hostname(host->mmc));
}
while (time_before(jiffies, timeout)) {
cmd_status = mci_readl(host, CMD);
if (!(cmd_status & SDMMC_CMD_START))
- return 0;
+ return ;
}
dev_err(&slot->mmc->class_dev,
"Timeout sending command (cmd %#x arg %#x status %#x)\n",
cmd, arg, cmd_status);
- return -EAGAIN;
}
-static int dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
+static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
{
struct dw_mci *host = slot->host;
unsigned int tempck,clock = slot->clock;
u32 div;
u32 clk_en_a;
u32 sdio_int;
- int ret = 0;
- MMC_DBG_INFO_FUNC(host->mmc,"%d..%s: clock=%d, current_speed=%d, bus_hz=%d,forc=%d[%s]\n",
+ MMC_DBG_INFO_FUNC(host->mmc,"%d..%s: clock=%d, current_speed=%d, bus_hz=%d,forc=%d[%s]\n",
__LINE__, __FUNCTION__, clock, host->current_speed,host->bus_hz,force_clkinit,mmc_hostname(host->mmc));
if (!clock) {
mci_writel(host, CLKENA, 0);
- ret = mci_send_cmd(slot,
+ mci_send_cmd(slot,
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
- if(ret < 0)
- return -EAGAIN;
+
} else if (clock != host->current_speed || force_clkinit) {
div = host->bus_hz / clock;
if (host->bus_hz % clock && host->bus_hz > clock)
mci_writel(host, CLKSRC, 0);
/* inform CIU */
- ret = mci_send_cmd(slot,
+ mci_send_cmd(slot,
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
- if(ret < 0)
- return -EAGAIN;
if(clock <= 400*1000){
MMC_DBG_BOOT_FUNC(host->mmc,
mci_writel(host, CLKDIV, div);
/* inform CIU */
- ret = mci_send_cmd(slot,
+ mci_send_cmd(slot,
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
- if(ret < 0)
- return -EAGAIN;
/* enable clock; only low power if no SDIO */
clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
mci_writel(host, CLKENA, clk_en_a);
/* inform CIU */
- ret = mci_send_cmd(slot,
+ mci_send_cmd(slot,
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
- if(ret < 0)
- return -EAGAIN;
/* keep the clock with reflecting clock dividor */
slot->__clk_old = clock << div;
}
/* Set the current slot bus width */
mci_writel(host, CTYPE, (slot->ctype << slot->id));
- return ret;
}
static void dw_mci_wait_unbusy(struct dw_mci *host)
spin_unlock_bh(&host->lock);
}
-static int dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
u32 regs;
-#ifdef SDMMC_WAIT_FOR_UNBUSY
- unsigned long time_loop = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY);
- bool ret=0;
-
- if(!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)){
- printk("%d..%s: no card. [%s]\n", \
- __LINE__, __FUNCTION__, mmc_hostname(mmc));
- goto EXIT_POWER;
- }
+#ifdef SDMMC_WAIT_FOR_UNBUSY
+ unsigned long time_loop = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY);
+ bool ret = true;
+
+ if(!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)){
+ printk("%d..%s: no card. [%s]\n", \
+ __LINE__, __FUNCTION__, mmc_hostname(mmc));
+ goto EXIT_POWER;
+ }
- while (ret=time_before(jiffies, time_loop)) {
- regs = mci_readl(slot->host, STATUS);
- if (!(regs & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY)))
- break;
- } ;
- if(!ret)
- {
- printk("slot->flags=%d ", slot->flags);
- dump_stack();
- printk("%d..%s: wait for unbusy timeout....... STATUS = 0x%x[%s]\n", \
- __LINE__, __FUNCTION__, regs, mmc_hostname(mmc));
- }
+ while (ret) {
+ ret = time_before(jiffies, time_loop);
+ regs = mci_readl(slot->host, STATUS);
+ if (!(regs & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY)))
+ break;
+ };
+
+ if(false == ret)
+ {
+ printk("slot->flags = %lu ", slot->flags);
+ dump_stack();
+ printk("%d..%s: wait for unbusy timeout....... STATUS = 0x%x [%s]\n", \
+ __LINE__, __FUNCTION__, regs, mmc_hostname(mmc));
+ }
#endif
switch (ios->bus_width) {
case MMC_BUS_WIDTH_4:
drv_data->set_ios(slot->host, ios);
/* Slot specific timing and width adjustment */
- if(dw_mci_setup_bus(slot, false) < 0)
- return -EAGAIN;
+ dw_mci_setup_bus(slot, false);
+ //return -EAGAIN;
EXIT_POWER:
switch (ios->power_mode) {
default:
break;
}
- return 0;
}
static int dw_mci_get_ro(struct mmc_host *mmc)
static int dw_mci_set_sdio_status(struct mmc_host *mmc, int val)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
- struct dw_mci_board *brd = slot->host->pdata;
+ /*struct dw_mci_board *brd = slot->host->pdata;*/
struct dw_mci *host = slot->host;
if (!(mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO))
return 0;
{
struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
- u32 cmd_flags, timeout, regs;
- bool ret = true;
+ u32 cmd_flags, regs;
+ unsigned long timeout;
+ bool ret = true;
/* (1) CMD12 to end any transfer in process */
cmd_flags = SDMMC_CMD_STOP | SDMMC_CMD_RESP_CRC
}
}
-
+#if 0
static int dw_mci_do_start_signal_voltage_switch(struct dw_mci *host,
struct mmc_ios *ios)
{
//sdhci_runtime_pm_put(host);
return err;
}
-
+#endif
static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
//.start_signal_voltage_switch = dw_mci_start_signal_voltage_switch,
//.card_busy = dw_mci_card_busy,
};
-
+#if 0
static void dw_mci_enable_irq(struct dw_mci *host, bool irqflag)
{
unsigned long flags;
}
local_irq_restore(flags);
}
-
+#endif
static void dw_mci_deal_data_end(struct dw_mci *host, struct mmc_request *mrq)
__releases(&host->lock)
__acquires(&host->lock)
struct mmc_command *cmd;
enum dw_mci_state state;
enum dw_mci_state prev_state;
- u32 status, ctrl, cmd_flags;
+ u32 status, cmd_flags;
unsigned long timeout = 0;
- bool ret = 0;
+ bool ret = true;
spin_lock(&host->lock);
if (test_and_clear_bit(EVENT_DATA_ERROR, &host->pending_events)) {
dw_mci_stop_dma(host);
#if 1
- if (data->stop)
+ if (data->stop){
send_stop_cmd(host, data);
- else{
+ }else{
/*single block read/write, send stop cmd manually to prevent host controller halt*/
MMC_DBG_INFO_FUNC(host->mmc, "%s status 1 0x%08x [%s]\n",
__func__, mci_readl(host, STATUS), mmc_hostname(host->mmc));
wmb();
timeout = jiffies + msecs_to_jiffies(500);
- while(ret = time_before(jiffies, timeout)){
+ while(ret){
+ ret = time_before(jiffies, timeout);
if(!(mci_readl(host, CMD) & SDMMC_CMD_START))
break;
}
- if(!ret)
- MMC_DBG_ERR_FUNC(host->mmc, "%s EVENT_DATA_ERROR recovery failed!!! [%s]\n",
+ if(false == ret)
+ MMC_DBG_ERR_FUNC(host->mmc,
+ "%s EVENT_DATA_ERROR recovery failed!!! [%s]\n",
__func__, mmc_hostname(host->mmc));
}
#else
break;
}
- MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: STATE_SENDING_DATA, wait for EVENT_XFER_COMPLETE.[%s]",\
+ MMC_DBG_CMD_FUNC(host->mmc,
+ "Pre-state[%d]-->NowState[%d]: STATE_SENDING_DATA, wait for EVENT_XFER_COMPLETE.[%s]",\
prev_state,state, mmc_hostname(host->mmc));
if (!test_and_clear_bit(EVENT_XFER_COMPLETE,
&host->pending_events))
break;
- MMC_DBG_INFO_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: STATE_SENDING_DATA, wait for EVENT_DATA_COMPLETE. [%s]",\
+ MMC_DBG_INFO_FUNC(host->mmc,
+ "Pre-state[%d]-->NowState[%d]: STATE_SENDING_DATA, wait for EVENT_DATA_COMPLETE. [%s]",\
prev_state,state,mmc_hostname(host->mmc));
set_bit(EVENT_XFER_COMPLETE, &host->completed_events);
break;
dw_mci_deal_data_end(host, host->mrq);
- MMC_DBG_INFO_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: STATE_DATA_BUSY, after EVENT_DATA_COMPLETE. [%s]", \
+ MMC_DBG_INFO_FUNC(host->mmc,
+ "Pre-state[%d]-->NowState[%d]: STATE_DATA_BUSY, after EVENT_DATA_COMPLETE. [%s]", \
prev_state,state,mmc_hostname(host->mmc));
host->data = NULL;
if (status & DW_MCI_DATA_ERROR_FLAGS) {
if((SDMMC_CTYPE_1BIT != slot->ctype)&&(MMC_SEND_EXT_CSD == host->mrq->cmd->opcode))
- MMC_DBG_ERR_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: DW_MCI_DATA_ERROR_FLAGS,datastatus=0x%x [%s]",\
+ MMC_DBG_ERR_FUNC(host->mmc,
+ "Pre-state[%d]-->NowState[%d]: DW_MCI_DATA_ERROR_FLAGS,datastatus=0x%x [%s]",\
prev_state,state, status, mmc_hostname(host->mmc));
if (status & SDMMC_INT_DRTO) {
} else if (status & SDMMC_INT_DCRC) {
data->error = -EILSEQ;
} else if (status & SDMMC_INT_EBE &&
- host->dir_status ==
- DW_MCI_SEND_STATUS) {
+ host->dir_status == DW_MCI_SEND_STATUS){
/*
* No data CRC status was returned.
* The number of bytes transferred will
unsigned int remain, fcnt;
if(!host->mmc->bus_refs){
- printk("Note: %s host->mmc->bus_refs is 0!!!\n",__func__,host->mmc->bus_refs);
+ printk("Note: %s host->mmc->bus_refs is 0!!!\n", __func__);
goto host_put;
}
do {
unsigned int remain, fcnt;
if(!host->mmc->bus_refs){
- printk("Note: %s host->mmc->bus_refs is 0!!!\n",__func__,host->mmc->bus_refs);
+ printk("Note: %s host->mmc->bus_refs is 0!!!\n", __func__);
goto host_put;
}
struct mmc_host *mmc = slot->mmc;
struct mmc_request *mrq;
int present;
- u32 ctrl;
present = dw_mci_get_cd(mmc);
while (present != slot->last_detect_state) {
}
#ifdef CONFIG_OF
+/*
static struct dw_mci_of_quirks {
char *quirk;
int id;
.id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
},
};
-
+*/
static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
{
struct dw_mci_board *pdata;
struct device *dev = host->dev;
struct device_node *np = dev->of_node;
const struct dw_mci_drv_data *drv_data = host->drv_data;
- int idx, ret;
+ int ret;
u32 clock_frequency;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
}
}
-RESUME_AGAIN:
if (!dw_mci_ctrl_all_reset(host)) {
ret = -ENODEV;
return ret;
enable_irq(host->irq);
}
- if((retry_cnt++) > 0x100) {
- dev_err(host->dev,
- "failed to resume controller: %d.[%s]\n", ret, mmc_hostname(host->mmc));
- return -ENODEV;
- }
- if(retry_cnt > 1)
- dev_err("%s sdmmc resume error.[%s]\n",__func__, mmc_hostname(host->mmc));
for (i = 0; i < host->num_slots; i++) {
struct dw_mci_slot *slot = host->slot[i];
if (!slot)
continue;
if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
- if(dw_mci_set_ios(slot->mmc, &slot->mmc->ios) < 0)
- goto RESUME_AGAIN;
- if(dw_mci_setup_bus(slot, true) < 0)
- goto RESUME_AGAIN;
+ dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
+ dw_mci_setup_bus(slot, true);
}
}