This patch add a quirk: DW_MCI_QUIRK_SDIO_INT_24BIT. The bit of sdio interrupt is 16 in designware implementation, but is 24 in RK3288. To support RK3288 mmc controller, we need add a quirk for it. Signed-off-by: Addy Ke <addy.ke@xxxxxxxxxxxxxx> --- drivers/mmc/host/dw_mmc.c | 32 +++++++++++++++++++++++++++----- drivers/mmc/host/dw_mmc.h | 1 + include/linux/mmc/dw_mmc.h | 2 ++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 69f0cc6..db29621 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -778,6 +778,12 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) u32 div; u32 clk_en_a; u32 sdmmc_cmd_bits = SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT; + u32 sdio_int_bit; + + if (host->quirks & DW_MCI_QUIRK_SDIO_INT_24BIT) + sdio_int_bit = SDMMC_INT_SDIO_24BIT(slot->id); + else + sdio_int_bit = SDMMC_INT_SDIO(slot->id); /* We must continue to set bit 28 in CMD until the change is complete */ if (host->state == STATE_WAITING_CMD11_DONE) @@ -819,7 +825,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) /* enable clock; only low power if no SDIO */ clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; - if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) + if (!(mci_readl(host, INTMASK) & sdio_int_bit)) clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; mci_writel(host, CLKENA, clk_en_a); @@ -1167,6 +1173,12 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) struct dw_mci_slot *slot = mmc_priv(mmc); struct dw_mci *host = slot->host; u32 int_mask; + u32 sdio_int_bit; + + if (host->quirks & DW_MCI_QUIRK_SDIO_INT_24BIT) + sdio_int_bit = SDMMC_INT_SDIO_24BIT(slot->id); + else + sdio_int_bit = SDMMC_INT_SDIO(slot->id); /* Enable/disable Slot Specific SDIO interrupt */ int_mask = mci_readl(host, INTMASK); @@ -1180,10 +1192,10 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) dw_mci_disable_low_power(slot); mci_writel(host, INTMASK, - (int_mask | SDMMC_INT_SDIO(slot->id))); + (int_mask | sdio_int_bit)); } else { mci_writel(host, INTMASK, - (int_mask & ~SDMMC_INT_SDIO(slot->id))); + (int_mask & ~sdio_int_bit)); } } @@ -2035,8 +2047,15 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) /* Handle SDIO Interrupts */ for (i = 0; i < host->num_slots; i++) { struct dw_mci_slot *slot = host->slot[i]; - if (pending & SDMMC_INT_SDIO(i)) { - mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i)); + u32 sdio_int_bit; + + if (host->quirks & DW_MCI_QUIRK_SDIO_INT_24BIT) + sdio_int_bit = SDMMC_INT_SDIO_24BIT(i); + else + sdio_int_bit = SDMMC_INT_SDIO(i); + + if (pending & sdio_int_bit) { + mci_writel(host, RINTSTS, sdio_int_bit); mmc_signal_sdio_irq(slot->mmc); } } @@ -2452,6 +2471,9 @@ static struct dw_mci_of_quirks { }, { .quirk = "disable-wp", .id = DW_MCI_QUIRK_NO_WRITE_PROTECT, + }, { + .quirk = "sdio-int-24bit", + .id = DW_MCI_QUIRK_SDIO_INT_24BIT, }, }; diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 01b99e8..6a48015 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -92,6 +92,7 @@ #define SDMMC_CTYPE_4BIT BIT(0) #define SDMMC_CTYPE_1BIT 0 /* Interrupt status & mask register defines */ +#define SDMMC_INT_SDIO_24BIT(n) BIT(24 + (n)) #define SDMMC_INT_SDIO(n) BIT(16 + (n)) #define SDMMC_INT_EBE BIT(15) #define SDMMC_INT_ACD BIT(14) diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 0013669..6d4669e 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -217,6 +217,8 @@ struct dw_mci_dma_ops { #define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3) /* No write protect */ #define DW_MCI_QUIRK_NO_WRITE_PROTECT BIT(4) +/* In RK3288, the bit of sdio interrupt is 24 */ +#define DW_MCI_QUIRK_SDIO_INT_24BIT BIT(5) /* Slot level quirks */ /* This slot has no write protect */ -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html