summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml1
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc-controller.yaml13
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml2
-rw-r--r--Documentation/devicetree/bindings/mmc/mtk-sd.yaml1
-rw-r--r--Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml3
-rw-r--r--Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml1
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-am654.yaml3
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.yaml6
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/mmc/core/host.c2
-rw-r--r--drivers/mmc/core/sdio.c4
-rw-r--r--drivers/mmc/core/sdio_irq.c4
-rw-r--r--drivers/mmc/host/Kconfig1
-rw-r--r--drivers/mmc/host/au1xmmc.c3
-rw-r--r--drivers/mmc/host/jz4740_mmc.c4
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c84
-rw-r--r--drivers/mmc/host/meson-mx-sdhc-mmc.c4
-rw-r--r--drivers/mmc/host/mtk-sd.c109
-rw-r--r--drivers/mmc/host/rtsx_usb_sdmmc.c5
-rw-r--r--drivers/mmc/host/sdhci-msm.c1
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c23
-rw-r--r--drivers/mmc/host/sdhci-pci-o2micro.c7
-rw-r--r--drivers/mmc/host/sdhci-sprd.c6
-rw-r--r--drivers/mmc/host/sdhci.c84
-rw-r--r--drivers/mmc/host/sdhci.h2
-rw-r--r--drivers/mmc/host/sdhci_am654.c5
-rw-r--r--drivers/mmc/host/wmt-sdmmc.c5
-rw-r--r--include/linux/mmc/host.h2
28 files changed, 255 insertions, 136 deletions
diff --git a/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml b/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml
index 4207fed62dfe..8b1a0fdcb5e3 100644
--- a/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml
@@ -8,7 +8,6 @@ title: Cadence SD/SDIO/eMMC Host Controller (SD4HC)
maintainers:
- Masahiro Yamada <yamada.masahiro@socionext.com>
- - Piotr Sroka <piotrs@cadence.com>
allOf:
- $ref: mmc-controller.yaml
diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
index ff5ce89e5111..802e3ca8be4d 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
+++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
@@ -88,11 +88,18 @@ properties:
default: 1
max-frequency:
- description:
- Maximum operating frequency of the bus.
+ description: |
+ Maximum operating frequency of the bus:
+ - for eMMC, the maximum supported frequency is 200MHz,
+ - for SD/SDIO cards the SDR104 mode has a max supported
+ frequency of 208MHz,
+ - some mmc host controllers do support a max frequency upto
+ 384MHz.
+ So, lets keep the maximum supported value here.
+
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 400000
- maximum: 200000000
+ maximum: 384000000
disable-wp:
$ref: /schemas/types.yaml#/definitions/flag
diff --git a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml
index c45b91099325..c0662ce9946d 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml
+++ b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml
@@ -23,8 +23,6 @@ properties:
reg:
maxItems: 1
- spi-max-frequency: true
-
interrupts:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
index 083d1ec2f661..d8e1e2e9adf2 100644
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
@@ -20,6 +20,7 @@ properties:
- mediatek,mt2701-mmc
- mediatek,mt2712-mmc
- mediatek,mt6779-mmc
+ - mediatek,mt6795-mmc
- mediatek,mt7620-mmc
- mediatek,mt7622-mmc
- mediatek,mt8135-mmc
diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
index 14945ebc31d2..0424b06cb655 100644
--- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
+++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
@@ -89,6 +89,9 @@ properties:
- tx
- rx
+ iommus:
+ maxItems: 1
+
power-domains:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
index 8d888b435817..ccf0e3e93efa 100644
--- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
+++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
@@ -32,6 +32,7 @@ properties:
- rockchip,px30-dw-mshc
- rockchip,rk1808-dw-mshc
- rockchip,rk3036-dw-mshc
+ - rockchip,rk3128-dw-mshc
- rockchip,rk3228-dw-mshc
- rockchip,rk3308-dw-mshc
- rockchip,rk3328-dw-mshc
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
index 0ab07759b472..ea9121fb188d 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
@@ -51,6 +51,9 @@ properties:
sdhci-caps-mask: true
+ dma-coherent:
+ type: boolean
+
# PHY output tap delays:
# Used to delay the data valid window and align it to the sampling clock.
# Binding needs to be provided for each supported speed mode otherwise the
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
index fc0e81c2066c..a96f143479c7 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
@@ -38,9 +38,11 @@ properties:
- qcom,sc7180-sdhci
- qcom,sc7280-sdhci
- qcom,sdm630-sdhci
+ - qcom,sdm670-sdhci
- qcom,sdm845-sdhci
- qcom,sdx55-sdhci
- qcom,sdx65-sdhci
+ - qcom,sm6115-sdhci
- qcom,sm6125-sdhci
- qcom,sm6350-sdhci
- qcom,sm8150-sdhci
@@ -96,6 +98,10 @@ properties:
description:
Should specify pin control groups used for this controller.
+ pinctrl-1:
+ description:
+ Should specify sleep pin control groups used for this controller.
+
resets:
maxItems: 1
diff --git a/MAINTAINERS b/MAINTAINERS
index 8656ab794786..b2a88ff1596c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7536,7 +7536,7 @@ M: Adrian Hunter <adrian.hunter@intel.com>
M: Ritesh Harjani <riteshh@codeaurora.org>
M: Asutosh Das <asutoshd@codeaurora.org>
L: linux-mmc@vger.kernel.org
-S: Maintained
+S: Supported
F: drivers/mmc/host/cqhci*
EMULEX 10Gbps iSCSI - OneConnect DRIVER
@@ -18316,7 +18316,7 @@ F: drivers/mmc/host/sdhci-brcmstb*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
M: Adrian Hunter <adrian.hunter@intel.com>
L: linux-mmc@vger.kernel.org
-S: Maintained
+S: Supported
F: drivers/mmc/host/sdhci*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) MICROCHIP DRIVER
@@ -18339,7 +18339,7 @@ S: Maintained
F: drivers/mmc/host/sdhci-spear.c
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) TI OMAP DRIVER
-M: Kishon Vijay Abraham I <kishon@ti.com>
+M: Vignesh Raghavendra <vigneshr@ti.com>
L: linux-mmc@vger.kernel.org
S: Maintained
F: drivers/mmc/host/sdhci-omap.c
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 0fd91f749b3a..b89dca1f15e9 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -565,7 +565,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
- INIT_DELAYED_WORK(&host->sdio_irq_work, sdio_irq_work);
+ INIT_WORK(&host->sdio_irq_work, sdio_irq_work);
timer_setup(&host->retune_timer, mmc_retune_timer, 0);
/*
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 0b682a31cd3e..f64b9ac76a5c 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -1043,7 +1043,7 @@ static int mmc_sdio_suspend(struct mmc_host *host)
/* Prevent processing of SDIO IRQs in suspended state. */
mmc_card_set_suspended(host->card);
- cancel_delayed_work_sync(&host->sdio_irq_work);
+ cancel_work_sync(&host->sdio_irq_work);
mmc_claim_host(host);
@@ -1103,7 +1103,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD))
wake_up_process(host->sdio_irq_thread);
else if (host->caps & MMC_CAP_SDIO_IRQ)
- queue_delayed_work(system_wq, &host->sdio_irq_work, 0);
+ schedule_work(&host->sdio_irq_work);
}
out:
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 4b1f7c966ec8..2b24bdf38296 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -124,7 +124,7 @@ static void sdio_run_irqs(struct mmc_host *host)
void sdio_irq_work(struct work_struct *work)
{
struct mmc_host *host =
- container_of(work, struct mmc_host, sdio_irq_work.work);
+ container_of(work, struct mmc_host, sdio_irq_work);
sdio_run_irqs(host);
}
@@ -132,7 +132,7 @@ void sdio_irq_work(struct work_struct *work)
void sdio_signal_irq(struct mmc_host *host)
{
host->sdio_irq_pending = true;
- queue_delayed_work(system_wq, &host->sdio_irq_work, 0);
+ schedule_work(&host->sdio_irq_work);
}
EXPORT_SYMBOL_GPL(sdio_signal_irq);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index e63608834411..f324daadaf70 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -157,6 +157,7 @@ config MMC_SDHCI_OF_ARASAN
config MMC_SDHCI_OF_ASPEED
tristate "SDHCI OF support for the ASPEED SDHCI controller"
+ depends on ARCH_ASPEED || COMPILE_TEST
depends on MMC_SDHCI_PLTFM
depends on OF && OF_ADDRESS
select MMC_SDHCI_IO_ACCESSORS
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index a9a0837153d8..c88b039dc9fb 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -1097,8 +1097,9 @@ out5:
if (host->platdata && host->platdata->cd_setup &&
!(mmc->caps & MMC_CAP_NEEDS_POLL))
host->platdata->cd_setup(mmc, 0);
-out_clk:
+
clk_disable_unprepare(host->clk);
+out_clk:
clk_put(host->clk);
out_irq:
free_irq(host->irq, host);
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index b1d563b2ed1b..dc2db9c185ea 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -298,7 +298,7 @@ static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host,
{
struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data);
enum dma_data_direction dir = mmc_get_dma_dir(data);
- int sg_count;
+ unsigned int sg_count;
if (data->host_cookie == COOKIE_PREMAPPED)
return data->sg_count;
@@ -308,7 +308,7 @@ static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host,
data->sg_len,
dir);
- if (sg_count <= 0) {
+ if (!sg_count) {
dev_err(mmc_dev(host->mmc),
"Failed to map scatterlist for DMA operation\n");
return -EINVAL;
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index fc462995cf94..df05e60bed9a 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -41,14 +41,17 @@
#define CLK_V2_TX_DELAY_MASK GENMASK(19, 16)
#define CLK_V2_RX_DELAY_MASK GENMASK(23, 20)
#define CLK_V2_ALWAYS_ON BIT(24)
+#define CLK_V2_IRQ_SDIO_SLEEP BIT(25)
#define CLK_V3_TX_DELAY_MASK GENMASK(21, 16)
#define CLK_V3_RX_DELAY_MASK GENMASK(27, 22)
#define CLK_V3_ALWAYS_ON BIT(28)
+#define CLK_V3_IRQ_SDIO_SLEEP BIT(29)
#define CLK_TX_DELAY_MASK(h) (h->data->tx_delay_mask)
#define CLK_RX_DELAY_MASK(h) (h->data->rx_delay_mask)
#define CLK_ALWAYS_ON(h) (h->data->always_on)
+#define CLK_IRQ_SDIO_SLEEP(h) (h->data->irq_sdio_sleep)
#define SD_EMMC_DELAY 0x4
#define SD_EMMC_ADJUST 0x8
@@ -101,8 +104,7 @@
#define IRQ_RESP_STATUS BIT(14)
#define IRQ_SDIO BIT(15)
#define IRQ_EN_MASK \
- (IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN | IRQ_RESP_STATUS |\
- IRQ_SDIO)
+ (IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN)
#define SD_EMMC_CMD_CFG 0x50
#define SD_EMMC_CMD_ARG 0x54
@@ -136,6 +138,7 @@ struct meson_mmc_data {
unsigned int rx_delay_mask;
unsigned int always_on;
unsigned int adjust;
+ unsigned int irq_sdio_sleep;
};
struct sd_emmc_desc {
@@ -175,6 +178,7 @@ struct meson_host {
bool vqmmc_enabled;
bool needs_pre_post_req;
+ spinlock_t lock;
};
#define CMD_CFG_LENGTH_MASK GENMASK(8, 0)
@@ -431,6 +435,7 @@ static int meson_mmc_clk_init(struct meson_host *host)
clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180);
clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0);
clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, CLK_PHASE_0);
+ clk_reg |= CLK_IRQ_SDIO_SLEEP(host);
writel(clk_reg, host->regs + SD_EMMC_CLOCK);
/* get the mux parents */
@@ -929,33 +934,54 @@ static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
}
}
+static void __meson_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ struct meson_host *host = mmc_priv(mmc);
+ u32 reg_irqen = IRQ_EN_MASK;
+
+ if (enable)
+ reg_irqen |= IRQ_SDIO;
+ writel(reg_irqen, host->regs + SD_EMMC_IRQ_EN);
+}
+
static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
{
struct meson_host *host = dev_id;
struct mmc_command *cmd;
- struct mmc_data *data;
- u32 irq_en, status, raw_status;
+ u32 status, raw_status;
irqreturn_t ret = IRQ_NONE;
- irq_en = readl(host->regs + SD_EMMC_IRQ_EN);
raw_status = readl(host->regs + SD_EMMC_STATUS);
- status = raw_status & irq_en;
+ status = raw_status & (IRQ_EN_MASK | IRQ_SDIO);
if (!status) {
dev_dbg(host->dev,
- "Unexpected IRQ! irq_en 0x%08x - status 0x%08x\n",
- irq_en, raw_status);
+ "Unexpected IRQ! irq_en 0x%08lx - status 0x%08x\n",
+ IRQ_EN_MASK | IRQ_SDIO, raw_status);
return IRQ_NONE;
}
- if (WARN_ON(!host) || WARN_ON(!host->cmd))
+ if (WARN_ON(!host))
return IRQ_NONE;
/* ack all raised interrupts */
writel(status, host->regs + SD_EMMC_STATUS);
cmd = host->cmd;
- data = cmd->data;
+
+ if (status & IRQ_SDIO) {
+ spin_lock(&host->lock);
+ __meson_mmc_enable_sdio_irq(host->mmc, 0);
+ sdio_signal_irq(host->mmc);
+ spin_unlock(&host->lock);
+ status &= ~IRQ_SDIO;
+ if (!status)
+ return IRQ_HANDLED;
+ }
+
+ if (WARN_ON(!cmd))
+ return IRQ_NONE;
+
cmd->error = 0;
if (status & IRQ_CRC_ERR) {
dev_dbg(host->dev, "CRC Error - status 0x%08x\n", status);
@@ -973,12 +999,9 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
meson_mmc_read_resp(host->mmc, cmd);
- if (status & IRQ_SDIO) {
- dev_dbg(host->dev, "IRQ: SDIO TODO.\n");
- ret = IRQ_HANDLED;
- }
-
if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) {
+ struct mmc_data *data = cmd->data;
+
if (data && !cmd->error)
data->bytes_xfered = data->blksz * data->blocks;
if (meson_mmc_bounce_buf_read(data) ||
@@ -1121,6 +1144,21 @@ static int meson_mmc_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
return -EINVAL;
}
+static void meson_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ struct meson_host *host = mmc_priv(mmc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+ __meson_mmc_enable_sdio_irq(mmc, enable);
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void meson_mmc_ack_sdio_irq(struct mmc_host *mmc)
+{
+ meson_mmc_enable_sdio_irq(mmc, 1);
+}
+
static const struct mmc_host_ops meson_mmc_ops = {
.request = meson_mmc_request,
.set_ios = meson_mmc_set_ios,
@@ -1130,6 +1168,8 @@ static const struct mmc_host_ops meson_mmc_ops = {
.execute_tuning = meson_mmc_resampling_tuning,
.card_busy = meson_mmc_card_busy,
.start_signal_voltage_switch = meson_mmc_voltage_switch,
+ .enable_sdio_irq = meson_mmc_enable_sdio_irq,
+ .ack_sdio_irq = meson_mmc_ack_sdio_irq,
};
static int meson_mmc_probe(struct platform_device *pdev)
@@ -1226,10 +1266,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
/* clear, ack and enable interrupts */
writel(0, host->regs + SD_EMMC_IRQ_EN);
- writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN,
- host->regs + SD_EMMC_STATUS);
- writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN,
- host->regs + SD_EMMC_IRQ_EN);
+ writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS);
+ writel(IRQ_EN_MASK, host->regs + SD_EMMC_IRQ_EN);
ret = request_threaded_irq(host->irq, meson_mmc_irq,
meson_mmc_irq_thread, IRQF_ONESHOT,
@@ -1237,7 +1275,13 @@ static int meson_mmc_probe(struct platform_device *pdev)
if (ret)
goto err_init_clk;
+ spin_lock_init(&host->lock);
+
mmc->caps |= MMC_CAP_CMD23;
+
+ if (mmc->caps & MMC_CAP_SDIO_IRQ)
+ mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
+
if (host->dram_access_quirk) {
/* Limit segments to 1 due to low available sram memory */
mmc->max_segs = 1;
@@ -1328,6 +1372,7 @@ static const struct meson_mmc_data meson_gx_data = {
.rx_delay_mask = CLK_V2_RX_DELAY_MASK,
.always_on = CLK_V2_ALWAYS_ON,
.adjust = SD_EMMC_ADJUST,
+ .irq_sdio_sleep = CLK_V2_IRQ_SDIO_SLEEP,
};
static const struct meson_mmc_data meson_axg_data = {
@@ -1335,6 +1380,7 @@ static const struct meson_mmc_data meson_axg_data = {
.rx_delay_mask = CLK_V3_RX_DELAY_MASK,
.always_on = CLK_V3_ALWAYS_ON,
.adjust = SD_EMMC_V3_ADJUST,
+ .irq_sdio_sleep = CLK_V3_IRQ_SDIO_SLEEP,
};
static const struct of_device_id meson_mmc_of_match[] = {
diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c
index e92e63cb5641..da85c2f2acb8 100644
--- a/drivers/mmc/host/meson-mx-sdhc-mmc.c
+++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c
@@ -381,14 +381,14 @@ static void meson_mx_sdhc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static int meson_mx_sdhc_map_dma(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct mmc_data *data = mrq->data;
- int dma_len;
+ unsigned int dma_len;
if (!data)
return 0;
dma_len = dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len,
mmc_get_dma_dir(data));
- if (dma_len <= 0) {
+ if (!dma_len) {
dev_err(mmc_dev(mmc), "dma_map_sg failed\n");
return -ENOMEM;
}
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 69d78604d1fc..df941438aef5 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -474,33 +474,20 @@ struct msdc_host {
struct cqhci_host *cq_host;
};
-static const struct mtk_mmc_compatible mt8135_compat = {
- .clk_div_bits = 8,
+static const struct mtk_mmc_compatible mt2701_compat = {
+ .clk_div_bits = 12,
.recheck_sdio_irq = true,
.hs400_tune = false,
- .pad_tune_reg = MSDC_PAD_TUNE,
- .async_fifo = false,
- .data_tune = false,
- .busy_check = false,
- .stop_clk_fix = false,
- .enhance_rx = false,
- .support_64g = false,
-};
-
-static const struct mtk_mmc_compatible mt8173_compat = {
- .clk_div_bits = 8,
- .recheck_sdio_irq = true,
- .hs400_tune = true,
- .pad_tune_reg = MSDC_PAD_TUNE,
- .async_fifo = false,
- .data_tune = false,
+ .pad_tune_reg = MSDC_PAD_TUNE0,
+ .async_fifo = true,
+ .data_tune = true,
.busy_check = false,
.stop_clk_fix = false,
.enhance_rx = false,
.support_64g = false,
};
-static const struct mtk_mmc_compatible mt8183_compat = {
+static const struct mtk_mmc_compatible mt2712_compat = {
.clk_div_bits = 12,
.recheck_sdio_irq = false,
.hs400_tune = false,
@@ -513,30 +500,43 @@ static const struct mtk_mmc_compatible mt8183_compat = {
.support_64g = true,
};
-static const struct mtk_mmc_compatible mt2701_compat = {
+static const struct mtk_mmc_compatible mt6779_compat = {
.clk_div_bits = 12,
- .recheck_sdio_irq = true,
+ .recheck_sdio_irq = false,
.hs400_tune = false,
.pad_tune_reg = MSDC_PAD_TUNE0,
.async_fifo = true,
.data_tune = true,
+ .busy_check = true,
+ .stop_clk_fix = true,
+ .enhance_rx = true,
+ .support_64g = true,
+};
+
+static const struct mtk_mmc_compatible mt6795_compat = {
+ .clk_div_bits = 8,
+ .recheck_sdio_irq = false,
+ .hs400_tune = true,
+ .pad_tune_reg = MSDC_PAD_TUNE,
+ .async_fifo = false,
+ .data_tune = false,
.busy_check = false,
.stop_clk_fix = false,
.enhance_rx = false,
.support_64g = false,
};
-static const struct mtk_mmc_compatible mt2712_compat = {
- .clk_div_bits = 12,
- .recheck_sdio_irq = false,
+static const struct mtk_mmc_compatible mt7620_compat = {
+ .clk_div_bits = 8,
+ .recheck_sdio_irq = true,
.hs400_tune = false,
- .pad_tune_reg = MSDC_PAD_TUNE0,
- .async_fifo = true,
- .data_tune = true,
- .busy_check = true,
- .stop_clk_fix = true,
- .enhance_rx = true,
- .support_64g = true,
+ .pad_tune_reg = MSDC_PAD_TUNE,
+ .async_fifo = false,
+ .data_tune = false,
+ .busy_check = false,
+ .stop_clk_fix = false,
+ .enhance_rx = false,
+ .use_internal_cd = true,
};
static const struct mtk_mmc_compatible mt7622_compat = {
@@ -552,31 +552,33 @@ static const struct mtk_mmc_compatible mt7622_compat = {
.support_64g = false,
};
-static const struct mtk_mmc_compatible mt8516_compat = {
- .clk_div_bits = 12,
+static const struct mtk_mmc_compatible mt8135_compat = {
+ .clk_div_bits = 8,
.recheck_sdio_irq = true,
.hs400_tune = false,
- .pad_tune_reg = MSDC_PAD_TUNE0,
- .async_fifo = true,
- .data_tune = true,
- .busy_check = true,
- .stop_clk_fix = true,
+ .pad_tune_reg = MSDC_PAD_TUNE,
+ .async_fifo = false,
+ .data_tune = false,
+ .busy_check = false,
+ .stop_clk_fix = false,
+ .enhance_rx = false,
+ .support_64g = false,
};
-static const struct mtk_mmc_compatible mt7620_compat = {
+static const struct mtk_mmc_compatible mt8173_compat = {
.clk_div_bits = 8,
.recheck_sdio_irq = true,
- .hs400_tune = false,
+ .hs400_tune = true,
.pad_tune_reg = MSDC_PAD_TUNE,
.async_fifo = false,
.data_tune = false,
.busy_check = false,
.stop_clk_fix = false,
.enhance_rx = false,
- .use_internal_cd = true,
+ .support_64g = false,
};
-static const struct mtk_mmc_compatible mt6779_compat = {
+static const struct mtk_mmc_compatible mt8183_compat = {
.clk_div_bits = 12,
.recheck_sdio_irq = false,
.hs400_tune = false,
@@ -589,16 +591,29 @@ static const struct mtk_mmc_compatible mt6779_compat = {
.support_64g = true,
};
+static const struct mtk_mmc_compatible mt8516_compat = {
+ .clk_div_bits = 12,
+ .recheck_sdio_irq = true,
+ .hs400_tune = false,
+ .pad_tune_reg = MSDC_PAD_TUNE0,
+ .async_fifo = true,
+ .data_tune = true,
+ .busy_check = true,
+ .stop_clk_fix = true,
+};
+
static const struct of_device_id msdc_of_ids[] = {
- { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat},
- { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat},
- { .compatible = "mediatek,mt8183-mmc", .data = &mt8183_compat},
{ .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat},
{ .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat},
+ { .compatible = "mediatek,mt6779-mmc", .data = &mt6779_compat},
+ { .compatible = "mediatek,mt6795-mmc", .data = &mt6795_compat},
+ { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat},
{ .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat},
+ { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat},
+ { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat},
+ { .compatible = "mediatek,mt8183-mmc", .data = &mt8183_compat},
{ .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat},
- { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat},
- { .compatible = "mediatek,mt6779-mmc", .data = &mt6779_compat},
+
{}
};
MODULE_DEVICE_TABLE(of, msdc_of_ids);
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c
index 5fe4528e296e..5798aee06653 100644
--- a/drivers/mmc/host/rtsx_usb_sdmmc.c
+++ b/drivers/mmc/host/rtsx_usb_sdmmc.c
@@ -1042,7 +1042,6 @@ static int sd_set_timing(struct rtsx_usb_sdmmc *host,
unsigned char timing, bool *ddr_mode)
{
struct rtsx_ucr *ucr = host->ucr;
- int err;
*ddr_mode = false;
@@ -1097,9 +1096,7 @@ static int sd_set_timing(struct rtsx_usb_sdmmc *host,
break;
}
- err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
-
- return err;
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
}
static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index dc2991422a87..3a091a387ecb 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2441,6 +2441,7 @@ static const struct of_device_id sdhci_msm_dt_match[] = {
*/
{.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var},
{.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var},
+ {.compatible = "qcom,sdm670-sdhci", .data = &sdm845_sdhci_var},
{.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var},
{.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var},
{},
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 622b7de96c7f..169b84761041 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -297,6 +297,27 @@ static const struct sdhci_pci_fixes sdhci_ricoh_mmc = {
SDHCI_QUIRK_MISSING_CAPS
};
+static void ene_714_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ sdhci_set_ios(mmc, ios);
+
+ /*
+ * Some (ENE) controllers misbehave on some ios operations,
+ * signalling timeout and CRC errors even on CMD0. Resetting
+ * it on each ios seems to solve the problem.
+ */
+ if (!(host->flags & SDHCI_DEVICE_DEAD))
+ sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+}
+
+static int ene_714_probe_slot(struct sdhci_pci_slot *slot)
+{
+ slot->host->mmc_host_ops.set_ios = ene_714_set_ios;
+ return 0;
+}
+
static const struct sdhci_pci_fixes sdhci_ene_712 = {
.quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_BROKEN_DMA,
@@ -304,8 +325,8 @@ static const struct sdhci_pci_fixes sdhci_ene_712 = {
static const struct sdhci_pci_fixes sdhci_ene_714 = {
.quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE |
- SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
SDHCI_QUIRK_BROKEN_DMA,
+ .probe_slot = ene_714_probe_slot,
};
static const struct sdhci_pci_fixes sdhci_cafe = {
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index 0d4d343dbb77..ad457cd9cbaa 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -317,11 +317,12 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
u32 reg_val;
/*
- * This handler only implements the eMMC tuning that is specific to
+ * This handler implements the hardware tuning that is specific to
* this controller. Fall back to the standard method for other TIMING.
*/
if ((host->timing != MMC_TIMING_MMC_HS200) &&
- (host->timing != MMC_TIMING_UHS_SDR104))
+ (host->timing != MMC_TIMING_UHS_SDR104) &&
+ (host->timing != MMC_TIMING_UHS_SDR50))
return sdhci_execute_tuning(mmc, opcode);
if (WARN_ON((opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
@@ -631,6 +632,8 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
if (reg & 0x1)
host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+ host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50;
+
sdhci_pci_o2_enable_msi(chip, host);
if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
index f33e9349e4e6..46c55ab4884c 100644
--- a/drivers/mmc/host/sdhci-sprd.c
+++ b/drivers/mmc/host/sdhci-sprd.c
@@ -205,14 +205,14 @@ static inline u32 sdhci_sprd_calc_div(u32 base_clk, u32 clk)
if ((base_clk / div) > (clk * 2))
div++;
- if (div > SDHCI_SPRD_CLK_MAX_DIV)
- div = SDHCI_SPRD_CLK_MAX_DIV;
-
if (div % 2)
div = (div + 1) / 2;
else
div = div / 2;
+ if (div > SDHCI_SPRD_CLK_MAX_DIV)
+ div = SDHCI_SPRD_CLK_MAX_DIV;
+
return div;
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 251172890af7..fef03de85b99 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -233,28 +233,62 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
}
EXPORT_SYMBOL_GPL(sdhci_reset);
-static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
+static bool sdhci_do_reset(struct sdhci_host *host, u8 mask)
{
if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
struct mmc_host *mmc = host->mmc;
if (!mmc->ops->get_cd(mmc))
- return;
+ return false;
}
host->ops->reset(host, mask);
- if (mask & SDHCI_RESET_ALL) {
+ return true;
+}
+
+static void sdhci_reset_for_all(struct sdhci_host *host)
+{
+ if (sdhci_do_reset(host, SDHCI_RESET_ALL)) {
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma)
host->ops->enable_dma(host);
}
-
/* Resetting the controller clears many */
host->preset_enabled = false;
}
}
+enum sdhci_reset_reason {
+ SDHCI_RESET_FOR_INIT,
+ SDHCI_RESET_FOR_REQUEST_ERROR,
+ SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY,
+ SDHCI_RESET_FOR_TUNING_ABORT,
+ SDHCI_RESET_FOR_CARD_REMOVED,
+ SDHCI_RESET_FOR_CQE_RECOVERY,
+};
+
+static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason)
+{
+ switch (reason) {
+ case SDHCI_RESET_FOR_INIT:
+ sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ break;
+ case SDHCI_RESET_FOR_REQUEST_ERROR:
+ case SDHCI_RESET_FOR_TUNING_ABORT:
+ case SDHCI_RESET_FOR_CARD_REMOVED:
+ case SDHCI_RESET_FOR_CQE_RECOVERY:
+ sdhci_do_reset(host, SDHCI_RESET_CMD);
+ sdhci_do_reset(host, SDHCI_RESET_DATA);
+ break;
+ case SDHCI_RESET_FOR_REQUEST_ERROR_DATA_ONLY:
+ sdhci_do_reset(host, SDHCI_RESET_DATA);
+ break;
+ }
+}
+
+#define sdhci_reset_for(h, r) sdhci_reset_for_reason((h), SDHCI_RESET_FOR_##r)
+
static void sdhci_set_default_irqs(struct sdhci_host *host)
{
host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
@@ -323,9 +357,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
unsigned long flags;
if (soft)
- sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ sdhci_reset_for(host, INIT);
else
- sdhci_do_reset(host, SDHCI_RESET_ALL);
+ sdhci_reset_for_all(host);
if (host->v4_mode)
sdhci_do_enable_v4_mode(host);
@@ -1538,8 +1572,9 @@ static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
*/
if (data->error) {
if (!host->cmd || host->cmd == data_cmd)
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
+ sdhci_reset_for(host, REQUEST_ERROR);
+ else
+ sdhci_reset_for(host, REQUEST_ERROR_DATA_ONLY);
}
if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) ==
@@ -2403,14 +2438,6 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->ops->set_clock(host, host->clock);
} else
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-
- /*
- * Some (ENE) controllers go apeshit on some ios operation,
- * signalling timeout and CRC errors even on CMD0. Resetting
- * it on each ios seems to solve the problem.
- */
- if (host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
- sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
}
EXPORT_SYMBOL_GPL(sdhci_set_ios);
@@ -2718,8 +2745,7 @@ void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
{
sdhci_reset_tuning(host);
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
+ sdhci_reset_for(host, TUNING_ABORT);
sdhci_end_tuning(host);
@@ -2987,8 +3013,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
pr_err("%s: Resetting controller.\n",
mmc_hostname(mmc));
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
+ sdhci_reset_for(host, CARD_REMOVED);
sdhci_error_out_mrqs(host, -ENOMEDIUM);
}
@@ -3059,12 +3084,7 @@ static bool sdhci_request_done(struct sdhci_host *host)
/* This is to force an update */
host->ops->set_clock(host, host->clock);
- /*
- * Spec says we should do both at the same time, but Ricoh
- * controllers do not like that.
- */
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
+ sdhci_reset_for(host, REQUEST_ERROR);
host->pending_reset = false;
}
@@ -3905,10 +3925,8 @@ void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery)
host->cqe_on = false;
- if (recovery) {
- sdhci_do_reset(host, SDHCI_RESET_CMD);
- sdhci_do_reset(host, SDHCI_RESET_DATA);
- }
+ if (recovery)
+ sdhci_reset_for(host, CQE_RECOVERY);
pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n",
mmc_hostname(mmc), host->ier,
@@ -4066,7 +4084,7 @@ void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver,
if (debug_quirks2)
host->quirks2 = debug_quirks2;
- sdhci_do_reset(host, SDHCI_RESET_ALL);
+ sdhci_reset_for_all(host);
if (host->v4_mode)
sdhci_do_enable_v4_mode(host);
@@ -4807,7 +4825,7 @@ int __sdhci_add_host(struct sdhci_host *host)
unled:
sdhci_led_unregister(host);
unirq:
- sdhci_do_reset(host, SDHCI_RESET_ALL);
+ sdhci_reset_for_all(host);
sdhci_writel(host, 0, SDHCI_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
free_irq(host->irq, host);
@@ -4865,7 +4883,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
sdhci_led_unregister(host);
if (!dead)
- sdhci_do_reset(host, SDHCI_RESET_ALL);
+ sdhci_reset_for_all(host);
sdhci_writel(host, 0, SDHCI_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 95a08f09df30..d750c464bd1e 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -379,8 +379,6 @@ struct sdhci_host {
#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2)
/* Controller doesn't like clearing the power reg before a change */
#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3)
-/* Controller has flaky internal state so reset it on each ios change */
-#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4)
/* Controller has an unusable DMA engine */
#define SDHCI_QUIRK_BROKEN_DMA (1<<5)
/* Controller has an unusable ADMA engine */
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
index e7ced1496a07..8f1023480e12 100644
--- a/drivers/mmc/host/sdhci_am654.c
+++ b/drivers/mmc/host/sdhci_am654.c
@@ -554,7 +554,6 @@ static const struct cqhci_host_ops sdhci_am654_cqhci_ops = {
static int sdhci_am654_cqe_add_host(struct sdhci_host *host)
{
struct cqhci_host *cq_host;
- int ret;
cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(struct cqhci_host),
GFP_KERNEL);
@@ -568,9 +567,7 @@ static int sdhci_am654_cqe_add_host(struct sdhci_host *host)
host->mmc->caps2 |= MMC_CAP2_CQE;
- ret = cqhci_init(cq_host, host->mmc, 1);
-
- return ret;
+ return cqhci_init(cq_host, host->mmc, 1);
}
static int sdhci_am654_get_otap_delay(struct sdhci_host *host,
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
index 163ac9df8cca..9b5c503e3a3f 100644
--- a/drivers/mmc/host/wmt-sdmmc.c
+++ b/drivers/mmc/host/wmt-sdmmc.c
@@ -846,7 +846,7 @@ static int wmt_mci_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk_sdmmc)) {
dev_err(&pdev->dev, "Error getting clock\n");
ret = PTR_ERR(priv->clk_sdmmc);
- goto fail5;
+ goto fail5_and_a_half;
}
ret = clk_prepare_enable(priv->clk_sdmmc);
@@ -863,6 +863,9 @@ static int wmt_mci_probe(struct platform_device *pdev)
return 0;
fail6:
clk_put(priv->clk_sdmmc);
+fail5_and_a_half:
+ dma_free_coherent(&pdev->dev, mmc->max_blk_count * 16,
+ priv->dma_desc_buffer, priv->dma_desc_device_addr);
fail5:
free_irq(dma_irq, priv);
fail4:
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index eb8bc5b9b0b7..8fdd3cf971a3 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -476,7 +476,7 @@ struct mmc_host {
unsigned int sdio_irqs;
struct task_struct *sdio_irq_thread;
- struct delayed_work sdio_irq_work;
+ struct work_struct sdio_irq_work;
bool sdio_irq_pending;
atomic_t sdio_irq_thread_abort;