diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index 6baa4577834960..a0824eccf0444b 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -405,9 +405,14 @@ Params: non-lite SKU of CM4). (default "on") - sd_cqe Set to "off" to disable Command Queueing if you - have an incompatible Class A2 SD card - (Pi 5 only, default "on") + sd_cqe Modify Command Queuing behaviour on the main SD + interface. Legal values are: + 0: disable CQ + 1: allow CQ for known-good SD A2 cards, and all + eMMC cards + 2: allow CQ for all SD A2 cards that aren't + known-bad, and all eMMC cards. + (2712 only, default "1") sd_overclock Clock (in MHz) to use when the MMC framework requests 50MHz diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi index adff5ae55b1f46..82d97d4af84bfe 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi @@ -586,7 +586,7 @@ clocks = <&clk_emmc2>; sdhci-caps-mask = <0x0000C000 0x0>; sdhci-caps = <0x0 0x0>; - supports-cqe; + supports-cqe = <1>; mmc-ddr-3_3v; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts index 83b88b0107f3c5..b6cb76ada0a2d2 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts @@ -322,7 +322,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; sd-uhs-sdr50; sd-uhs-ddr50; sd-uhs-sdr104; - supports-cqe; + supports-cqe = <1>; cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>; //no-1-8-v; status = "okay"; @@ -703,7 +703,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; / { __overrides__ { - sd_cqe = <&sdio1>, "supports-cqe?"; + sd_cqe = <&sdio1>, "supports-cqe:0"; }; }; diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi index 79666d85c31a24..129d7be38eb930 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi @@ -296,7 +296,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; mmc-hs400-1_8v; mmc-hs400-enhanced-strobe; broken-cd; - supports-cqe; + supports-cqe = <1>; status = "okay"; }; @@ -710,5 +710,6 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; <&ant2>, "output-low?=on"; noanthogs = <&ant1>,"status=disabled", <&ant2>, "status=disabled"; + sd_cqe = <&sdio1>, "supports-cqe:0"; }; }; diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index 0efdd58841f75f..273bdb5b49b8f3 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h @@ -93,6 +93,7 @@ struct mmc_fixup { #define CID_MANFID_KINGSTON 0x70 #define CID_MANFID_HYNIX 0x90 #define CID_MANFID_KINGSTON_SD 0x9F +#define CID_MANFID_LONGSYS_SD 0xAD #define CID_MANFID_NUMONYX 0xFE #define END_FIXUP { NULL } @@ -295,4 +296,9 @@ static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY; } +static inline int mmc_card_working_sd_cq(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_WORKING_SD_CQ; +} + #endif diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 48bda70145ee68..018b77ade4c690 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -272,7 +272,7 @@ EXPORT_SYMBOL(mmc_of_parse_clk_phase); int mmc_of_parse(struct mmc_host *host) { struct device *dev = host->parent; - u32 bus_width, drv_type, cd_debounce_delay_ms; + u32 bus_width, drv_type, cd_debounce_delay_ms, cq_allow; int ret; if (!dev || !dev_fwnode(dev)) @@ -407,6 +407,15 @@ int mmc_of_parse(struct mmc_host *host) host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | MMC_CAP2_HS400_ES); + cq_allow = 0; + /* + * Downstream property - if a u32 and 2 instead of a bool, + * trust most A2 SD cards claiming CQ support. + */ + device_property_read_u32(dev, "supports-cqe", &cq_allow); + if (cq_allow == 2) + host->caps2 |= MMC_CAP2_SD_CQE_PERMISSIVE; + /* Must be after "non-removable" check */ if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) { if (host->caps & MMC_CAP_NONREMOVABLE) diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index 0cbcc8bda05f37..9f8f5e121bc3fc 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -66,6 +66,12 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = { 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + /* SD A2 allow-list - only trust CQ on these cards */ + /* Raspberry Pi A2 cards */ + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_LONGSYS_SD, 0x4c53, CID_YEAR_ANY, CID_MONTH_ANY, + cid_rev(1, 0, 0, 0), -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_WORKING_SD_CQ, EXT_CSD_REV_ANY), + END_FIXUP }; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index cd0cef8aebe03d..ea42fa2ef4a6e8 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1501,6 +1501,10 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, goto free_card; } + /* Disallow command queueing on unvetted cards unless overridden */ + if (!(host->caps2 & MMC_CAP2_SD_CQE_PERMISSIVE) && !mmc_card_working_sd_cq(card)) + card->ext_csd.cmdq_support = false; + /* Enable command queueing if supported */ if (card->ext_csd.cmdq_support && host->caps2 & MMC_CAP2_CQE) { /* diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 9743d6cf921b85..1f267c9336d467 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -571,7 +571,7 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host; const struct of_device_id *match; struct sdhci_brcmstb_priv *priv; - u32 actual_clock_mhz; + u32 actual_clock_mhz, cqe; struct sdhci_host *host; struct resource *iomem; bool no_pinctrl = false; @@ -600,7 +600,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) pltfm_host->clk = clk; priv = sdhci_pltfm_priv(pltfm_host); - if (device_property_read_bool(&pdev->dev, "supports-cqe")) { + cqe = 0; + device_property_read_u32(&pdev->dev, "supports-cqe", &cqe); + if (cqe > 0) { priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_CQE; match_priv->ops->irq = sdhci_brcmstb_cqhci_irq; } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 92255a1dc0c6d3..6289155f806f15 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -295,6 +295,7 @@ struct mmc_card { #define MMC_QUIRK_BROKEN_SD_CACHE (1<<15) /* Disable broken SD cache support */ #define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */ #define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */ +#define MMC_QUIRK_WORKING_SD_CQ (1<<30) /* SD card has known-good CQ implementation */ #define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */ bool written_flag; /* Indicates eMMC has been written since power on */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 8fc2b328ec4d19..b89232b091b63a 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -404,6 +404,7 @@ struct mmc_host { #define MMC_CAP2_CRYPTO 0 #endif #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */ +#define MMC_CAP2_SD_CQE_PERMISSIVE (1 << 31) /* Ignore allow-list for CQ capable SD card detection */ int fixed_drv_type; /* fixed driver type for non-removable media */