From: Diwakar Sharma <diwakar.sharma@xxxxxxxxxxxx> This patch adds a quirk to report "SDR50" mode on IMX side even if support of SDR104 was received from Marvell 8887 WiFi + Bluetooth chip side, as Marvell does not recommend to use SDIO at the speed of higher than 150MHz. Signed-off-by: Diwakar Sharma <diwakar.sharma@xxxxxxxxxxxx> Signed-off-by: Harish Jenny K N <harish_kandiga@xxxxxxxxxx> --- drivers/mmc/core/card.h | 5 +++++ drivers/mmc/core/quirks.h | 3 +++ drivers/mmc/core/sdio.c | 23 +++++++++++++++++++++++ include/linux/mmc/card.h | 2 ++ include/linux/mmc/sdio_ids.h | 1 + 5 files changed, 34 insertions(+) diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index 9c821ee..e6c7dad 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h @@ -221,4 +221,9 @@ static inline int mmc_card_broken_hpi(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BROKEN_HPI; } +static inline int mmc_card_broken_uhs(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_BROKEN_UHS; +} + #endif diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index 5153577..575b6f7 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -132,6 +132,9 @@ SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0, add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING), + SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887WLAN, + add_quirk, MMC_QUIRK_BROKEN_UHS), + END_FIXUP }; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index c599a62..9ed8b31 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -566,6 +566,9 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, int retries = 10; u32 rocr = 0; u32 ocr_card = ocr; + int cccr_vsn; + unsigned char data; + int uhs; WARN_ON(!host->claimed); @@ -740,6 +743,26 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, card->ocr = ocr_card; mmc_fixup_device(card, sdio_fixup_methods); + uhs = ocr & R4_18V_PRESENT; + err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CCCR, 0, &data); + if (err) + goto remove; + + cccr_vsn = data & 0x0f; + if (cccr_vsn >= SDIO_CCCR_REV_3_00 && uhs) { + if (mmc_host_uhs(card->host) && mmc_card_broken_uhs(card)) { + /* + * The MMC device reports a non-working + * maximum clock rate, workaround is to + * force the MMC host controller to report + * a lower clock rate than supported. + */ + card->sw_caps.sd3_bus_mode &= ~SD_MODE_UHS_DDR50; + card->sw_caps.sd3_bus_mode &= ~SD_MODE_UHS_SDR104; + card->sw_caps.sd3_bus_mode |= SD_MODE_UHS_SDR50; + } + } + if (card->type == MMC_TYPE_SD_COMBO) { err = mmc_sd_setup_card(host, card, oldcard != NULL); /* handle as SDIO-only card if memory init failed */ diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 279b390..05cdf0c 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -268,6 +268,8 @@ struct mmc_card { #define MMC_QUIRK_BROKEN_IRQ_POLLING (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */ #define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */ #define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */ +#define MMC_QUIRK_BROKEN_UHS (1<<14) /* Report a lower SDIO clock rate */ + /* for broken UHS */ bool reenable_cmdq; /* Re-enable Command Queue */ diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index cdd66a5..00e18e2 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -55,6 +55,7 @@ #define SDIO_DEVICE_ID_MARVELL_8688WLAN 0x9104 #define SDIO_DEVICE_ID_MARVELL_8688BT 0x9105 #define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128 +#define SDIO_DEVICE_ID_MARVELL_8887WLAN 0x9134 #define SDIO_VENDOR_ID_SIANO 0x039a #define SDIO_DEVICE_ID_SIANO_NOVA_B0 0x0201 -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html