MMC host:

- 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
  - sdhci-msm: 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
 -----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAmM8P8cXHHVsZi5oYW5z
 c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjCkCYg//a6lPP1HkpcUgpwk8iYosdwEU
 BKQDRnuUvU/ddfL85/WaUpbM6atdwtHB80lxZ3+krtNWYWxWdQWV1qTRrNFN6kI4
 qoOqXfFUa3brSwteOoGOCw7YYWveVjC3FFWDPAIRBzKmjiJwvFnF8rBdTl+ahIa1
 tk7cxCyaGmoxlx9Zq0PsRotlM0XhObFVY7TR82RmNh1CGIPqC0EIXpk6C4Ami+SZ
 1KufSg/UPo2rvTD0z0hodtb1fEjLKGvyclB1xlxm7GHvpadolPkOfuR1OoSYuieI
 IeSGfJW6WJ/CQv0PIgR/7I1jqEoZWsNBX6aMSdecpcK0KdwEZwW7iMYhLREaHDta
 KncPIG2i1RaYh6FvNKgtpk685nRK3VGyL83/dR4F3MdRQKN02GdQ0gAPkxqndmuN
 UiogQgcZNcCO2uRbxNu+phc867di1pyeDoTm3vKfDqDWCRqCAKhJDoYoI8anNDJN
 gb1czPYdLQaIQ39tHk8b0tjzTaiWh2xtyXdUcoIzpyJLck4f2vBtZvZGxHlqtSuw
 iOM/ceIHoLZnaEamX+k6wLR33zxYYBL0hZ/6txzAvS6uA1mo3mcD8WdeLOrNmgwG
 BIj3GarBgAU65dSuL2yiXUddis1pTe30dSSZaAVPPt5C3e1T0K4yb1Z9Pm8TXL5u
 uRezDmtH4FxN4wgJu10=
 =bO7a
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2022-10-05 10:00:19 -07:00
commit c3f13bbfc2
28 changed files with 278 additions and 159 deletions

View file

@ -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

View file

@ -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

View file

@ -23,8 +23,6 @@ properties:
reg:
maxItems: 1
spi-max-frequency: true
interrupts:
maxItems: 1

View file

@ -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

View file

@ -89,6 +89,9 @@ properties:
- tx
- rx
iommus:
maxItems: 1
power-domains:
maxItems: 1

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
/*

View file

@ -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:

View file

@ -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);

View file

@ -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

View file

@ -1097,8 +1097,9 @@ static int au1xmmc_probe(struct platform_device *pdev)
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);

View file

@ -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;

View file

@ -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[] = {

View file

@ -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;
}

View file

@ -474,6 +474,84 @@ struct msdc_host {
struct cqhci_host *cq_host;
};
static const struct mtk_mmc_compatible mt2701_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 = 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,
.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 mt6779_compat = {
.clk_div_bits = 12,
.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 mt7620_compat = {
.clk_div_bits = 8,
.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,
.use_internal_cd = true,
};
static const struct mtk_mmc_compatible mt7622_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,
.enhance_rx = true,
.support_64g = false,
};
static const struct mtk_mmc_compatible mt8135_compat = {
.clk_div_bits = 8,
.recheck_sdio_irq = true,
@ -513,45 +591,6 @@ static const struct mtk_mmc_compatible mt8183_compat = {
.support_64g = true,
};
static const struct mtk_mmc_compatible mt2701_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 = 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,
.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 mt7622_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,
.enhance_rx = true,
.support_64g = false,
};
static const struct mtk_mmc_compatible mt8516_compat = {
.clk_div_bits = 12,
.recheck_sdio_irq = true,
@ -563,42 +602,18 @@ static const struct mtk_mmc_compatible mt8516_compat = {
.stop_clk_fix = true,
};
static const struct mtk_mmc_compatible mt7620_compat = {
.clk_div_bits = 8,
.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,
.use_internal_cd = true,
};
static const struct mtk_mmc_compatible mt6779_compat = {
.clk_div_bits = 12,
.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 of_device_id msdc_of_ids[] = {
{ .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,mt2701-mmc", .data = &mt2701_compat},
{ .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat},
{ .compatible = "mediatek,mt7622-mmc", .data = &mt7622_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);

View file

@ -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)

View file

@ -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},
{},

View file

@ -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 = {

View file

@ -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) {

View file

@ -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;
}

View file

@ -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);

View file

@ -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 */

View file

@ -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,

View file

@ -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:

View file

@ -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;