diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-15 15:57:25 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-15 15:57:25 -0800 |
commit | ce51c2b7ceb23a23eb0dc523c80879d8f35e4f38 (patch) | |
tree | 9088f11b41470e02bbf020027682454d33a1871d /drivers/mmc/host | |
parent | 9d0d886799e49e0f6d51e70c823416919544fdb7 (diff) | |
parent | 72b248cfbf3fd308807afe7cc30d05fefeff7fb1 (diff) |
Merge tag 'mmc-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"MMC core:
- Initial support for SD express card/host
MMC host:
- mxc: Convert the driver to DT-only
- mtk-sd: Add HS400 enhanced strobe support
- mtk-sd: Add support for the MT8192 SoC variant
- sdhci-acpi: Allow changing HS200/HS400 driver strength for AMDI0040
- sdhci-esdhc-imx: Convert the driver to DT-only
- sdhci-pci-gli: Improve performance for HS400 mode for GL9763E
- sdhci-pci-gli: Reduce power consumption for GL9755
- sdhci-xenon: Introduce ACPI support
- tmio: Fix command error processing
- tmio: Inform the core about the max_busy_timeout
- tmio/renesas_sdhi: Support custom calculation of busy-wait time
- renesas_sdhi: Reset SCC only when available
- rtsx_pci: Add SD Express mode support for RTS5261
- rtsx_pci: Various fixes and improvements for RTS5261
MEMSTICK:
- Minor fixes/improvements"
* tag 'mmc-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (72 commits)
dt-bindings: mmc: eliminate yamllint warnings
mmc: sdhci-xenon: introduce ACPI support
mmc: sdhci-xenon: use clk only with DT
mmc: sdhci-xenon: switch to device_* API
mmc: sdhci-xenon: use match data for controllers variants
dt-bindings: mmc: Fix xlnx,mio-bank property values for arasan driver
mmc: renesas_sdhi: populate hook for longer busy_wait
mmc: tmio: add hook for custom busy_wait calculation
mmc: tmio: set max_busy_timeout
dt-bindings: mmc: imx: fix the wrongly dropped imx8qm compatible string
mmc: sdhci-pci-gli: Disable slow mode in HS400 mode for GL9763E
mmc: sdhci: Use more concise device_property_read_u64
memstick: r592: Fix error return in r592_probe()
mmc: mxc: Convert the driver to DT-only
mmc: mxs: Remove the unused .id_table
mmc: sdhci-of-arasan: Fix fall-through warnings for Clang
mmc: sdhci-pci-gli: Reduce power consumption for GL9755
mmc: mediatek: depend on COMMON_CLK to fix compile tests
mmc: pxamci: Fix error return code in pxamci_probe
mmc: sdhci: Update firmware interface API
...
Diffstat (limited to 'drivers/mmc/host')
32 files changed, 478 insertions, 318 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 31481c9fcc2e..596f32637315 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -631,8 +631,8 @@ config MMC_SPI config MMC_S3C tristate "Samsung S3C SD/MMC Card Interface support" - depends on ARCH_S3C24XX - depends on S3C24XX_DMAC + depends on ARCH_S3C24XX || COMPILE_TEST + depends on S3C24XX_DMAC || COMPILE_TEST help This selects a driver for the MCI interface found in Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. @@ -664,7 +664,7 @@ config MMC_S3C_PIO config MMC_S3C_DMA bool "Use DMA transfers only" help - Use DMA to transfer data between memory and the hardare. + Use DMA to transfer data between memory and the hardware. Currently, the DMA support in this driver seems to not be working properly and needs to be debugged before this @@ -1023,6 +1023,7 @@ config MMC_BCM2835 config MMC_MTK tristate "MediaTek SD/MMC Card Interface support" depends on HAS_DMA + depends on COMMON_CLK select REGULATOR select MMC_CQHCI help diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 90cd179625fc..2a757c88f9d2 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -290,7 +290,7 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, default: s = ", (R? response)"; break; - }; s; })); + } s; })); host->cmd = cmd; switch (mmc_resp_type(cmd)) { diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 43c5795691fb..a5244435556b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2617,7 +2617,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) struct dw_mci *host = dev_id; u32 pending; struct dw_mci_slot *slot = host->slot; - unsigned long irqflags; pending = mci_readl(host, MINTSTS); /* read-only mask reg */ @@ -2632,15 +2631,15 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) * Hold the lock; we know cmd11_timer can't be kicked * off after the lock is released, so safe to delete. */ - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); dw_mci_cmd_interrupt(host, pending); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); del_timer(&host->cmd11_timer); } if (pending & DW_MCI_CMD_ERROR_FLAGS) { - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); del_timer(&host->cto_timer); mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); @@ -2648,7 +2647,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) smp_wmb(); /* drain writebuffer */ set_bit(EVENT_CMD_COMPLETE, &host->pending_events); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); } if (pending & DW_MCI_DATA_ERROR_FLAGS) { @@ -2661,7 +2660,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) } if (pending & SDMMC_INT_DATA_OVER) { - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); del_timer(&host->dto_timer); @@ -2676,7 +2675,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) set_bit(EVENT_DATA_COMPLETE, &host->pending_events); tasklet_schedule(&host->tasklet); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); } if (pending & SDMMC_INT_RXDR) { @@ -2692,12 +2691,12 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) } if (pending & SDMMC_INT_CMD_DONE) { - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); dw_mci_cmd_interrupt(host, pending); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); } if (pending & SDMMC_INT_CD) { diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 4ec41579940a..13f6a2c0ed04 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -1265,7 +1265,7 @@ static struct platform_driver meson_mmc_driver = { .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(meson_mmc_of_match), + .of_match_table = meson_mmc_of_match, }, }; diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index 1c5299cd0cbe..d4a48916bfb6 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c @@ -418,10 +418,9 @@ static irqreturn_t meson_mx_mmc_irq(int irq, void *data) { struct meson_mx_mmc_host *host = (void *) data; u32 irqs, send; - unsigned long irqflags; irqreturn_t ret; - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); irqs = readl(host->base + MESON_MX_SDIO_IRQS); send = readl(host->base + MESON_MX_SDIO_SEND); @@ -434,7 +433,7 @@ static irqreturn_t meson_mx_mmc_irq(int irq, void *data) /* finally ACK all pending interrupts */ writel(irqs, host->base + MESON_MX_SDIO_IRQS); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); return ret; } diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index f25079ba3bca..89bff4e8ec10 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -465,9 +465,8 @@ static irqreturn_t moxart_irq(int irq, void *devid) { struct moxart_host *host = (struct moxart_host *)devid; u32 status; - unsigned long flags; - spin_lock_irqsave(&host->lock, flags); + spin_lock(&host->lock); status = readl(host->base + REG_STATUS); if (status & CARD_CHANGE) { @@ -484,7 +483,7 @@ static irqreturn_t moxart_irq(int irq, void *devid) if (status & (FIFO_ORUN | FIFO_URUN) && host->mrq) moxart_transfer_pio(host); - spin_unlock_irqrestore(&host->lock, flags); + spin_unlock(&host->lock); return IRQ_HANDLED; } diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 004fbfc23672..de09c6347524 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -35,6 +35,7 @@ #include "cqhci.h" #define MAX_BD_NUM 1024 +#define MSDC_NR_CLOCKS 3 /*--------------------------------------------------------------------------*/ /* Common Definition */ @@ -77,9 +78,12 @@ #define MSDC_PAD_TUNE0 0xf0 #define PAD_DS_TUNE 0x188 #define PAD_CMD_TUNE 0x18c +#define EMMC51_CFG0 0x204 #define EMMC50_CFG0 0x208 +#define EMMC50_CFG1 0x20c #define EMMC50_CFG3 0x220 #define SDC_FIFO_CFG 0x228 +#define CQHCI_SETTING 0x7fc /*--------------------------------------------------------------------------*/ /* Top Pad Register Offset */ @@ -260,15 +264,26 @@ #define PAD_CMD_TUNE_RX_DLY3 (0x1f << 1) /* RW */ +/* EMMC51_CFG0 mask */ +#define CMDQ_RDAT_CNT (0x3ff << 12) /* RW */ + #define EMMC50_CFG_PADCMD_LATCHCK (0x1 << 0) /* RW */ #define EMMC50_CFG_CRCSTS_EDGE (0x1 << 3) /* RW */ #define EMMC50_CFG_CFCSTS_SEL (0x1 << 4) /* RW */ +#define EMMC50_CFG_CMD_RESP_SEL (0x1 << 9) /* RW */ + +/* EMMC50_CFG1 mask */ +#define EMMC50_CFG1_DS_CFG (0x1 << 28) /* RW */ #define EMMC50_CFG3_OUTS_WR (0x1f << 0) /* RW */ #define SDC_FIFO_CFG_WRVALIDSEL (0x1 << 24) /* RW */ #define SDC_FIFO_CFG_RDVALIDSEL (0x1 << 25) /* RW */ +/* CQHCI_SETTING */ +#define CQHCI_RD_CMD_WND_SEL (0x1 << 14) /* RW */ +#define CQHCI_WR_CMD_WND_SEL (0x1 << 15) /* RW */ + /* EMMC_TOP_CONTROL mask */ #define PAD_RXDLY_SEL (0x1 << 0) /* RW */ #define DELAY_EN (0x1 << 1) /* RW */ @@ -425,6 +440,8 @@ struct msdc_host { struct clk *h_clk; /* msdc h_clk */ struct clk *bus_clk; /* bus clock which used to access register */ struct clk *src_clk_cg; /* msdc source clock control gate */ + struct clk *sys_clk_cg; /* msdc subsys clock control gate */ + struct clk_bulk_data bulk_clks[MSDC_NR_CLOCKS]; u32 mclk; /* mmc subsystem clock frequency */ u32 src_clk_freq; /* source clock frequency */ unsigned char timing; @@ -785,6 +802,7 @@ static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks) static void msdc_gate_clock(struct msdc_host *host) { + clk_bulk_disable_unprepare(MSDC_NR_CLOCKS, host->bulk_clks); clk_disable_unprepare(host->src_clk_cg); clk_disable_unprepare(host->src_clk); clk_disable_unprepare(host->bus_clk); @@ -793,10 +811,18 @@ static void msdc_gate_clock(struct msdc_host *host) static void msdc_ungate_clock(struct msdc_host *host) { + int ret; + clk_prepare_enable(host->h_clk); clk_prepare_enable(host->bus_clk); clk_prepare_enable(host->src_clk); clk_prepare_enable(host->src_clk_cg); + ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks); + if (ret) { + dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n"); + return; + } + while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) cpu_relax(); } @@ -1537,13 +1563,12 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) struct mmc_host *mmc = mmc_from_priv(host); while (true) { - unsigned long flags; struct mmc_request *mrq; struct mmc_command *cmd; struct mmc_data *data; u32 events, event_mask; - spin_lock_irqsave(&host->lock, flags); + spin_lock(&host->lock); events = readl(host->base + MSDC_INT); event_mask = readl(host->base + MSDC_INTEN); if ((events & event_mask) & MSDC_INT_SDIOIRQ) @@ -1554,7 +1579,7 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) mrq = host->mrq; cmd = host->cmd; data = host->data; - spin_unlock_irqrestore(&host->lock, flags); + spin_unlock(&host->lock); if ((events & event_mask) & MSDC_INT_SDIOIRQ) sdio_signal_irq(mmc); @@ -2266,6 +2291,31 @@ static int msdc_get_cd(struct mmc_host *mmc) return !val; } +static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct msdc_host *host = mmc_priv(mmc); + + if (ios->enhanced_strobe) { + msdc_prepare_hs400_tuning(mmc, ios); + sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_PADCMD_LATCHCK, 1); + sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_CMD_RESP_SEL, 1); + sdr_set_field(host->base + EMMC50_CFG1, EMMC50_CFG1_DS_CFG, 1); + + sdr_clr_bits(host->base + CQHCI_SETTING, CQHCI_RD_CMD_WND_SEL); + sdr_clr_bits(host->base + CQHCI_SETTING, CQHCI_WR_CMD_WND_SEL); + sdr_clr_bits(host->base + EMMC51_CFG0, CMDQ_RDAT_CNT); + } else { + sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_PADCMD_LATCHCK, 0); + sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_CMD_RESP_SEL, 0); + sdr_set_field(host->base + EMMC50_CFG1, EMMC50_CFG1_DS_CFG, 0); + + sdr_set_bits(host->base + CQHCI_SETTING, CQHCI_RD_CMD_WND_SEL); + sdr_set_bits(host->base + CQHCI_SETTING, CQHCI_WR_CMD_WND_SEL); + sdr_set_field(host->base + EMMC51_CFG0, CMDQ_RDAT_CNT, 0xb4); + } +} + static void msdc_cqe_enable(struct mmc_host *mmc) { struct msdc_host *host = mmc_priv(mmc); @@ -2323,6 +2373,7 @@ static const struct mmc_host_ops mt_msdc_ops = { .set_ios = msdc_ops_set_ios, .get_ro = mmc_gpio_get_ro, .get_cd = msdc_get_cd, + .hs400_enhanced_strobe = msdc_hs400_enhanced_strobe, .enable_sdio_irq = msdc_enable_sdio_irq, .ack_sdio_irq = msdc_ack_sdio_irq, .start_signal_voltage_switch = msdc_ops_switch_volt, @@ -2367,6 +2418,48 @@ static void msdc_of_property_parse(struct platform_device *pdev, host->cqhci = false; } +static int msdc_of_clock_parse(struct platform_device *pdev, + struct msdc_host *host) +{ + int ret; + + host->src_clk = devm_clk_get(&pdev->dev, "source"); + if (IS_ERR(host->src_clk)) + return PTR_ERR(host->src_clk); + + host->h_clk = devm_clk_get(&pdev->dev, "hclk"); + if (IS_ERR(host->h_clk)) + return PTR_ERR(host->h_clk); + + host->bus_clk = devm_clk_get_optional(&pdev->dev, "bus_clk"); + if (IS_ERR(host->bus_clk)) + host->bus_clk = NULL; + + /*source clock control gate is optional clock*/ + host->src_clk_cg = devm_clk_get_optional(&pdev->dev, "source_cg"); + if (IS_ERR(host->src_clk_cg)) + host->src_clk_cg = NULL; + + host->sys_clk_cg = devm_clk_get_optional(&pdev->dev, "sys_cg"); + if (IS_ERR(host->sys_clk_cg)) + host->sys_clk_cg = NULL; + + /* If present, always enable for this clock gate */ + clk_prepare_enable(host->sys_clk_cg); + + host->bulk_clks[0].id = "pclk_cg"; + host->bulk_clks[1].id = "axi_cg"; + host->bulk_clks[2].id = "ahb_cg"; + ret = devm_clk_bulk_get_optional(&pdev->dev, MSDC_NR_CLOCKS, + host->bulk_clks); + if (ret) { + dev_err(&pdev->dev, "Cannot get pclk/axi/ahb clock gates\n"); + return ret; + } + + return 0; +} + static int msdc_drv_probe(struct platform_device *pdev) { struct mmc_host *mmc; @@ -2406,30 +2499,16 @@ static int msdc_drv_probe(struct platform_device *pdev) if (ret) goto host_free; - host->src_clk = devm_clk_get(&pdev->dev, "source"); - if (IS_ERR(host->src_clk)) { - ret = PTR_ERR(host->src_clk); - goto host_free; - } - - host->h_clk = devm_clk_get(&pdev->dev, "hclk"); - if (IS_ERR(host->h_clk)) { - ret = PTR_ERR(host->h_clk); + ret = msdc_of_clock_parse(pdev, host); + if (ret) goto host_free; - } - - host->bus_clk = devm_clk_get(&pdev->dev, "bus_clk"); - if (IS_ERR(host->bus_clk)) - host->bus_clk = NULL; - /*source clock control gate is optional clock*/ - host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg"); - if (IS_ERR(host->src_clk_cg)) - host->src_clk_cg = NULL; host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, "hrst"); - if (IS_ERR(host->reset)) - return PTR_ERR(host->reset); + if (IS_ERR(host->reset)) { + ret = PTR_ERR(host->reset); + goto host_free; + } host->irq = platform_get_irq(pdev, 0); if (host->irq < 0) { diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 12ee07285980..2fe6fcdbb1b3 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -157,32 +157,16 @@ struct mxcmci_host { enum mxcmci_type devtype; }; -static const struct platform_device_id mxcmci_devtype[] = { - { - .name = "imx21-mmc", - .driver_data = IMX21_MMC, - }, { - .name = "imx31-mmc", - .driver_data = IMX31_MMC, - }, { - .name = "mpc512x-sdhc", - .driver_data = MPC512X_MMC, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, mxcmci_devtype); - static const struct of_device_id mxcmci_of_match[] = { { .compatible = "fsl,imx21-mmc", - .data = &mxcmci_devtype[IMX21_MMC], + .data = (void *) IMX21_MMC, }, { .compatible = "fsl,imx31-mmc", - .data = &mxcmci_devtype[IMX31_MMC], + .data = (void *) IMX31_MMC, }, { .compatible = "fsl,mpc5121-sdhc", - .data = &mxcmci_devtype[MPC512X_MMC], + .data = (void *) MPC512X_MMC, }, { /* sentinel */ } @@ -1001,13 +985,10 @@ static int mxcmci_probe(struct platform_device *pdev) int ret = 0, irq; bool dat3_card_detect = false; dma_cap_mask_t mask; - const struct of_device_id *of_id; struct imxmmc_platform_data *pdata = pdev->dev.platform_data; pr_info("i.MX/MPC512x SDHC driver\n"); - of_id = of_match_device(mxcmci_of_match, &pdev->dev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -1044,12 +1025,7 @@ static int mxcmci_probe(struct platform_device *pdev) mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; mmc->max_seg_size = mmc->max_req_size; - if (of_id) { - const struct platform_device_id *id_entry = of_id->data; - host->devtype = id_entry->driver_data; - } else { - host->devtype = pdev->id_entry->driver_data; - } + host->devtype = (enum mxcmci_type)of_device_get_match_data(&pdev->dev); /* adjust max_segs after devtype detection */ if (!is_mpc512x_mmc(host)) @@ -1241,7 +1217,6 @@ static SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume); static struct platform_driver mxcmci_driver = { .probe = mxcmci_probe, .remove = mxcmci_remove, - .id_table = mxcmci_devtype, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 75007f61df97..56bbc6cd9c84 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -545,19 +545,6 @@ static const struct mmc_host_ops mxs_mmc_ops = { .enable_sdio_irq = mxs_mmc_enable_sdio_irq, }; -static const struct platform_device_id mxs_ssp_ids[] = { - { - .name = "imx23-mmc", - .driver_data = IMX23_SSP, - }, { - .name = "imx28-mmc", - .driver_data = IMX28_SSP, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, mxs_ssp_ids); - static const struct of_device_id mxs_mmc_dt_ids[] = { { .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_SSP, }, { .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_SSP, }, @@ -567,8 +554,6 @@ MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids); static int mxs_mmc_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(mxs_mmc_dt_ids, &pdev->dev); struct device_node *np = pdev->dev.of_node; struct mxs_mmc_host *host; struct mmc_host *mmc; @@ -593,7 +578,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) goto out_mmc_free; } - ssp->devid = (enum mxs_ssp_id) of_id->data; + ssp->devid = (enum mxs_ssp_id)of_device_get_match_data(&pdev->dev); host->mmc = mmc; host->sdio_irq_en = 0; @@ -723,7 +708,6 @@ static SIMPLE_DEV_PM_OPS(mxs_mmc_pm_ops, mxs_mmc_suspend, mxs_mmc_resume); static struct platform_driver mxs_mmc_driver = { .probe = mxs_mmc_probe, .remove = mxs_mmc_remove, - .id_table = mxs_ssp_ids, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index ccf214a89eda..53b81582f1af 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -134,10 +134,9 @@ static void owl_mmc_update_reg(void __iomem *reg, unsigned int val, bool state) static irqreturn_t owl_irq_handler(int irq, void *devid) { struct owl_mmc_host *owl_host = devid; - unsigned long flags; u32 state; - spin_lock_irqsave(&owl_host->lock, flags); + spin_lock(&owl_host->lock); state = readl(owl_host->base + OWL_REG_SD_STATE); if (state & OWL_SD_STATE_TEI) { @@ -147,7 +146,7 @@ static irqreturn_t owl_irq_handler(int irq, void *devid) complete(&owl_host->sdc_complete); } - spin_unlock_irqrestore(&owl_host->lock, flags); + spin_unlock(&owl_host->lock); return IRQ_HANDLED; } @@ -522,11 +521,11 @@ static void owl_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* Enable DDR mode if requested */ if (ios->timing == MMC_TIMING_UHS_DDR50) { - owl_host->ddr_50 = 1; + owl_host->ddr_50 = true; owl_mmc_update_reg(owl_host->base + OWL_REG_SD_EN, OWL_SD_EN_DDREN, true); } else { - owl_host->ddr_50 = 0; + owl_host->ddr_50 = false; } } diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 29f6180a0036..316393c694d7 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -731,6 +731,7 @@ static int pxamci_probe(struct platform_device *pdev) host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); if (IS_ERR(host->power)) { + ret = PTR_ERR(host->power); dev_err(dev, "Failed requesting gpio_power\n"); goto out; } diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index acb9c81a4e45..38f028e70633 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -18,28 +18,39 @@ * */ -#include <linux/kernel.h> #include <linux/clk.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/pm_domain.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/mfd/tmio.h> #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> #include <linux/mmc/slot-gpio.h> -#include <linux/mfd/tmio.h> -#include <linux/sh_dma.h> -#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/pinctrl/pinctrl-state.h> +#include <linux/platform_device.h> +#include <linux/pm_domain.h> #include <linux/regulator/consumer.h> +#include <linux/sh_dma.h> +#include <linux/slab.h> #include <linux/sys_soc.h> #include "renesas_sdhi.h" #include "tmio_mmc.h" -#define HOST_MODE 0xe4 +#define CTL_HOST_MODE 0xe4 +#define HOST_MODE_GEN2_SDR50_WMODE BIT(0) +#define HOST_MODE_GEN2_SDR104_WMODE BIT(0) +#define HOST_MODE_GEN3_WMODE BIT(0) +#define HOST_MODE_GEN3_BUSWIDTH BIT(8) + +#define HOST_MODE_GEN3_16BIT HOST_MODE_GEN3_WMODE +#define HOST_MODE_GEN3_32BIT (HOST_MODE_GEN3_WMODE | HOST_MODE_GEN3_BUSWIDTH) +#define HOST_MODE_GEN3_64BIT 0 + +#define CTL_SDIF_MODE 0xe6 +#define SDIF_MODE_HS400 BIT(0) #define SDHI_VER_GEN2_SDR50 0x490c #define SDHI_VER_RZ_A1 0x820b @@ -60,26 +71,26 @@ static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width) */ switch (sd_ctrl_read16(host, CTL_VERSION)) { case SDHI_VER_GEN2_SDR50: - val = (width == 32) ? 0x0001 : 0x0000; + val = (width == 32) ? HOST_MODE_GEN2_SDR50_WMODE : 0; break; case SDHI_VER_GEN2_SDR104: - val = (width == 32) ? 0x0000 : 0x0001; + val = (width == 32) ? 0 : HOST_MODE_GEN2_SDR104_WMODE; break; case SDHI_VER_GEN3_SD: case SDHI_VER_GEN3_SDMMC: if (width == 64) - val = 0x0000; + val = HOST_MODE_GEN3_64BIT; else if (width == 32) - val = 0x0101; + val = HOST_MODE_GEN3_32BIT; else - val = 0x0001; + val = HOST_MODE_GEN3_16BIT; break; default: /* nothing to do */ return; } - sd_ctrl_write16(host, HOST_MODE, val); + sd_ctrl_write16(host, CTL_HOST_MODE, val); } static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host) @@ -373,7 +384,7 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc) sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); /* Set HS400 mode */ - sd_ctrl_write16(host, CTL_SDIF_MODE, 0x0001 | + sd_ctrl_write16(host, CTL_SDIF_MODE, SDIF_MODE_HS400 | sd_ctrl_read16(host, CTL_SDIF_MODE)); sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, @@ -424,9 +435,11 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc) priv->needs_adjust_hs400 = true; } -static void renesas_sdhi_reset_scc(struct tmio_mmc_host *host, - struct renesas_sdhi *priv) +static void renesas_sdhi_disable_scc(struct mmc_host *mmc) { + struct tmio_mmc_host *host = mmc_priv(mmc); + struct renesas_sdhi *priv = host_to_priv(host); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN & sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); @@ -434,14 +447,6 @@ static void renesas_sdhi_reset_scc(struct tmio_mmc_host *host, ~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL & sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL)); -} - -static void renesas_sdhi_disable_scc(struct mmc_host *mmc) -{ - struct tmio_mmc_host *host = mmc_priv(mmc); - struct renesas_sdhi *priv = host_to_priv(host); - - renesas_sdhi_reset_scc(host, priv); sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL, ~SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN & @@ -527,7 +532,7 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); /* Reset HS400 mode */ - sd_ctrl_write16(host, CTL_SDIF_MODE, ~0x0001 & + sd_ctrl_write16(host, CTL_SDIF_MODE, ~SDIF_MODE_HS400 & sd_ctrl_read16(host, CTL_SDIF_MODE)); sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos); @@ -552,24 +557,38 @@ static int renesas_sdhi_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_io return 0; } +/* only populated for TMIO_MMC_MIN_RCAR2 */ static void renesas_sdhi_reset(struct tmio_mmc_host *host) { struct renesas_sdhi *priv = host_to_priv(host); + u16 val; - renesas_sdhi_reset_scc(host, priv); - renesas_sdhi_reset_hs400_mode(host, priv); - priv->needs_adjust_hs400 = false; + if (priv->scc_ctl) { + renesas_sdhi_disable_scc(host->mmc); + renesas_sdhi_reset_hs400_mode(host, priv); + priv->needs_adjust_hs400 = false; - sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | - sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); + sd_scc_write32(host, priv, SH_MOBILE_SDHI |