openwrt/target/linux/bcm27xx/patches-6.1/950-1075-drivers-mmc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch
Marty Jones 2e715fb4fc bcm27xx: update 6.1 patches to latest version
Add support for BCM2712 (Raspberry Pi 5).
3bb5880ab3
Patches were generated from the diff between linux kernel branch linux-6.1.y
and rpi-6.1.y from raspberry pi kernel source:
- git format-patch linux-6.1.y...rpi-6.1.y

Build system: x86_64
Build-tested: bcm2708, bcm2709, bcm2710, bcm2711
Run-tested: bcm2710/RPi3B, bcm2711/RPi4B

Signed-off-by: Marty Jones <mj8263788@gmail.com>
[Remove applied and reverted patches, squash patches and config commits]
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2024-01-25 17:46:45 +01:00

63 lines
2.3 KiB
Diff

From 4d2261fe86ce08bbee3c000718000e9f86593d88 Mon Sep 17 00:00:00 2001
From: Jonathan Bell <jonathan@raspberrypi.com>
Date: Wed, 8 Nov 2023 11:52:16 +0000
Subject: [PATCH] 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 <jonathan@raspberrypi.com>
---
drivers/mmc/host/sdhci.c | 11 +++++++++++
drivers/mmc/host/sdhci.h | 3 +++
2 files changed, 14 insertions(+)
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1728,6 +1728,12 @@ static bool sdhci_send_command(struct sd
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_h
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))
--- 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 */