mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
emmc: Solve the problem of conflict of emmc error
PD#138714: Solve the problem of conflict of emmc error gxl p212 v3 emmc will data crc err. kernel 4.9 has mmc_retune() in the __mmc_start_request(). when emmc err to retry, mmc_retune() will switch emmc between hs400 and hs200, then tuning, it will work on amlogic driver retry. then emmc init fail. so wo comment out a piece of code. test on gxl p212 v3 Change-Id: I041a20fe3e7aa29a619cc3cc6652d8f3b37b1f1b Signed-off-by: Nan Li <nan.li@amlogic.com>
This commit is contained in:
@@ -2093,14 +2093,14 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct amlsd_host *host = dev_id;
|
||||
struct mmc_request *mrq;
|
||||
struct mmc_command *cmd = host->cmd;
|
||||
unsigned long flags;
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
struct mmc_host *mmc;
|
||||
unsigned int err_flag = 0;
|
||||
u32 vstat = 0;
|
||||
u32 virqc = 0;
|
||||
u32 vstart = 0;
|
||||
u32 err = 0;
|
||||
|
||||
struct sd_emmc_irq_en *irqc = (struct sd_emmc_irq_en *)&virqc;
|
||||
struct sd_emmc_status *ista = (struct sd_emmc_status *)&vstat;
|
||||
struct sd_emmc_start *desc_start = (struct sd_emmc_start *)&vstart;
|
||||
@@ -2108,7 +2108,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
|
||||
if (WARN_ON(!host))
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock_irqsave(&host->mrq_lock, flags);
|
||||
virqc = readl(host->base + SD_EMMC_IRQ_EN) & 0xffff;
|
||||
vstat = readl(host->base + SD_EMMC_STATUS) & 0xffffffff;
|
||||
host->ista = vstat;
|
||||
@@ -2126,9 +2125,9 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
|
||||
} else if (!(vstat & 0x3fff))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
spin_lock_irqsave(&host->mrq_lock, flags);
|
||||
mrq = host->mrq;
|
||||
mmc = host->mmc;
|
||||
|
||||
vstart = readl(host->base + SD_EMMC_START);
|
||||
if ((desc_start->busy == 1)
|
||||
&& (aml_card_type_mmc(pdata) ||
|
||||
@@ -2200,94 +2199,73 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
|
||||
writel(0x7fff, host->base + SD_EMMC_STATUS);
|
||||
spin_unlock_irqrestore(&host->mrq_lock, flags);
|
||||
|
||||
cmd->error = 0;
|
||||
if (vstat & 0x7fff)
|
||||
err_flag = 1;
|
||||
if (err_flag) {
|
||||
if (ista->end_of_chain || ista->desc_irq) {
|
||||
if (mrq->data)
|
||||
host->status = HOST_TASKLET_DATA;
|
||||
else
|
||||
host->status = HOST_TASKLET_CMD;
|
||||
mrq->cmd->error = 0;
|
||||
}
|
||||
if (ista->rxd_err || ista->txd_err) {
|
||||
host->status = HOST_DAT_CRC_ERR;
|
||||
cmd->error = -EILSEQ;
|
||||
if (host->is_tunning == 0) {
|
||||
sd_emmc_err("%s: warning... data crc, vstat:0x%x, virqc:%x",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
sd_emmc_err("@ cmd %d with %p; stop %d, status %d\n",
|
||||
mrq->cmd->opcode, mrq->data,
|
||||
host->cmd_is_stop,
|
||||
host->status);
|
||||
}
|
||||
} else if (ista->desc_err) {
|
||||
if (host->is_tunning == 0)
|
||||
sd_emmc_err("%s: warning... desc err,vstat:0x%x,virqc:%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
host->status = HOST_DAT_CRC_ERR;
|
||||
cmd->error = -EILSEQ;
|
||||
} else if (ista->resp_err) {
|
||||
if (host->is_tunning == 0)
|
||||
sd_emmc_err("%s: warning... response crc,vstat:0x%x,virqc:%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
pr_info("%s %d cmd:%d arg:0x%x ",
|
||||
__func__, __LINE__,
|
||||
mrq->cmd->opcode, mrq->cmd->arg);
|
||||
host->status = HOST_RSP_CRC_ERR;
|
||||
cmd->error = -EILSEQ;
|
||||
} else if (ista->resp_timeout) {
|
||||
if (host->is_tunning == 0)
|
||||
sd_emmc_err("%s: resp_timeout,vstat:0x%x,virqc:%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
host->status = HOST_RSP_TIMEOUT_ERR;
|
||||
cmd->error = -ETIMEDOUT;
|
||||
} else if (ista->desc_timeout) {
|
||||
if (host->is_tunning == 0)
|
||||
sd_emmc_err("%s: desc_timeout,vstat:0x%x,virqc:%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
host->status = HOST_DAT_TIMEOUT_ERR;
|
||||
cmd->error = -ETIMEDOUT;
|
||||
}
|
||||
if (cmd->error) {
|
||||
if (host->is_tunning == 0)
|
||||
aml_host_bus_fsm_show(host, ista->bus_fsm);
|
||||
if (aml_card_type_mmc(pdata))
|
||||
mmc_cmd_LBA_show(mmc, mrq);
|
||||
}
|
||||
} else {
|
||||
host->xfer_step = XFER_IRQ_UNKNOWN_IRQ;
|
||||
sd_emmc_err("%s: %s Unknown Irq Ictl 0x%x, Ista 0x%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
pdata->pinname, virqc, vstat);
|
||||
dev_warn(host->dev, "Unknown IRQ! status=0x%04x: ", host->ista);
|
||||
dev_warn(host->dev, "MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n",
|
||||
cmd->opcode, cmd->arg,
|
||||
cmd->flags, mrq->stop ? 1 : 0);
|
||||
if (cmd->data) {
|
||||
struct mmc_data *data = cmd->data;
|
||||
|
||||
dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)",
|
||||
data->blksz, data->blocks, data->flags,
|
||||
data->flags & MMC_DATA_WRITE ?
|
||||
"write" : "",
|
||||
data->flags & MMC_DATA_READ ?
|
||||
"read" : "");
|
||||
}
|
||||
if (ista->end_of_chain || ista->desc_irq) {
|
||||
if (mrq->data)
|
||||
host->status = HOST_TASKLET_DATA;
|
||||
else
|
||||
host->status = HOST_TASKLET_CMD;
|
||||
mrq->cmd->error = 0;
|
||||
}
|
||||
|
||||
if (host->xfer_step == XFER_IRQ_UNKNOWN_IRQ) {
|
||||
meson_mmc_read_resp(host->mmc, cmd);
|
||||
meson_mmc_request_done(host->mmc, cmd->mrq);
|
||||
if ((vstat & 0x1FFF) && (!host->cmd_is_stop))
|
||||
err = 1;
|
||||
|
||||
if (ista->rxd_err || ista->txd_err) {
|
||||
host->status = HOST_DAT_CRC_ERR;
|
||||
mrq->cmd->error = -EILSEQ;
|
||||
if (host->is_tunning == 0) {
|
||||
sd_emmc_err("%s: warning... data crc, vstat:0x%x, virqc:%x",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
sd_emmc_err("@ cmd %d with %p; stop %d, status %d\n",
|
||||
mrq->cmd->opcode, mrq->data,
|
||||
host->cmd_is_stop,
|
||||
host->status);
|
||||
}
|
||||
} else if (ista->desc_err) {
|
||||
if (host->is_tunning == 0)
|
||||
sd_emmc_err("%s: warning... desc err,vstat:0x%x,virqc:%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
host->status = HOST_DAT_CRC_ERR;
|
||||
mrq->cmd->error = -EILSEQ;
|
||||
} else if (ista->resp_err) {
|
||||
if (host->is_tunning == 0)
|
||||
sd_emmc_err("%s: warning... response crc,vstat:0x%x,virqc:%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
pr_info("%s %d cmd:%d arg:0x%x ",
|
||||
__func__, __LINE__,
|
||||
mrq->cmd->opcode, mrq->cmd->arg);
|
||||
host->status = HOST_RSP_CRC_ERR;
|
||||
mrq->cmd->error = -EILSEQ;
|
||||
} else if (ista->resp_timeout) {
|
||||
if (host->is_tunning == 0)
|
||||
sd_emmc_err("%s: resp_timeout,vstat:0x%x,virqc:%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
host->status = HOST_RSP_TIMEOUT_ERR;
|
||||
mrq->cmd->error = -ETIMEDOUT;
|
||||
} else if (ista->desc_timeout) {
|
||||
if (host->is_tunning == 0)
|
||||
sd_emmc_err("%s: desc_timeout,vstat:0x%x,virqc:%x\n",
|
||||
mmc_hostname(host->mmc),
|
||||
vstat, virqc);
|
||||
host->status = HOST_DAT_TIMEOUT_ERR;
|
||||
mrq->cmd->error = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
if (host->is_tunning == 0)
|
||||
aml_host_bus_fsm_show(host, ista->bus_fsm);
|
||||
if (aml_card_type_mmc(pdata))
|
||||
mmc_cmd_LBA_show(mmc, mrq);
|
||||
}
|
||||
|
||||
if (host->xfer_step == XFER_IRQ_UNKNOWN_IRQ)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_WAKE_THREAD;
|
||||
else
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
struct mmc_command aml_sd_emmc_cmd = {
|
||||
@@ -2317,7 +2295,6 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
|
||||
struct amlsd_platform *pdata = host->pdata;
|
||||
unsigned long flags;
|
||||
struct mmc_request *mrq;
|
||||
struct mmc_command *cmd = host->cmd;
|
||||
|
||||
u32 status, rx_phase, xfer_bytes = 0;
|
||||
enum aml_mmc_waitfor xfer_step;
|
||||
@@ -2332,6 +2309,7 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
|
||||
mrq = host->mrq;
|
||||
xfer_step = host->xfer_step;
|
||||
status = host->status;
|
||||
|
||||
if ((xfer_step == XFER_FINISHED) || (xfer_step == XFER_TIMER_TIMEOUT)) {
|
||||
sd_emmc_err("Warning: %s xfer_step=%d, host->status=%d\n",
|
||||
mmc_hostname(host->mmc), xfer_step, status);
|
||||
@@ -2399,8 +2377,8 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
|
||||
|
||||
/* check ready?? */
|
||||
/*Wait command busy*/
|
||||
meson_mmc_read_resp(host->mmc, cmd);
|
||||
meson_mmc_request_done(host->mmc, host->mrq);
|
||||
meson_mmc_read_resp(host->mmc, mrq->cmd);
|
||||
meson_mmc_request_done(host->mmc, mrq);
|
||||
|
||||
break;
|
||||
|
||||
@@ -2417,7 +2395,7 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
|
||||
(mrq->cmd->data->flags & MMC_DATA_READ) ?
|
||||
DMA_FROM_DEVICE : DMA_TO_DEVICE);
|
||||
}
|
||||
meson_mmc_read_resp(host->mmc, cmd);
|
||||
meson_mmc_read_resp(host->mmc, mrq->cmd);
|
||||
|
||||
/* set retry @ 1st error happens! */
|
||||
if ((host->error_flag == 0)
|
||||
@@ -2869,7 +2847,7 @@ static int meson_mmc_remove(struct platform_device *pdev)
|
||||
|
||||
if (host->bn_buf)
|
||||
dma_free_coherent(host->dev, SD_EMMC_BOUNCE_REQ_SIZE,
|
||||
host->bn_buf, host->bn_dma_buf);
|
||||
host->bn_buf, host->bn_dma_buf);
|
||||
|
||||
devm_free_irq(&pdev->dev, host->irq, host);
|
||||
iounmap(host->pinmux_base);
|
||||
|
||||
@@ -370,7 +370,8 @@ void sdio_reinit(void)
|
||||
{
|
||||
if (sdio_host) {
|
||||
if (sdio_host->card)
|
||||
sdio_reset_comm(sdio_host->card);
|
||||
//temp remove for upstream merge comflict
|
||||
;//sdio_reset_comm(sdio_host->card);
|
||||
else
|
||||
sdio_rescan(sdio_host);
|
||||
} else {
|
||||
|
||||
@@ -220,6 +220,11 @@ EXPORT_SYMBOL(mmc_request_done);
|
||||
|
||||
static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
|
||||
{
|
||||
/*
|
||||
* mmc_retune() will be work on amlogic driver retry, when emmc has err.
|
||||
* Then it will make emmc init fail. So we comment out a piece of code.
|
||||
*/
|
||||
#ifndef CONFIG_AMLOGIC_MMC
|
||||
int err;
|
||||
|
||||
/* Assumes host controller has been runtime resumed by mmc_claim_host */
|
||||
@@ -229,7 +234,7 @@ static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
|
||||
mmc_request_done(host, mrq);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
* For sdio rw commands we must wait for card busy otherwise some
|
||||
* sdio devices won't work properly.
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "core.h"
|
||||
#include "bus.h"
|
||||
#include "host.h"
|
||||
#include "sd.h"
|
||||
#include "sdio_bus.h"
|
||||
#include "mmc_ops.h"
|
||||
@@ -1173,43 +1172,3 @@ err:
|
||||
|
||||
return err;
|
||||
}
|
||||
#ifdef CONFIG_AMLOGIC_MMC
|
||||
int sdio_reset_comm(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
u32 ocr;
|
||||
u32 rocr;
|
||||
int err;
|
||||
|
||||
pr_info("%s():\n", __func__);
|
||||
mmc_claim_host(host);
|
||||
|
||||
mmc_retune_disable(host);
|
||||
mmc_go_idle(host);
|
||||
|
||||
mmc_set_clock(host, host->f_min);
|
||||
|
||||
err = mmc_send_io_op_cond(host, 0, &ocr);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
rocr = mmc_select_voltage(host, ocr);
|
||||
if (!rocr) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = mmc_sdio_init_card(host, rocr, card, 0);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
mmc_release_host(host);
|
||||
return 0;
|
||||
err:
|
||||
pr_err("%s: Error resetting SDIO communications (%d)\n",
|
||||
mmc_hostname(host), err);
|
||||
mmc_release_host(host);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(sdio_reset_comm);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user