From 86bbab3a0bc6bd767a5635e8b590d6b06ed03f52 Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 8 Nov 2023 11:52:16 +0000 Subject: [PATCH 1/4] drivers: mmc: sdhci: add SPURIOUS_INT_RESP quirk Certain controllers (dwc-mshc) generate timeout conditions separately to command-completion conditions, where the end result is interrupts are separated in time depending on the current SDCLK frequency. This causes spurious interrupts if SDCLK is slow compared to the CPU's ability to process and return from interrupt. This occurs during card probe with an empty slot where all commands that would generate a response time out. Add a quirk to squelch command response interrupts when a command timeout interrupt is received. Signed-off-by: Jonathan Bell --- drivers/mmc/host/sdhci.c | 11 +++++++++++ drivers/mmc/host/sdhci.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ac0e46bcf1a70e..561a4dbd50ce58 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1728,6 +1728,12 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) if (host->use_external_dma) sdhci_external_dma_pre_transfer(host, cmd); + if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_INT_RESP) { + host->ier |= SDHCI_INT_RESPONSE; + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + } + sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); return true; @@ -3330,6 +3336,11 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) if (intmask & SDHCI_INT_TIMEOUT) { host->cmd->error = -ETIMEDOUT; sdhci_err_stats_inc(host, CMD_TIMEOUT); + if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_INT_RESP) { + host->ier &= ~SDHCI_INT_RESPONSE; + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + } } else { host->cmd->error = -EILSEQ; if (!mmc_op_tuning(host->cmd->opcode)) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index bc5ce36fb83a66..ff6113c963d2fb 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -486,6 +486,9 @@ struct sdhci_host { #define SDHCI_QUIRK2_NO_SDR50 (1<<20) #define SDHCI_QUIRK2_NO_SDR104 (1<<21) +/* Command timeouts may generate a trailing INT_RESPONSE later */ +#define SDHCI_QUIRK2_SPURIOUS_INT_RESP (1<<31) + int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ phys_addr_t mapbase; /* physical address base */ From 7fe0536241bcb66c1667bddabaf6f0ffa0789336 Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 8 Nov 2023 16:10:13 +0000 Subject: [PATCH 2/4] dt-bindings: mmc: sdhci-of-dwcmhsc: Add Raspberry Pi RP1 support The DWC MSHC controller on RP1 needs differentiating from the generic version. Signed-off-by: Jonathan Bell --- .../devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml index 71f8e726d641ca..c1b8630403142a 100644 --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml @@ -16,6 +16,7 @@ allOf: properties: compatible: enum: + - raspberrypi,rp1-dwcmshc - rockchip,rk3568-dwcmshc - rockchip,rk3588-dwcmshc - snps,dwcmshc-sdhci @@ -34,6 +35,8 @@ properties: - description: axi clock for rockchip specified - description: block clock for rockchip specified - description: timer clock for rockchip specified + - description: timeout clock for rp1 specified + - description: sdio clock generator for rp1 specified clock-names: @@ -44,6 +47,8 @@ properties: - const: axi - const: block - const: timer + - const: timeout + - const: sdio rockchip,txclk-tapnum: description: Specify the number of delay for tx sampling. From 694da989dc801054d4b7526efe25f88dc7d191c5 Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 8 Nov 2023 16:12:59 +0000 Subject: [PATCH 3/4] drivers: mmc: sdhci-of-dwcmshc: add RP1 dt ID and quirks Differentiate the RP1 variant of the Designware MSHC controller(s). Signed-off-by: Jonathan Bell --- drivers/mmc/host/sdhci-of-dwcmshc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index cdc336c3e71cc2..0918399bf35441 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -373,6 +373,15 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_bf3_pdata = { }; #endif +static const struct sdhci_pltfm_data sdhci_dwcmshc_rp1_pdata = { + .ops = &sdhci_dwcmshc_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | + SDHCI_QUIRK_BROKEN_CARD_DETECTION, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_BROKEN_HS200 | + SDHCI_QUIRK2_SPURIOUS_INT_RESP, +}; + static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = { .ops = &sdhci_dwcmshc_rk35xx_ops, .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | @@ -440,6 +449,10 @@ static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv } static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { + { + .compatible = "raspberrypi,rp1-dwcmshc", + .data = &sdhci_dwcmshc_rp1_pdata, + }, { .compatible = "rockchip,rk3588-dwcmshc", .data = &sdhci_dwcmshc_rk35xx_pdata, From d636935cf6e590f6c25eeaa8100782cf7927aa5f Mon Sep 17 00:00:00 2001 From: Jonathan Bell Date: Wed, 8 Nov 2023 16:14:25 +0000 Subject: [PATCH 4/4] arm: dts: change RP1 SDHCI controller compatible string Also add a sdio-pi5 overlay which enables mmc0 on GPIOs 22-27, as was possible with earlier models of Pi. Signed-off-by: Jonathan Bell --- arch/arm/boot/dts/overlays/Makefile | 1 + arch/arm/boot/dts/overlays/README | 7 ++++++ arch/arm/boot/dts/overlays/overlay_map.dts | 4 ++++ .../boot/dts/overlays/sdio-pi5-overlay.dts | 24 +++++++++++++++++++ arch/arm/boot/dts/rp1.dtsi | 4 ++-- 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 arch/arm/boot/dts/overlays/sdio-pi5-overlay.dts diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile index 5b1380b55343fc..faebe83cf76da2 100644 --- a/arch/arm/boot/dts/overlays/Makefile +++ b/arch/arm/boot/dts/overlays/Makefile @@ -226,6 +226,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ sc16is752-spi1.dtbo \ sdhost.dtbo \ sdio.dtbo \ + sdio-pi5.dtbo \ seeed-can-fd-hat-v1.dtbo \ seeed-can-fd-hat-v2.dtbo \ sh1106-spi.dtbo \ diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index 1f3379caf79582..4d6fe35f5926fb 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -3936,6 +3936,13 @@ Info: This overlay is now deprecated. Use Load: +Name: sdio-pi5 +Info: Selects the rp1_mmc0 interface and enables it on GPIOs 22-27. + Pi 5 only. +Load: dtoverlay=sdio-pi5 +Params: + + Name: sdtweak Info: This overlay is now deprecated. Use the sd_* dtparams in the base DTB, e.g. "dtoverlay=sdtweak,poll_once" becomes diff --git a/arch/arm/boot/dts/overlays/overlay_map.dts b/arch/arm/boot/dts/overlays/overlay_map.dts index 5c9dc160c10c2c..4aa6004044144b 100644 --- a/arch/arm/boot/dts/overlays/overlay_map.dts +++ b/arch/arm/boot/dts/overlays/overlay_map.dts @@ -260,6 +260,10 @@ deprecated = "use sdio,bus_width=1,gpios_22_25"; }; + sdio-pi5 { + bcm2712; + }; + sdtweak { deprecated = "use 'dtparam=sd_poll_once' etc."; }; diff --git a/arch/arm/boot/dts/overlays/sdio-pi5-overlay.dts b/arch/arm/boot/dts/overlays/sdio-pi5-overlay.dts new file mode 100644 index 00000000000000..4e42cb5c856ebd --- /dev/null +++ b/arch/arm/boot/dts/overlays/sdio-pi5-overlay.dts @@ -0,0 +1,24 @@ +/dts-v1/; +/plugin/; + +/* SDIO/SD/MMC on RP1 bank 0 */ + +/{ + compatible = "brcm,bcm2712"; + + fragment@0 { + target = <&rp1_mmc0>; + frag0: __overlay__ { + status = "okay"; + pinctrl-0 = <&rp1_sdio0_22_27>; + pinctrl-names = "default"; + }; + }; + + fragment@1 { + target = <&rp1_sdio_clk0>; + frag1: __overlay__ { + status = "okay"; + }; + }; +}; diff --git a/arch/arm/boot/dts/rp1.dtsi b/arch/arm/boot/dts/rp1.dtsi index 08b54149df0884..7d403d91a02613 100644 --- a/arch/arm/boot/dts/rp1.dtsi +++ b/arch/arm/boot/dts/rp1.dtsi @@ -962,7 +962,7 @@ rp1_mmc0: mmc@180000 { reg = <0xc0 0x40180000 0x0 0x100>; - compatible = "snps,dwcmshc-sdhci"; + compatible = "raspberrypi,rp1-dwcmshc"; interrupts = ; clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core &rp1_clocks RP1_CLK_SDIO_TIMER @@ -978,7 +978,7 @@ rp1_mmc1: mmc@184000 { reg = <0xc0 0x40184000 0x0 0x100>; - compatible = "snps,dwcmshc-sdhci"; + compatible = "raspberrypi,rp1-dwcmshc"; interrupts = ; clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core &rp1_clocks RP1_CLK_SDIO_TIMER