128
128
#define MSDC_PS_CDSTS (0x1 << 1) /* R */
129
129
#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */
130
130
#define MSDC_PS_DAT (0xff << 16) /* R */
131
+ #define MSDC_PS_DATA1 (0x1 << 17) /* R */
131
132
#define MSDC_PS_CMD (0x1 << 24) /* R */
132
133
#define MSDC_PS_WP (0x1 << 31) /* R */
133
134
@@ -361,6 +362,7 @@ struct msdc_save_para {
361
362
362
363
struct mtk_mmc_compatible {
363
364
u8 clk_div_bits ;
365
+ bool recheck_sdio_irq ;
364
366
bool hs400_tune ; /* only used for MT8173 */
365
367
u32 pad_tune_reg ;
366
368
bool async_fifo ;
@@ -436,6 +438,7 @@ struct msdc_host {
436
438
437
439
static const struct mtk_mmc_compatible mt8135_compat = {
438
440
.clk_div_bits = 8 ,
441
+ .recheck_sdio_irq = false,
439
442
.hs400_tune = false,
440
443
.pad_tune_reg = MSDC_PAD_TUNE ,
441
444
.async_fifo = false,
@@ -448,6 +451,7 @@ static const struct mtk_mmc_compatible mt8135_compat = {
448
451
449
452
static const struct mtk_mmc_compatible mt8173_compat = {
450
453
.clk_div_bits = 8 ,
454
+ .recheck_sdio_irq = true,
451
455
.hs400_tune = true,
452
456
.pad_tune_reg = MSDC_PAD_TUNE ,
453
457
.async_fifo = false,
@@ -460,6 +464,7 @@ static const struct mtk_mmc_compatible mt8173_compat = {
460
464
461
465
static const struct mtk_mmc_compatible mt8183_compat = {
462
466
.clk_div_bits = 12 ,
467
+ .recheck_sdio_irq = false,
463
468
.hs400_tune = false,
464
469
.pad_tune_reg = MSDC_PAD_TUNE0 ,
465
470
.async_fifo = true,
@@ -472,6 +477,7 @@ static const struct mtk_mmc_compatible mt8183_compat = {
472
477
473
478
static const struct mtk_mmc_compatible mt2701_compat = {
474
479
.clk_div_bits = 12 ,
480
+ .recheck_sdio_irq = false,
475
481
.hs400_tune = false,
476
482
.pad_tune_reg = MSDC_PAD_TUNE0 ,
477
483
.async_fifo = true,
@@ -484,6 +490,7 @@ static const struct mtk_mmc_compatible mt2701_compat = {
484
490
485
491
static const struct mtk_mmc_compatible mt2712_compat = {
486
492
.clk_div_bits = 12 ,
493
+ .recheck_sdio_irq = false,
487
494
.hs400_tune = false,
488
495
.pad_tune_reg = MSDC_PAD_TUNE0 ,
489
496
.async_fifo = true,
@@ -496,6 +503,7 @@ static const struct mtk_mmc_compatible mt2712_compat = {
496
503
497
504
static const struct mtk_mmc_compatible mt7622_compat = {
498
505
.clk_div_bits = 12 ,
506
+ .recheck_sdio_irq = false,
499
507
.hs400_tune = false,
500
508
.pad_tune_reg = MSDC_PAD_TUNE0 ,
501
509
.async_fifo = true,
@@ -508,6 +516,7 @@ static const struct mtk_mmc_compatible mt7622_compat = {
508
516
509
517
static const struct mtk_mmc_compatible mt8516_compat = {
510
518
.clk_div_bits = 12 ,
519
+ .recheck_sdio_irq = false,
511
520
.hs400_tune = false,
512
521
.pad_tune_reg = MSDC_PAD_TUNE0 ,
513
522
.async_fifo = true,
@@ -518,6 +527,7 @@ static const struct mtk_mmc_compatible mt8516_compat = {
518
527
519
528
static const struct mtk_mmc_compatible mt7620_compat = {
520
529
.clk_div_bits = 8 ,
530
+ .recheck_sdio_irq = false,
521
531
.hs400_tune = false,
522
532
.pad_tune_reg = MSDC_PAD_TUNE ,
523
533
.async_fifo = false,
@@ -591,6 +601,7 @@ static void msdc_reset_hw(struct msdc_host *host)
591
601
592
602
static void msdc_cmd_next (struct msdc_host * host ,
593
603
struct mmc_request * mrq , struct mmc_command * cmd );
604
+ static void __msdc_enable_sdio_irq (struct msdc_host * host , int enb );
594
605
595
606
static const u32 cmd_ints_mask = MSDC_INTEN_CMDRDY | MSDC_INTEN_RSPCRCERR |
596
607
MSDC_INTEN_CMDTMO | MSDC_INTEN_ACMDRDY |
@@ -1007,6 +1018,32 @@ static int msdc_auto_cmd_done(struct msdc_host *host, int events,
1007
1018
return cmd -> error ;
1008
1019
}
1009
1020
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
+
1010
1047
static void msdc_track_cmd_data (struct msdc_host * host ,
1011
1048
struct mmc_command * cmd , struct mmc_data * data )
1012
1049
{
@@ -1035,6 +1072,8 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
1035
1072
if (host -> error )
1036
1073
msdc_reset_hw (host );
1037
1074
mmc_request_done (host -> mmc , mrq );
1075
+ if (host -> dev_comp -> recheck_sdio_irq )
1076
+ msdc_recheck_sdio_irq (host );
1038
1077
}
1039
1078
1040
1079
/* 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)
1393
1432
if (enb ) {
1394
1433
sdr_set_bits (host -> base + MSDC_INTEN , MSDC_INTEN_SDIOIRQ );
1395
1434
sdr_set_bits (host -> base + SDC_CFG , SDC_CFG_SDIOIDE );
1435
+ if (host -> dev_comp -> recheck_sdio_irq )
1436
+ msdc_recheck_sdio_irq (host );
1396
1437
} else {
1397
1438
sdr_clr_bits (host -> base + MSDC_INTEN , MSDC_INTEN_SDIOIRQ );
1398
1439
sdr_clr_bits (host -> base + SDC_CFG , SDC_CFG_SDIOIDE );
0 commit comments