Commit c3f13bbf authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC updates from Ulf Hansson:

 - dt-bindings: Increase maximum supported frequency to 384MHz

 - dw_mmc-rockchip: Add support for the rk3128 variant

 - meson-gx: Add support for SDIO interrupts

 - mtk-sd: Add support for MT6795 Helio X10 variant

 - sdhci: Improve the code by centralizing the CMD/DATA reset handling

 - sdhci-msm:
     - Add support for the sdm670 variant
     - Add support for the sm6115 variant

 - sdhci-omap: Make Vignesh replace Kishon as the maintainer

 - sdhci-pci-o2micro: Disable fragile support for DDR50 in favor of
   SDR50

 - sdhci-sprd: Fix clock divider limitation

* tag 'mmc-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (31 commits)
  mmc: sdhci: Centralize CMD and DATA reset handling
  mmc: sdhci: Get rid of SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS
  mmc: sdhci: Remove misleading comment about resets
  mmc: sdhci: Separate out sdhci_reset_for_all()
  MAINTAINERS: Add Vignesh as maintainer of TI SDHCI OMAP DRIVER
  mmc: sdhci-msm: add compatible string check for sdm670
  dt-bindings: mmc: sdhci-msm: add sdm670 compatible
  mmc: wmt-sdmmc: Fix an error handling path in wmt_mci_probe()
  mmc: rtsx_usb_sdmmc: Remove the unneeded result variable
  mmc: sdhci-of-aspeed: Add dependency on ARCH_ASPEED
  mmc: mtk-sd: Add support for MT6795 Helio X10
  mmc: mtk-sd: Reorder of_device_id and platform data by name
  mmc: sdhci-sprd: Fix the limitation of div
  dt-bindings: mmc: sdhci-msm: Add pinctrl-1 property
  dt-bindings: mmc: rockchip: add rockchip,rk3128-dw-mshc
  dt-bindings: mmc: renesas,sdhi: Add iommus property
  mmc: sdhci_am654: Remove the unneeded result variable
  mmc: meson-gx: add SDIO interrupt support
  mmc: meson-gx: adjust and re-use constant IRQ_EN_MASK
  mmc: jz4740_mmc: Fix error check for dma_map_sg
  ...
