Skip to content

Commit 9e2582e

Browse files
yong maostorulf
authored andcommitted
mmc: mediatek: fix SDIO irq issue
SDIO irq is not triggered by low level, but by falling edge in our previous IC. This mechanism only have one chance to catch the SDIO irq if a SDIO irq comes within the multiple block transmission. This SDIO irq may be easily lost, because falling edge appears only once within 2 clock after data transmission is completed. SDIO irq recheck mechanism will make sure all irqs can be processed correctly. Signed-off-by: Yong Mao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent d4a384c commit 9e2582e

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

drivers/mmc/host/mtk-sd.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
#define MSDC_PS_CDSTS (0x1 << 1) /* R */
129129
#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */
130130
#define MSDC_PS_DAT (0xff << 16) /* R */
131+
#define MSDC_PS_DATA1 (0x1 << 17) /* R */
131132
#define MSDC_PS_CMD (0x1 << 24) /* R */
132133
#define MSDC_PS_WP (0x1 << 31) /* R */
133134

@@ -361,6 +362,7 @@ struct msdc_save_para {
361362

362363
struct mtk_mmc_compatible {
363364
u8 clk_div_bits;
365+
bool recheck_sdio_irq;
364366
bool hs400_tune; /* only used for MT8173 */
365367
u32 pad_tune_reg;
366368
bool async_fifo;
@@ -436,6 +438,7 @@ struct msdc_host {
436438

437439
static const struct mtk_mmc_compatible mt8135_compat = {
438440
.clk_div_bits = 8,
441+
.recheck_sdio_irq = false,
439442
.hs400_tune = false,
440443
.pad_tune_reg = MSDC_PAD_TUNE,
441444
.async_fifo = false,
@@ -448,6 +451,7 @@ static const struct mtk_mmc_compatible mt8135_compat = {
448451

449452
static const struct mtk_mmc_compatible mt8173_compat = {
450453
.clk_div_bits = 8,
454+
.recheck_sdio_irq = true,
451455
.hs400_tune = true,
452456
.pad_tune_reg = MSDC_PAD_TUNE,
453457
.async_fifo = false,
@@ -460,6 +464,7 @@ static const struct mtk_mmc_compatible mt8173_compat = {
460464

461465
static const struct mtk_mmc_compatible mt8183_compat = {
462466
.clk_div_bits = 12,
467+
.recheck_sdio_irq = false,
463468
.hs400_tune = false,
464469
.pad_tune_reg = MSDC_PAD_TUNE0,
465470
.async_fifo = true,
@@ -472,6 +477,7 @@ static const struct mtk_mmc_compatible mt8183_compat = {
472477

473478
static const struct mtk_mmc_compatible mt2701_compat = {
474479
.clk_div_bits = 12,
480+
.recheck_sdio_irq = false,
475481
.hs400_tune = false,
476482
.pad_tune_reg = MSDC_PAD_TUNE0,
477483
.async_fifo = true,
@@ -484,6 +490,7 @@ static const struct mtk_mmc_compatible mt2701_compat = {
484490

485491
static const struct mtk_mmc_compatible mt2712_compat = {
486492
.clk_div_bits = 12,
493+
.recheck_sdio_irq = false,
487494
.hs400_tune = false,
488495
.pad_tune_reg = MSDC_PAD_TUNE0,
489496
.async_fifo = true,
@@ -496,6 +503,7 @@ static const struct mtk_mmc_compatible mt2712_compat = {
496503

497504
static const struct mtk_mmc_compatible mt7622_compat = {
498505
.clk_div_bits = 12,
506+
.recheck_sdio_irq = false,
499507
.hs400_tune = false,
500508
.pad_tune_reg = MSDC_PAD_TUNE0,
501509
.async_fifo = true,
@@ -508,6 +516,7 @@ static const struct mtk_mmc_compatible mt7622_compat = {
508516

509517
static const struct mtk_mmc_compatible mt8516_compat = {
510518
.clk_div_bits = 12,
519+
.recheck_sdio_irq = false,
511520
.hs400_tune = false,
512521
.pad_tune_reg = MSDC_PAD_TUNE0,
513522
.async_fifo = true,
@@ -518,6 +527,7 @@ static const struct mtk_mmc_compatible mt8516_compat = {
518527

519528
static const struct mtk_mmc_compatible mt7620_compat = {
520529
.clk_div_bits = 8,
530+
.recheck_sdio_irq = false,
521531
.hs400_tune = false,
522532
.pad_tune_reg = MSDC_PAD_TUNE,
523533
.async_fifo = false,
@@ -591,6 +601,7 @@ static void msdc_reset_hw(struct msdc_host *host)
591601

592602
static void msdc_cmd_next(struct msdc_host *host,
593603
struct mmc_request *mrq, struct mmc_command *cmd);
604+
static void __msdc_enable_sdio_irq(struct msdc_host *host, int enb);
594605

595606
static const u32 cmd_ints_mask = MSDC_INTEN_CMDRDY | MSDC_INTEN_RSPCRCERR |
596607
MSDC_INTEN_CMDTMO | MSDC_INTEN_ACMDRDY |
@@ -1007,6 +1018,32 @@ static int msdc_auto_cmd_done(struct msdc_host *host, int events,
10071018
return cmd->error;
10081019
}
10091020

1021+
/**
1022+
* msdc_recheck_sdio_irq - recheck whether the SDIO irq is lost
1023+
*
1024+
* Host controller may lost interrupt in some special case.
1025+
* Add SDIO irq recheck mechanism to make sure all interrupts
1026+
* can be processed immediately
1027+
*
1028+
*/
1029+
static void msdc_recheck_sdio_irq(struct msdc_host *host)
1030+
{
1031+
u32 reg_int, reg_inten, reg_ps;
1032+
1033+
if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
1034+
reg_inten = readl(host->base + MSDC_INTEN);
1035+
if (reg_inten & MSDC_INTEN_SDIOIRQ) {
1036+
reg_int = readl(host->base + MSDC_INT);
1037+
reg_ps = readl(host->base + MSDC_PS);
1038+
if (!(reg_int & MSDC_INT_SDIOIRQ ||
1039+
reg_ps & MSDC_PS_DATA1)) {
1040+
__msdc_enable_sdio_irq(host, 0);
1041+
sdio_signal_irq(host->mmc);
1042+
}
1043+
}
1044+
}
1045+
}
1046+
10101047
static void msdc_track_cmd_data(struct msdc_host *host,
10111048
struct mmc_command *cmd, struct mmc_data *data)
10121049
{
@@ -1035,6 +1072,8 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
10351072
if (host->error)
10361073
msdc_reset_hw(host);
10371074
mmc_request_done(host->mmc, mrq);
1075+
if (host->dev_comp->recheck_sdio_irq)
1076+
msdc_recheck_sdio_irq(host);
10381077
}
10391078

10401079
/* returns true if command is fully handled; returns false otherwise */
@@ -1393,6 +1432,8 @@ static void __msdc_enable_sdio_irq(struct msdc_host *host, int enb)
13931432
if (enb) {
13941433
sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ);
13951434
sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
1435+
if (host->dev_comp->recheck_sdio_irq)
1436+
msdc_recheck_sdio_irq(host);
13961437
} else {
13971438
sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ);
13981439
sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);

0 commit comments

Comments
 (0)