parents ebcfaeec 178422c2
...@@ -8,7 +8,6 @@ title: Cadence SD/SDIO/eMMC Host Controller (SD4HC) ...@@ -8,7 +8,6 @@ title: Cadence SD/SDIO/eMMC Host Controller (SD4HC)
maintainers: maintainers:
- Masahiro Yamada <yamada.masahiro@socionext.com> - Masahiro Yamada <yamada.masahiro@socionext.com>
- Piotr Sroka <piotrs@cadence.com>
allOf: allOf:
- $ref: mmc-controller.yaml - $ref: mmc-controller.yaml
......
...@@ -88,11 +88,18 @@ properties: ...@@ -88,11 +88,18 @@ properties:
default: 1 default: 1
max-frequency: max-frequency:
description: description: |
Maximum operating frequency of the bus. 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 $ref: /schemas/types.yaml#/definitions/uint32
minimum: 400000 minimum: 400000
maximum: 200000000 maximum: 384000000
disable-wp: disable-wp:
$ref: /schemas/types.yaml#/definitions/flag $ref: /schemas/types.yaml#/definitions/flag
......
...@@ -23,8 +23,6 @@ properties: ...@@ -23,8 +23,6 @@ properties:
reg: reg:
maxItems: 1 maxItems: 1
spi-max-frequency: true
interrupts: interrupts:
maxItems: 1 maxItems: 1
......
...@@ -20,6 +20,7 @@ properties: ...@@ -20,6 +20,7 @@ properties:
- mediatek,mt2701-mmc - mediatek,mt2701-mmc
- mediatek,mt2712-mmc - mediatek,mt2712-mmc
- mediatek,mt6779-mmc - mediatek,mt6779-mmc
- mediatek,mt6795-mmc
- mediatek,mt7620-mmc - mediatek,mt7620-mmc
- mediatek,mt7622-mmc - mediatek,mt7622-mmc
- mediatek,mt8135-mmc - mediatek,mt8135-mmc
......
...@@ -89,6 +89,9 @@ properties: ...@@ -89,6 +89,9 @@ properties:
- tx - tx
- rx - rx
iommus:
maxItems: 1
power-domains: power-domains:
maxItems: 1 maxItems: 1
......
...@@ -32,6 +32,7 @@ properties: ...@@ -32,6 +32,7 @@ properties:
- rockchip,px30-dw-mshc - rockchip,px30-dw-mshc
- rockchip,rk1808-dw-mshc - rockchip,rk1808-dw-mshc
- rockchip,rk3036-dw-mshc - rockchip,rk3036-dw-mshc
- rockchip,rk3128-dw-mshc
- rockchip,rk3228-dw-mshc - rockchip,rk3228-dw-mshc
- rockchip,rk3308-dw-mshc - rockchip,rk3308-dw-mshc
- rockchip,rk3328-dw-mshc - rockchip,rk3328-dw-mshc
......
...@@ -51,6 +51,9 @@ properties: ...@@ -51,6 +51,9 @@ properties:
sdhci-caps-mask: true sdhci-caps-mask: true
dma-coherent:
type: boolean
# PHY output tap delays: # PHY output tap delays:
# Used to delay the data valid window and align it to the sampling clock. # 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 # Binding needs to be provided for each supported speed mode otherwise the
......
...@@ -38,9 +38,11 @@ properties: ...@@ -38,9 +38,11 @@ properties:
- qcom,sc7180-sdhci - qcom,sc7180-sdhci
- qcom,sc7280-sdhci - qcom,sc7280-sdhci
- qcom,sdm630-sdhci - qcom,sdm630-sdhci
- qcom,sdm670-sdhci
- qcom,sdm845-sdhci - qcom,sdm845-sdhci
- qcom,sdx55-sdhci - qcom,sdx55-sdhci
- qcom,sdx65-sdhci - qcom,sdx65-sdhci
- qcom,sm6115-sdhci
- qcom,sm6125-sdhci - qcom,sm6125-sdhci
- qcom,sm6350-sdhci - qcom,sm6350-sdhci
- qcom,sm8150-sdhci - qcom,sm8150-sdhci
...@@ -96,6 +98,10 @@ properties: ...@@ -96,6 +98,10 @@ properties:
description: description:
Should specify pin control groups used for this controller. Should specify pin control groups used for this controller.
pinctrl-1:
description:
Should specify sleep pin control groups used for this controller.
resets: resets:
maxItems: 1 maxItems: 1
......
...@@ -7536,7 +7536,7 @@ M: Adrian Hunter <adrian.hunter@intel.com> ...@@ -7536,7 +7536,7 @@ M: Adrian Hunter <adrian.hunter@intel.com>
M: Ritesh Harjani <riteshh@codeaurora.org> M: Ritesh Harjani <riteshh@codeaurora.org>
M: Asutosh Das <asutoshd@codeaurora.org> M: Asutosh Das <asutoshd@codeaurora.org>
L: linux-mmc@vger.kernel.org L: linux-mmc@vger.kernel.org
S: Maintained S: Supported
F: drivers/mmc/host/cqhci* F: drivers/mmc/host/cqhci*
EMULEX 10Gbps iSCSI - OneConnect DRIVER EMULEX 10Gbps iSCSI - OneConnect DRIVER
...@@ -18316,7 +18316,7 @@ F: drivers/mmc/host/sdhci-brcmstb* ...@@ -18316,7 +18316,7 @@ F: drivers/mmc/host/sdhci-brcmstb*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
M: Adrian Hunter <adrian.hunter@intel.com> M: Adrian Hunter <adrian.hunter@intel.com>
L: linux-mmc@vger.kernel.org L: linux-mmc@vger.kernel.org
S: Maintained S: Supported
F: drivers/mmc/host/sdhci* F: drivers/mmc/host/sdhci*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) MICROCHIP DRIVER SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) MICROCHIP DRIVER
...@@ -18339,7 +18339,7 @@ S: Maintained ...@@ -18339,7 +18339,7 @@ S: Maintained
F: drivers/mmc/host/sdhci-spear.c F: drivers/mmc/host/sdhci-spear.c
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) TI OMAP DRIVER 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 L: linux-mmc@vger.kernel.org
S: Maintained S: Maintained
F: drivers/mmc/host/sdhci-omap.c F: drivers/mmc/host/sdhci-omap.c
......
...@@ -565,7 +565,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) ...@@ -565,7 +565,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq); init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan); 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); timer_setup(&host->retune_timer, mmc_retune_timer, 0);
/* /*
......
...@@ -1043,7 +1043,7 @@ static int mmc_sdio_suspend(struct mmc_host *host) ...@@ -1043,7 +1043,7 @@ static int mmc_sdio_suspend(struct mmc_host *host)
/* Prevent processing of SDIO IRQs in suspended state. */ /* Prevent processing of SDIO IRQs in suspended state. */
mmc_card_set_suspended(host->card); 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); mmc_claim_host(host);
...@@ -1103,7 +1103,7 @@ static int mmc_sdio_resume(struct mmc_host *host) ...@@ -1103,7 +1103,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD))
wake_up_process(host->sdio_irq_thread); wake_up_process(host->sdio_irq_thread);
else if (host->caps & MMC_CAP_SDIO_IRQ) 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: out:
......
...@@ -124,7 +124,7 @@ static void sdio_run_irqs(struct mmc_host *host) ...@@ -124,7 +124,7 @@ static void sdio_run_irqs(struct mmc_host *host)
void sdio_irq_work(struct work_struct *work) void sdio_irq_work(struct work_struct *work)
{ {
struct mmc_host *host = 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); sdio_run_irqs(host);
} }
...@@ -132,7 +132,7 @@ void sdio_irq_work(struct work_struct *work) ...@@ -132,7 +132,7 @@ void sdio_irq_work(struct work_struct *work)
void sdio_signal_irq(struct mmc_host *host) void sdio_signal_irq(struct mmc_host *host)
{ {
host->sdio_irq_pending = true; 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); EXPORT_SYMBOL_GPL(sdio_signal_irq);
......
...@@ -157,6 +157,7 @@ config MMC_SDHCI_OF_ARASAN ...@@ -157,6 +157,7 @@ config MMC_SDHCI_OF_ARASAN
config MMC_SDHCI_OF_ASPEED config MMC_SDHCI_OF_ASPEED
tristate "SDHCI OF support for the ASPEED SDHCI controller" tristate "SDHCI OF support for the ASPEED SDHCI controller"
depends on ARCH_ASPEED || COMPILE_TEST
depends on MMC_SDHCI_PLTFM depends on MMC_SDHCI_PLTFM
depends on OF && OF_ADDRESS depends on OF && OF_ADDRESS
select MMC_SDHCI_IO_ACCESSORS select MMC_SDHCI_IO_ACCESSORS
......
...@@ -1097,8 +1097,9 @@ static int au1xmmc_probe(struct platform_device *pdev) ...@@ -1097,8 +1097,9 @@ static int au1xmmc_probe(struct platform_device *pdev)
if (host->platdata && host->platdata->cd_setup && if (host->platdata && host->platdata->cd_setup &&
!(mmc->caps & MMC_CAP_NEEDS_POLL)) !(mmc->caps & MMC_CAP_NEEDS_POLL))
host->platdata->cd_setup(mmc, 0); host->platdata->cd_setup(mmc, 0);
out_clk:
clk_disable_unprepare(host->clk); clk_disable_unprepare(host->clk);
out_clk:
clk_put(host->clk); clk_put(host->clk);
out_irq: out_irq:
free_irq(host->irq, host); free_irq(host->irq, host);
......
...@@ -298,7 +298,7 @@ static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host, ...@@ -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); struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data);
enum dma_data_direction dir = mmc_get_dma_dir(data); enum dma_data_direction dir = mmc_get_dma_dir(data);
int sg_count; unsigned int sg_count;
if (data->host_cookie == COOKIE_PREMAPPED) if (data->host_cookie == COOKIE_PREMAPPED)
return data->sg_count; return data->sg_count;
...@@ -308,7 +308,7 @@ static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host, ...@@ -308,7 +308,7 @@ static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host,
data->sg_len, data->sg_len,
dir); dir);
if (sg_count <= 0) { if (!sg_count) {
dev_err(mmc_dev(host->mmc), dev_err(mmc_dev(host->mmc),
"Failed to map scatterlist for DMA operation\n"); "Failed to map scatterlist for DMA operation\n");
return -EINVAL; return -EINVAL;
......
...@@ -41,14 +41,17 @@ ...@@ -41,14 +41,17 @@
#define CLK_V2_TX_DELAY_MASK GENMASK(19, 16) #define CLK_V2_TX_DELAY_MASK GENMASK(19, 16)
#define CLK_V2_RX_DELAY_MASK GENMASK(23, 20) #define CLK_V2_RX_DELAY_MASK GENMASK(23, 20)
#define CLK_V2_ALWAYS_ON BIT(24) #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_TX_DELAY_MASK GENMASK(21, 16)
#define CLK_V3_RX_DELAY_MASK GENMASK(27, 22) #define CLK_V3_RX_DELAY_MASK GENMASK(27, 22)
#define CLK_V3_ALWAYS_ON BIT(28) #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_TX_DELAY_MASK(h) (h->data->tx_delay_mask)
#define CLK_RX_DELAY_MASK(h) (h->data->rx_delay_mask) #define CLK_RX_DELAY_MASK(h) (h->data->rx_delay_mask)
#define CLK_ALWAYS_ON(h) (h->data->always_on) #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_DELAY 0x4
#define SD_EMMC_ADJUST 0x8 #define SD_EMMC_ADJUST 0x8
...@@ -101,8 +104,7 @@ ...@@ -101,8 +104,7 @@
#define IRQ_RESP_STATUS BIT(14) #define IRQ_RESP_STATUS BIT(14)
#define IRQ_SDIO BIT(15) #define IRQ_SDIO BIT(15)
#define IRQ_EN_MASK \ #define IRQ_EN_MASK \
(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN | IRQ_RESP_STATUS |\ (IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN)
IRQ_SDIO)
#define SD_EMMC_CMD_CFG 0x50 #define SD_EMMC_CMD_CFG 0x50
#define SD_EMMC_CMD_ARG 0x54 #define SD_EMMC_CMD_ARG 0x54
...@@ -136,6 +138,7 @@ struct meson_mmc_data { ...@@ -136,6 +138,7 @@ struct meson_mmc_data {
unsigned int rx_delay_mask; unsigned int rx_delay_mask;
unsigned int always_on; unsigned int always_on;
unsigned int adjust; unsigned int adjust;
unsigned int irq_sdio_sleep;
}; };
struct sd_emmc_desc { struct sd_emmc_desc {
...@@ -175,6 +178,7 @@ struct meson_host { ...@@ -175,6 +178,7 @@ struct meson_host {
bool vqmmc_enabled; bool vqmmc_enabled;
bool needs_pre_post_req; bool needs_pre_post_req;
spinlock_t lock;
}; };
#define CMD_CFG_LENGTH_MASK GENMASK(8, 0) #define CMD_CFG_LENGTH_MASK GENMASK(8, 0)
...@@ -431,6 +435,7 @@ static int meson_mmc_clk_init(struct meson_host *host) ...@@ -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_CORE_PHASE_MASK, CLK_PHASE_180);
clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0); clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0);
clk_reg |= FIELD_PREP(CLK_RX_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); writel(clk_reg, host->regs + SD_EMMC_CLOCK);
/* get the mux parents */ /* get the mux parents */
...@@ -929,33 +934,54 @@ static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd) ...@@ -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) static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
{ {
struct meson_host *host = dev_id; struct meson_host *host = dev_id;
struct mmc_command *cmd; struct mmc_command *cmd;
struct mmc_data *data; u32 status, raw_status;
u32 irq_en, status, raw_status;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
irq_en = readl(host->regs + SD_EMMC_IRQ_EN);
raw_status = readl(host->regs + SD_EMMC_STATUS); raw_status = readl(host->regs + SD_EMMC_STATUS);
status = raw_status & irq_en; status = raw_status & (IRQ_EN_MASK | IRQ_SDIO);
if (!status) { if (!status) {
dev_dbg(host->dev, dev_dbg(host->dev,
"Unexpected IRQ! irq_en 0x%08x - status 0x%08x\n", "Unexpected IRQ! irq_en 0x%08lx - status 0x%08x\n",
irq_en, raw_status); IRQ_EN_MASK | IRQ_SDIO, raw_status);
return IRQ_NONE; return IRQ_NONE;
} }
if (WARN_ON(!host) || WARN_ON(!host->cmd)) if (WARN_ON(!host))
return IRQ_NONE; return IRQ_NONE;
/* ack all raised interrupts */ /* ack all raised interrupts */
writel(status, host->regs + SD_EMMC_STATUS); writel(status, host->regs + SD_EMMC_STATUS);
cmd = host->cmd; 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; cmd->error = 0;
if (status & IRQ_CRC_ERR) { if (status & IRQ_CRC_ERR) {
dev_dbg(host->dev, "CRC Error - status 0x%08x\n", status); 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) ...@@ -973,12 +999,9 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
meson_mmc_read_resp(host->mmc, cmd); 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)) { if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) {
struct mmc_data *data = cmd->data;
if (data && !cmd->error) if (data && !cmd->error)
data->bytes_xfered = data->blksz * data->blocks; data->bytes_xfered = data->blksz * data->blocks;
if (meson_mmc_bounce_buf_read(data) || 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) ...@@ -1121,6 +1144,21 @@ static int meson_mmc_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
return -EINVAL; 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 = { static const struct mmc_host_ops meson_mmc_ops = {
.request = meson_mmc_request, .request = meson_mmc_request,
.set_ios = meson_mmc_set_ios, .set_ios = meson_mmc_set_ios,
...@@ -1130,6 +1168,8 @@ static const struct mmc_host_ops meson_mmc_ops = { ...@@ -1130,6 +1168,8 @@ static const struct mmc_host_ops meson_mmc_ops = {
.execute_tuning = meson_mmc_resampling_tuning, .execute_tuning = meson_mmc_resampling_tuning,
.card_busy = meson_mmc_card_busy, .card_busy = meson_mmc_card_busy,
.start_signal_voltage_switch = meson_mmc_voltage_switch, .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) static int meson_mmc_probe(struct platform_device *pdev)
...@@ -1226,10 +1266,8 @@ 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 */ /* clear, ack and enable interrupts */
writel(0, host->regs + SD_EMMC_IRQ_EN); writel(0, host->regs + SD_EMMC_IRQ_EN);
writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS);
host->regs + SD_EMMC_STATUS); writel(IRQ_EN_MASK, host->regs + SD_EMMC_IRQ_EN);
writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN,
host->regs + SD_EMMC_IRQ_EN);
ret = request_threaded_irq(host->irq, meson_mmc_irq, ret = request_threaded_irq(host->irq, meson_mmc_irq,
meson_mmc_irq_thread, IRQF_ONESHOT, meson_mmc_irq_thread, IRQF_ONESHOT,
...@@ -1237,7 +1275,13 @@ static int meson_mmc_probe(struct platform_device *pdev) ...@@ -1237,7 +1275,13 @@ static int meson_mmc_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_init_clk; goto err_init_clk;
spin_lock_init(&host->lock);
mmc->caps |= MMC_CAP_CMD23; mmc->caps |= MMC_CAP_CMD23;
if (mmc->caps & MMC_CAP_SDIO_IRQ)
mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
if (host->dram_access_quirk) { if (host->dram_access_quirk) {
/* Limit segments to 1 due to low available sram memory */ /* Limit segments to 1 due to low available sram memory */
mmc->max_segs = 1; mmc->max_segs = 1;
...@@ -1328,6 +1372,7 @@ static const struct meson_mmc_data meson_gx_data = { ...@@ -1328,6 +1372,7 @@ static const struct meson_mmc_data meson_gx_data = {
.rx_delay_mask = CLK_V2_RX_DELAY_MASK, .rx_delay_mask = CLK_V2_RX_DELAY_MASK,
.always_on = CLK_V2_ALWAYS_ON, .always_on = CLK_V2_ALWAYS_ON,
.adjust = SD_EMMC_ADJUST, .adjust = SD_EMMC_ADJUST,
.irq_sdio_sleep = CLK_V2_IRQ_SDIO_SLEEP,
}; };
static const struct meson_mmc_data meson_axg_data = { static const struct meson_mmc_data meson_axg_data = {
...@@ -1335,6 +1380,7 @@ 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, .rx_delay_mask = CLK_V3_RX_DELAY_MASK,
.always_on = CLK_V3_ALWAYS_ON, .always_on = CLK_V3_ALWAYS_ON,
.adjust = SD_EMMC_V3_ADJUST, .adjust = SD_EMMC_V3_ADJUST,
.irq_sdio_sleep = CLK_V3_IRQ_SDIO_SLEEP,
}; };
static const struct of_device_id meson_mmc_of_match[] = { static const struct of_device_id meson_mmc_of_match[] = {
......
...@@ -381,14 +381,14 @@ static void meson_mx_sdhc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -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) static int meson_mx_sdhc_map_dma(struct mmc_host *mmc, struct mmc_request *mrq)
{ {
struct mmc_data *data = mrq->data; struct mmc_data *data = mrq->data;
int dma_len; unsigned int dma_len;
if (!data) if (!data)
return 0; return 0;
dma_len = dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dma_len = dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len,
mmc_get_dma_dir(data)); mmc_get_dma_dir(data));
if (dma_len <= 0) { if (!dma_len) {
dev_err(mmc_dev(mmc), "dma_map_sg failed\n"); dev_err(mmc_dev(mmc), "dma_map_sg failed\n");
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -474,33 +474,20 @@ struct msdc_host { ...@@ -474,33 +474,20 @@ struct msdc_host {
struct cqhci_host *cq_host; struct cqhci_host *cq_host;
}; };
static const struct mtk_mmc_compatible mt8135_compat = { static const struct mtk_mmc_compatible mt2701_compat = {
.clk_div_bits = 8, .clk_div_bits = 12,
.recheck_sdio_irq = true, .recheck_sdio_irq = true,
.hs400_tune = false, .hs400_tune = false,
.pad_tune_reg = MSDC_PAD_TUNE, .pad_tune_reg = MSDC_PAD_TUNE0,
.async_fifo = false, .async_fifo = true,
.data_tune = false, .data_tune = true,
.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,
.busy_check = false, .busy_check = false,
.stop_clk_fix = false, .stop_clk_fix = false,
.enhance_rx = false, .enhance_rx = false,
.support_64g = false, .support_64g = false,
}; };
static const struct mtk_mmc_compatible mt8183_compat = { static const struct mtk_mmc_compatible mt2712_compat = {
.clk_div_bits = 12, .clk_div_bits = 12,
.recheck_sdio_irq = false, .recheck_sdio_irq = false,
.hs400_tune = false, .hs400_tune = false,
...@@ -513,30 +500,43 @@ static const struct mtk_mmc_compatible mt8183_compat = { ...@@ -513,30 +500,43 @@ static const struct mtk_mmc_compatible mt8183_compat = {
.support_64g = true, .support_64g = true,
}; };
static const struct mtk_mmc_compatible mt2701_compat = { static const struct mtk_mmc_compatible mt6779_compat = {
.clk_div_bits = 12, .clk_div_bits = 12,
.recheck_sdio_irq = true, .recheck_sdio_irq = false,
.hs400_tune = false, .hs400_tune = false,
.pad_tune_reg = MSDC_PAD_TUNE0, .pad_tune_reg = MSDC_PAD_TUNE0,
.async_fifo = true, .async_fifo = true,
.data_tune = 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, .busy_check = false,
.stop_clk_fix = false, .stop_clk_fix = false,
.enhance_rx = false, .enhance_rx = false,
.support_64g = false, .support_64g = false,
}; };
static const struct mtk_mmc_compatible mt2712_compat = { static const struct mtk_mmc_compatible mt7620_compat = {
.clk_div_bits = 12, .clk_div_bits = 8,
.recheck_sdio_irq = false, .recheck_sdio_irq = true,
.hs400_tune = false, .hs400_tune = false,
.pad_tune_reg = MSDC_PAD_TUNE0, .pad_tune_reg = MSDC_PAD_TUNE,
.async_fifo = true, .async_fifo = false,
.data_tune = true, .data_tune = false,
.busy_check = true, .busy_check = false,
.stop_clk_fix = true, .stop_clk_fix = false,
.enhance_rx = true, .enhance_rx = false,
.support_64g = true, .use_internal_cd = true,
}; };
static const struct mtk_mmc_compatible mt7622_compat = { static const struct mtk_mmc_compatible mt7622_compat = {
...@@ -552,31 +552,33 @@ static const struct mtk_mmc_compatible mt7622_compat = { ...@@ -552,31 +552,33 @@ static const struct mtk_mmc_compatible mt7622_compat = {
.support_64g = false, .support_64g = false,
}; };
static const struct mtk_mmc_compatible mt8516_compat = { static const struct mtk_mmc_compatible mt8135_compat = {
.clk_div_bits = 12, .clk_div_bits = 8,
.recheck_sdio_irq = true, .recheck_sdio_irq = true,
.hs400_tune = false, .hs400_tune = false,
.pad_tune_reg = MSDC_PAD_TUNE0, .pad_tune_reg = MSDC_PAD_TUNE,
.async_fifo = true, .async_fifo = false,
.data_tune = true, .data_tune = false,
.busy_check = true, .busy_check = false,
.stop_clk_fix = true, .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, .clk_div_bits = 8,
.recheck_sdio_irq = true, .recheck_sdio_irq = true,
.hs400_tune = false, .hs400_tune = true,
.pad_tune_reg = MSDC_PAD_TUNE, .pad_tune_reg = MSDC_PAD_TUNE,
.async_fifo = false, .async_fifo = false,
.data_tune = false, .data_tune = false,
.busy_check = false, .busy_check = false,
.stop_clk_fix = false, .stop_clk_fix = false,
.enhance_rx = 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, .clk_div_bits = 12,
.recheck_sdio_irq = false, .recheck_sdio_irq = false,
.hs400_tune = false, .hs400_tune = false,
...@@ -589,16 +591,29 @@ static const struct mtk_mmc_compatible mt6779_compat = { ...@@ -589,16 +591,29 @@ static const struct mtk_mmc_compatible mt6779_compat = {
.support_64g = true, .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[] = { 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,mt2701-mmc", .data = &mt2701_compat},
{ .compatible = "mediatek,mt2712-mmc", .data = &mt2712_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,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,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); MODULE_DEVICE_TABLE(of, msdc_of_ids);
......
...@@ -1042,7 +1042,6 @@ static int sd_set_timing(struct rtsx_usb_sdmmc *host, ...@@ -1042,7 +1042,6 @@ static int sd_set_timing(struct rtsx_usb_sdmmc *host,
unsigned char timing, bool *ddr_mode) unsigned char timing, bool *ddr_mode)
{ {
struct rtsx_ucr *ucr = host->ucr; struct rtsx_ucr *ucr = host->ucr;
int err;
*ddr_mode = false; *ddr_mode = false;
...@@ -1097,9 +1096,7 @@ static int sd_set_timing(struct rtsx_usb_sdmmc *host, ...@@ -1097,9 +1096,7 @@ static int sd_set_timing(struct rtsx_usb_sdmmc *host,
break; break;
} }
err = rtsx_usb_send_cmd(ucr, MODE_C, 100); return rtsx_usb_send_cmd(ucr, MODE_C, 100);
return err;
} }
static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
......
...@@ -2441,6 +2441,7 @@ static const struct of_device_id sdhci_msm_dt_match[] = { ...@@ -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-v4", .data = &sdhci_msm_mci_var},
{.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_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,sdm845-sdhci", .data = &sdm845_sdhci_var},
{.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var}, {.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var},
{}, {},
......
...@@ -297,6 +297,27 @@ static const struct sdhci_pci_fixes sdhci_ricoh_mmc = { ...@@ -297,6 +297,27 @@ static const struct sdhci_pci_fixes sdhci_ricoh_mmc = {
SDHCI_QUIRK_MISSING_CAPS 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 = { static const struct sdhci_pci_fixes sdhci_ene_712 = {
.quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE | .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_BROKEN_DMA, SDHCI_QUIRK_BROKEN_DMA,
...@@ -304,8 +325,8 @@ static const struct sdhci_pci_fixes sdhci_ene_712 = { ...@@ -304,8 +325,8 @@ static const struct sdhci_pci_fixes sdhci_ene_712 = {
static const struct sdhci_pci_fixes sdhci_ene_714 = { static const struct sdhci_pci_fixes sdhci_ene_714 = {
.quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE | .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
SDHCI_QUIRK_BROKEN_DMA, SDHCI_QUIRK_BROKEN_DMA,
.probe_slot = ene_714_probe_slot,
}; };
static const struct sdhci_pci_fixes sdhci_cafe = { static const struct sdhci_pci_fixes sdhci_cafe = {
......
...@@ -317,11 +317,12 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode) ...@@ -317,11 +317,12 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
u32 reg_val; 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. * this controller. Fall back to the standard method for other TIMING.
*/ */
if ((host->timing != MMC_TIMING_MMC_HS200) && 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); return sdhci_execute_tuning(mmc, opcode);
if (WARN_ON((opcode != MMC_SEND_TUNING_BLOCK_HS200) && 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) ...@@ -631,6 +632,8 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
if (reg & 0x1) if (reg & 0x1)
host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50;
sdhci_pci_o2_enable_msi(chip, host); sdhci_pci_o2_enable_msi(chip, host);
if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) { if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
......
...@@ -205,14 +205,14 @@ static inline u32 sdhci_sprd_calc_div(u32 base_clk, u32 clk) ...@@ -205,14 +205,14 @@ static inline u32 sdhci_sprd_calc_div(u32 base_clk, u32 clk)
if ((base_clk / div) > (clk * 2)) if ((base_clk / div) > (clk * 2))
div++; div++;
if (div > SDHCI_SPRD_CLK_MAX_DIV)
div = SDHCI_SPRD_CLK_MAX_DIV;
if (div % 2) if (div % 2)
div = (div + 1) / 2; div = (div + 1) / 2;
else else
div = div / 2; div = div / 2;
if (div > SDHCI_SPRD_CLK_MAX_DIV)
div = SDHCI_SPRD_CLK_MAX_DIV;
return div; return div;
} }
......
...@@ -233,28 +233,62 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) ...@@ -233,28 +233,62 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
} }
EXPORT_SYMBOL_GPL(sdhci_reset); 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) { if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
struct mmc_host *mmc = host->mmc; struct mmc_host *mmc = host->mmc;
if (!mmc->ops->get_cd(mmc)) if (!mmc->ops->get_cd(mmc))
return; return false;
} }
host->ops->reset(host, mask); 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->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma) if (host->ops->enable_dma)
host->ops->enable_dma(host); host->ops->enable_dma(host);
} }
/* Resetting the controller clears many */ /* Resetting the controller clears many */
host->preset_enabled = false; 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) static void sdhci_set_default_irqs(struct sdhci_host *host)
{ {
host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | 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) ...@@ -323,9 +357,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
unsigned long flags; unsigned long flags;
if (soft) if (soft)
sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); sdhci_reset_for(host, INIT);
else else
sdhci_do_reset(host, SDHCI_RESET_ALL); sdhci_reset_for_all(host);
if (host->v4_mode) if (host->v4_mode)
sdhci_do_enable_v4_mode(host); sdhci_do_enable_v4_mode(host);
...@@ -1538,8 +1572,9 @@ static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) ...@@ -1538,8 +1572,9 @@ static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
*/ */
if (data->error) { if (data->error) {
if (!host->cmd || host->cmd == data_cmd) if (!host->cmd || host->cmd == data_cmd)
sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_reset_for(host, REQUEST_ERROR);
sdhci_do_reset(host, SDHCI_RESET_DATA); else
sdhci_reset_for(host, REQUEST_ERROR_DATA_ONLY);
} }
if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == 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) ...@@ -2403,14 +2438,6 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->ops->set_clock(host, host->clock); host->ops->set_clock(host, host->clock);
} else } else
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 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); EXPORT_SYMBOL_GPL(sdhci_set_ios);
...@@ -2718,8 +2745,7 @@ void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) ...@@ -2718,8 +2745,7 @@ void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
{ {
sdhci_reset_tuning(host); sdhci_reset_tuning(host);
sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_reset_for(host, TUNING_ABORT);
sdhci_do_reset(host, SDHCI_RESET_DATA);
sdhci_end_tuning(host); sdhci_end_tuning(host);
...@@ -2987,8 +3013,7 @@ static void sdhci_card_event(struct mmc_host *mmc) ...@@ -2987,8 +3013,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
pr_err("%s: Resetting controller.\n", pr_err("%s: Resetting controller.\n",
mmc_hostname(mmc)); mmc_hostname(mmc));
sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_reset_for(host, CARD_REMOVED);
sdhci_do_reset(host, SDHCI_RESET_DATA);
sdhci_error_out_mrqs(host, -ENOMEDIUM); sdhci_error_out_mrqs(host, -ENOMEDIUM);
} }
...@@ -3059,12 +3084,7 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -3059,12 +3084,7 @@ static bool sdhci_request_done(struct sdhci_host *host)
/* This is to force an update */ /* This is to force an update */
host->ops->set_clock(host, host->clock); host->ops->set_clock(host, host->clock);
/* sdhci_reset_for(host, REQUEST_ERROR);
* 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);
host->pending_reset = false; host->pending_reset = false;
} }
...@@ -3905,10 +3925,8 @@ void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery) ...@@ -3905,10 +3925,8 @@ void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery)
host->cqe_on = false; host->cqe_on = false;
if (recovery) { if (recovery)
sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_reset_for(host, CQE_RECOVERY);
sdhci_do_reset(host, SDHCI_RESET_DATA);
}
pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n", pr_debug("%s: sdhci: CQE off, IRQ mask %#x, IRQ status %#x\n",
mmc_hostname(mmc), host->ier, mmc_hostname(mmc), host->ier,
...@@ -4066,7 +4084,7 @@ void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver, ...@@ -4066,7 +4084,7 @@ void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver,
if (debug_quirks2) if (debug_quirks2)
host->quirks2 = debug_quirks2; host->quirks2 = debug_quirks2;
sdhci_do_reset(host, SDHCI_RESET_ALL); sdhci_reset_for_all(host);
if (host->v4_mode) if (host->v4_mode)
sdhci_do_enable_v4_mode(host); sdhci_do_enable_v4_mode(host);
...@@ -4807,7 +4825,7 @@ int __sdhci_add_host(struct sdhci_host *host) ...@@ -4807,7 +4825,7 @@ int __sdhci_add_host(struct sdhci_host *host)
unled: unled:
sdhci_led_unregister(host); sdhci_led_unregister(host);
unirq: 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_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
free_irq(host->irq, host); free_irq(host->irq, host);
...@@ -4865,7 +4883,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) ...@@ -4865,7 +4883,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
sdhci_led_unregister(host); sdhci_led_unregister(host);
if (!dead) 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_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
......
...@@ -379,8 +379,6 @@ struct sdhci_host { ...@@ -379,8 +379,6 @@ struct sdhci_host {
#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2)
/* Controller doesn't like clearing the power reg before a change */ /* Controller doesn't like clearing the power reg before a change */
#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) #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 */ /* Controller has an unusable DMA engine */
#define SDHCI_QUIRK_BROKEN_DMA (1<<5) #define SDHCI_QUIRK_BROKEN_DMA (1<<5)
/* Controller has an unusable ADMA engine */ /* Controller has an unusable ADMA engine */
......
...@@ -554,7 +554,6 @@ static const struct cqhci_host_ops sdhci_am654_cqhci_ops = { ...@@ -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) static int sdhci_am654_cqe_add_host(struct sdhci_host *host)
{ {
struct cqhci_host *cq_host; struct cqhci_host *cq_host;
int ret;
cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(struct cqhci_host), cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(struct cqhci_host),
GFP_KERNEL); GFP_KERNEL);
...@@ -568,9 +567,7 @@ static int sdhci_am654_cqe_add_host(struct sdhci_host *host) ...@@ -568,9 +567,7 @@ static int sdhci_am654_cqe_add_host(struct sdhci_host *host)
host->mmc->caps2 |= MMC_CAP2_CQE; host->mmc->caps2 |= MMC_CAP2_CQE;
ret = cqhci_init(cq_host, host->mmc, 1); return cqhci_init(cq_host, host->mmc, 1);
return ret;
} }
static int sdhci_am654_get_otap_delay(struct sdhci_host *host, static int sdhci_am654_get_otap_delay(struct sdhci_host *host,
......
...@@ -846,7 +846,7 @@ static int wmt_mci_probe(struct platform_device *pdev) ...@@ -846,7 +846,7 @@ static int wmt_mci_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk_sdmmc)) { if (IS_ERR(priv->clk_sdmmc)) {
dev_err(&pdev->dev, "Error getting clock\n"); dev_err(&pdev->dev, "Error getting clock\n");
ret = PTR_ERR(priv->clk_sdmmc); ret = PTR_ERR(priv->clk_sdmmc);
goto fail5; goto fail5_and_a_half;
} }
ret = clk_prepare_enable(priv->clk_sdmmc); ret = clk_prepare_enable(priv->clk_sdmmc);
...@@ -863,6 +863,9 @@ static int wmt_mci_probe(struct platform_device *pdev) ...@@ -863,6 +863,9 @@ static int wmt_mci_probe(struct platform_device *pdev)
return 0; return 0;
fail6: fail6:
clk_put(priv->clk_sdmmc); 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: fail5:
free_irq(dma_irq, priv); free_irq(dma_irq, priv);
fail4: fail4:
......
...@@ -476,7 +476,7 @@ struct mmc_host { ...@@ -476,7 +476,7 @@ struct mmc_host {
unsigned int sdio_irqs; unsigned int sdio_irqs;
struct task_struct *sdio_irq_thread; struct task_struct *sdio_irq_thread;
struct delayed_work sdio_irq_work; struct work_struct sdio_irq_work;
bool sdio_irq_pending; bool sdio_irq_pending;
atomic_t sdio_irq_thread_abort; atomic_t sdio_irq_thread_abort;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment