From 4453d51e1814a8b7c2e686e50241d7b28088622e Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Thu, 23 Feb 2023 19:44:02 +0530 Subject: mmc: sdhci-of-arasan: Add support to request the "gate" clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support to read the optional "gate" clock property and request the clock which will be used to ungate the DLL clock. For Xilinx platforms which has DLL module, dll clock must be ungated/enabled when SD controller operates at higher frequencies like 50 MHz, 100 MHz and 200 MHz. This will be done by explicitly requesting gate clock from the driver. Signed-off-by: Swati Agarwal Acked-by: Michal Simek Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230223141402.23979-1-swati.agarwal@amd.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 89c431a34c43..802acb252e7f 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -1630,6 +1630,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev) int ret; struct device_node *node; struct clk *clk_xin; + struct clk *clk_dll; struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct device *dev = &pdev->dev; @@ -1703,6 +1704,12 @@ static int sdhci_arasan_probe(struct platform_device *pdev) goto clk_dis_ahb; } + clk_dll = devm_clk_get_optional_enabled(dev, "gate"); + if (IS_ERR(clk_dll)) { + ret = dev_err_probe(dev, PTR_ERR(clk_dll), "failed to get dll clk\n"); + goto clk_disable_all; + } + if (of_property_read_bool(np, "xlnx,fails-without-test-cd")) sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_FORCE_CDTEST; -- cgit v1.2.3 From 4b4b7ac73704bfa796d2be6b96cb9072f7298861 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 27 Feb 2023 22:02:23 +0100 Subject: mmc: core: Allow invalid regulator in mmc_regulator_set_ocr() Basically all host drivers use code like this: if (!IS_ERR(mmc->supply.vmmc)) mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0) Move the IS_ERR() check to mmc_regulator_set_ocr() to simplify host driver code. Suggested-by: Ulf Hansson Signed-off-by: Heiner Kallweit Link: https://lore.kernel.org/r/0c1e7440-f4bc-b48a-137f-58b75ac98550@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/regulator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c index 609201a467ef..4fad81cd5252 100644 --- a/drivers/mmc/core/regulator.c +++ b/drivers/mmc/core/regulator.c @@ -110,6 +110,9 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, int result = 0; int min_uV, max_uV; + if (IS_ERR(supply)) + return 0; + if (vdd_bit) { mmc_ocrbitnum_to_vdd(vdd_bit, &min_uV, &max_uV); -- cgit v1.2.3 From 63264422785021704c39b38f65a78ab9e4a186d7 Mon Sep 17 00:00:00 2001 From: Zheng Wang Date: Wed, 8 Mar 2023 00:43:38 +0800 Subject: memstick: r592: Fix UAF bug in r592_remove due to race condition In r592_probe, dev->detect_timer was bound with r592_detect_timer. In r592_irq function, the timer function will be invoked by mod_timer. If we remove the module which will call hantro_release to make cleanup, there may be a unfinished work. The possible sequence is as follows, which will cause a typical UAF bug. Fix it by canceling the work before cleanup in r592_remove. CPU0 CPU1 |r592_detect_timer r592_remove | memstick_free_host| put_device; | kfree(host); | | | queue_work | &host->media_checker //use Signed-off-by: Zheng Wang Link: https://lore.kernel.org/r/20230307164338.1246287-1-zyytlz.wz@163.com Signed-off-by: Ulf Hansson --- drivers/memstick/host/r592.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index 1d35d147552d..42bfc46842b8 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -829,7 +829,7 @@ static void r592_remove(struct pci_dev *pdev) /* Stop the processing thread. That ensures that we won't take any more requests */ kthread_stop(dev->io_thread); - + del_timer_sync(&dev->detect_timer); r592_enable_device(dev, false); while (!error && dev->req) { -- cgit v1.2.3 From 07248afa83b0b31d7906201cf0348800d0552d99 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 7 Mar 2023 17:30:36 +0100 Subject: mmc: renesas_sdhi: remove R-Car H3 ES1.* handling R-Car H3 ES1.* was only available to an internal development group and needed a lot of quirks and workarounds. These become a maintenance burden now, so our development group decided to remove upstream support and disable booting for this SoC. Public users only have ES2 onwards. Reviewed-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20230307163041.3815-9-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index f38003f6b1ca..9ab813903b2c 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -72,11 +72,10 @@ enum renesas_sdhi_dma_cookie { static unsigned long global_flags; /* - * Workaround for avoiding to use RX DMAC by multiple channels. - * On R-Car H3 ES1.* and M3-W ES1.0, when multiple SDHI channels use - * RX DMAC simultaneously, sometimes hundreds of bytes data are not - * stored into the system memory even if the DMAC interrupt happened. - * So, this driver then uses one RX DMAC channel only. + * Workaround for avoiding to use RX DMAC by multiple channels. On R-Car M3-W + * ES1.0, when multiple SDHI channels use RX DMAC simultaneously, sometimes + * hundreds of data bytes are not stored into the system memory even if the + * DMAC interrupt happened. So, this driver then uses one RX DMAC channel only. */ #define SDHI_INTERNAL_DMAC_RX_IN_USE 0 @@ -222,7 +221,6 @@ static const struct renesas_sdhi_quirks sdhi_quirks_r9a09g011 = { */ static const struct soc_device_attribute sdhi_quirks_match[] = { { .soc_id = "r8a774a1", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 }, - { .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_4tap_nohs400_one_rx }, { .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_4tap }, { .soc_id = "r8a7796", .revision = "ES1.0", .data = &sdhi_quirks_4tap_nohs400_one_rx }, { .soc_id = "r8a7796", .revision = "ES1.[12]", .data = &sdhi_quirks_4tap_nohs400 }, -- cgit v1.2.3 From 49502408007b77ff290ce62e6218cefaeedcb31a Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Thu, 9 Mar 2023 17:03:49 -0800 Subject: mmc: sdhci-of-dwcmshc: properly determine max clock on Rockchip Currently .get_max_clock returns the current clock rate for cclk_emmc on rk35xx, thus max clock gets set to whatever bootloader set it to. In case of u-boot, it is intentionally reset to 50 MHz if it boots from eMMC, see mmc_deinit() in u-boot sources. As a result, HS200 and HS400 modes are never selected by Linux, because dwcmshc_rk35xx_postinit clears appropriate caps if host->mmc->f_max is < 52MHz cclk_emmc is not a fixed clock on rk35xx, so using sdhci_pltfm_clk_get_max_clock is not appropriate here. Implement rk35xx_get_max_clock that returns actual max clock for cclk_emmc. Signed-off-by: Vasily Khoruzhick Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230310010349.509132-1-anarsoul@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index d1490469184b..e68cd87998c8 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -126,6 +126,13 @@ static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) return pltfm_host->clock; } +static unsigned int rk35xx_get_max_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + return clk_round_rate(pltfm_host->clk, ULONG_MAX); +} + static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc, struct mmc_request *mrq) { @@ -343,7 +350,7 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = { .set_clock = dwcmshc_rk3568_set_clock, .set_bus_width = sdhci_set_bus_width, .set_uhs_signaling = dwcmshc_set_uhs_signaling, - .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_max_clock = rk35xx_get_max_clock, .reset = rk35xx_sdhci_reset, .adma_write_desc = dwcmshc_adma_write_desc, }; -- cgit v1.2.3 From 66756ca342547af8d3d8156b7abf47cb30082f0f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:14 -0600 Subject: mmc: arasan: Use of_property_present() for testing DT property presence It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. As part of this, convert of_get_property/of_find_property calls to the recently added of_property_present() helper when we just want to test for presence of a property and nothing more. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230310144714.1543767-1-robh@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 802acb252e7f..deb67daf179f 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -1434,7 +1434,7 @@ static void sdhci_arasan_unregister_sdclk(struct device *dev) { struct device_node *np = dev->of_node; - if (!of_find_property(np, "#clock-cells", NULL)) + if (!of_property_present(np, "#clock-cells")) return; of_clk_del_provider(dev->of_node); -- cgit v1.2.3 From e37556d947794c0c7730460a3cb029c700fe70cb Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Tue, 7 Mar 2023 14:17:31 +0100 Subject: dt-bindings: mmc: mediatek,mtk-sd: add mt8365 Add binding description for mediatek,mt8365-mmc Signed-off-by: Alexandre Mergnat Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230203-evk-board-support-v2-2-6ec7cdb10ccf@baylibre.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml index 7a649ebc688c..46eefdd19a2c 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -34,6 +34,7 @@ properties: - mediatek,mt8188-mmc - mediatek,mt8192-mmc - mediatek,mt8195-mmc + - mediatek,mt8365-mmc - const: mediatek,mt8183-mmc reg: -- cgit v1.2.3 From ca6b5fe277e91ebca5101dc00c0e26755f0ed6c4 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:14 -0600 Subject: mmc: Use of_property_read_bool() for boolean properties It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. Convert reading boolean properties to to of_property_read_bool(). Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230310144715.1543836-1-robh@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/mmci.c | 22 +++++++++++----------- drivers/mmc/host/omap_hsmmc.c | 8 ++++---- drivers/mmc/host/sdhci-esdhc-imx.c | 4 ++-- drivers/mmc/host/sdhci-pxav2.c | 2 +- drivers/mmc/host/sdhci-s3c.c | 4 ++-- drivers/mmc/host/tmio_mmc_core.c | 2 +- drivers/mmc/host/wmt-sdmmc.c | 6 ++---- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index b9e5dfe74e5c..f2b2e8b0574e 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1962,28 +1962,28 @@ static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc) if (ret) return ret; - if (of_get_property(np, "st,sig-dir-dat0", NULL)) + if (of_property_read_bool(np, "st,sig-dir-dat0")) host->pwr_reg_add |= MCI_ST_DATA0DIREN; - if (of_get_property(np, "st,sig-dir-dat2", NULL)) + if (of_property_read_bool(np, "st,sig-dir-dat2")) host->pwr_reg_add |= MCI_ST_DATA2DIREN; - if (of_get_property(np, "st,sig-dir-dat31", NULL)) + if (of_property_read_bool(np, "st,sig-dir-dat31")) host->pwr_reg_add |= MCI_ST_DATA31DIREN; - if (of_get_property(np, "st,sig-dir-dat74", NULL)) + if (of_property_read_bool(np, "st,sig-dir-dat74")) host->pwr_reg_add |= MCI_ST_DATA74DIREN; - if (of_get_property(np, "st,sig-dir-cmd", NULL)) + if (of_property_read_bool(np, "st,sig-dir-cmd")) host->pwr_reg_add |= MCI_ST_CMDDIREN; - if (of_get_property(np, "st,sig-pin-fbclk", NULL)) + if (of_property_read_bool(np, "st,sig-pin-fbclk")) host->pwr_reg_add |= MCI_ST_FBCLKEN; - if (of_get_property(np, "st,sig-dir", NULL)) + if (of_property_read_bool(np, "st,sig-dir")) host->pwr_reg_add |= MCI_STM32_DIRPOL; - if (of_get_property(np, "st,neg-edge", NULL)) + if (of_property_read_bool(np, "st,neg-edge")) host->clk_reg_add |= MCI_STM32_CLK_NEGEDGE; - if (of_get_property(np, "st,use-ckin", NULL)) + if (of_property_read_bool(np, "st,use-ckin")) mmci_probe_level_translator(mmc); - if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL)) + if (of_property_read_bool(np, "mmc-cap-mmc-highspeed")) mmc->caps |= MMC_CAP_MMC_HIGHSPEED; - if (of_get_property(np, "mmc-cap-sd-highspeed", NULL)) + if (of_property_read_bool(np, "mmc-cap-sd-highspeed")) mmc->caps |= MMC_CAP_SD_HIGHSPEED; return 0; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4bd744755205..517dde777413 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1736,18 +1736,18 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) if (legacy && legacy->name) pdata->name = legacy->name; - if (of_find_property(np, "ti,dual-volt", NULL)) + if (of_property_read_bool(np, "ti,dual-volt")) pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; - if (of_find_property(np, "ti,non-removable", NULL)) { + if (of_property_read_bool(np, "ti,non-removable")) { pdata->nonremovable = true; pdata->no_regulator_off_init = true; } - if (of_find_property(np, "ti,needs-special-reset", NULL)) + if (of_property_read_bool(np, "ti,needs-special-reset")) pdata->features |= HSMMC_HAS_UPDATED_RESET; - if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) + if (of_property_read_bool(np, "ti,needs-special-hs-handling")) pdata->features |= HSMMC_HAS_HSPE_SUPPORT; return pdata; diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 58f042fdd4f4..d7c0c0b9e26c 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1597,7 +1597,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, struct esdhc_platform_data *boarddata = &imx_data->boarddata; int ret; - if (of_get_property(np, "fsl,wp-controller", NULL)) + if (of_property_read_bool(np, "fsl,wp-controller")) boarddata->wp_type = ESDHC_WP_CONTROLLER; /* @@ -1614,7 +1614,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, of_property_read_u32(np, "fsl,strobe-dll-delay-target", &boarddata->strobe_dll_delay_target); - if (of_find_property(np, "no-1-8-v", NULL)) + if (of_property_read_bool(np, "no-1-8-v")) host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index fc306eb1f845..91aca8f8d6ef 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -228,7 +228,7 @@ static struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev) if (!pdata) return NULL; - if (of_find_property(np, "non-removable", NULL)) + if (of_property_read_bool(np, "non-removable")) pdata->flags |= PXA_FLAG_CARD_PERMANENT; of_property_read_u32(np, "bus-width", &bus_width); diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 9085f3932443..504015e84308 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -437,12 +437,12 @@ static int sdhci_s3c_parse_dt(struct device *dev, pdata->max_width = max_width; /* get the card detection method */ - if (of_get_property(node, "broken-cd", NULL)) { + if (of_property_read_bool(node, "broken-cd")) { pdata->cd_type = S3C_SDHCI_CD_NONE; return 0; } - if (of_get_property(node, "non-removable", NULL)) { + if (of_property_read_bool(node, "non-removable")) { pdata->cd_type = S3C_SDHCI_CD_PERMANENT; return 0; } diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index e24c3d284515..be7f18fd4836 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -1084,7 +1084,7 @@ static void tmio_mmc_of_parse(struct platform_device *pdev, * For new platforms, please use "disable-wp" instead of * "toshiba,mmc-wrprotect-disable" */ - if (of_get_property(np, "toshiba,mmc-wrprotect-disable", NULL)) + if (of_property_read_bool(np, "toshiba,mmc-wrprotect-disable")) mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; } diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 9aa3027ca25e..68525d900046 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c @@ -802,10 +802,8 @@ static int wmt_mci_probe(struct platform_device *pdev) priv->power_inverted = 0; priv->cd_inverted = 0; - if (of_get_property(np, "sdon-inverted", NULL)) - priv->power_inverted = 1; - if (of_get_property(np, "cd-inverted", NULL)) - priv->cd_inverted = 1; + priv->power_inverted = of_property_read_bool(np, "sdon-inverted"); + priv->cd_inverted = of_property_read_bool(np, "cd-inverted"); priv->sdmmc_base = of_iomap(np, 0); if (!priv->sdmmc_base) { -- cgit v1.2.3 From 51dfc6142acecfea9bf2041ccadbc3438e31af56 Mon Sep 17 00:00:00 2001 From: Fred Date: Thu, 23 Feb 2023 20:04:50 +0800 Subject: mmc: sdhci-pci-o2micro: Fix SDR50 mode timing issue Change SDR50 mode clock source from DLL output clock to PLL open clock 1.HS200 and SDR104 mode select DLL output clock 2.SDR50 mode select PLL open clock Signed-off-by: Fred Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230223120450.16858-1-fredaibayhubtech@126.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-o2micro.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index 98cadff47b2b..620f52ad9667 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -339,22 +339,24 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode) reg_val &= ~SDHCI_CLOCK_CARD_EN; sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); - /* UnLock WP */ - pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); - scratch_8 &= 0x7f; - pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); - - /* Set pcr 0x354[16] to choose dll clock, and set the default phase */ - pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, ®_val); - reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK); - reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE); - pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val); + if ((host->timing == MMC_TIMING_MMC_HS200) || + (host->timing == MMC_TIMING_UHS_SDR104)) { + /* UnLock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); + scratch_8 &= 0x7f; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); - /* Lock WP */ - pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); - scratch_8 |= 0x80; - pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); + /* Set pcr 0x354[16] to choose dll clock, and set the default phase */ + pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, ®_val); + reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK); + reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE); + pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val); + /* Lock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); + scratch_8 |= 0x80; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); + } /* Start clk */ reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); reg_val |= SDHCI_CLOCK_CARD_EN; -- cgit v1.2.3 From 2c52e002693dc51a789f54ce72e2f639d7cb1067 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 11 Mar 2023 23:27:18 +0100 Subject: mmc: meson-gx: simplify usage of mmc_regulator_set_ocr After 087592395a96 ("mmc: core: Allow invalid regulator in mmc_regulator_set_ocr()") we can remove the checks here. Signed-off-by: Heiner Kallweit Reviewed-by: Martin Blumenstingl Link: https://lore.kernel.org/r/858a592b-ebf4-99b4-74fc-21b4ad3382f8@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-gx-mmc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 2b963a81c2ad..28e04dc4efb6 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -604,8 +604,7 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) */ switch (ios->power_mode) { case MMC_POWER_OFF: - if (!IS_ERR(mmc->supply.vmmc)) - mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { regulator_disable(mmc->supply.vqmmc); @@ -615,8 +614,7 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) break; case MMC_POWER_UP: - if (!IS_ERR(mmc->supply.vmmc)) - mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); break; -- cgit v1.2.3 From 8d91f3f8ae57e6292142ca89f322e90fa0d6ac02 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 11 Mar 2023 23:39:55 +0100 Subject: mmc: core: add helpers mmc_regulator_enable/disable_vqmmc There's a number of drivers (e.g. dw_mmc, meson-gx, mmci, sunxi) using the same mechanism and a private flag vqmmc_enabled to deal with enabling/disabling the vqmmc regulator. Move this to the core and create new helpers mmc_regulator_enable_vqmmc and mmc_regulator_disable_vqmmc. Signed-off-by: Heiner Kallweit Acked-by: Martin Blumenstingl Link: https://lore.kernel.org/r/71586432-360f-9b92-17f6-b05a8a971bc2@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/regulator.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/linux/mmc/host.h | 3 +++ 2 files changed, 44 insertions(+) diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c index 4fad81cd5252..005247a49e51 100644 --- a/drivers/mmc/core/regulator.c +++ b/drivers/mmc/core/regulator.c @@ -274,3 +274,44 @@ int mmc_regulator_get_supply(struct mmc_host *mmc) return 0; } EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); + +/** + * mmc_regulator_enable_vqmmc - enable VQMMC regulator for a host + * @mmc: the host to regulate + * + * Returns 0 or errno. Enables the regulator for vqmmc. + * Keeps track of the enable status for ensuring that calls to + * regulator_enable/disable are balanced. + */ +int mmc_regulator_enable_vqmmc(struct mmc_host *mmc) +{ + int ret = 0; + + if (!IS_ERR(mmc->supply.vqmmc) && !mmc->vqmmc_enabled) { + ret = regulator_enable(mmc->supply.vqmmc); + if (ret < 0) + dev_err(mmc_dev(mmc), "enabling vqmmc regulator failed\n"); + else + mmc->vqmmc_enabled = true; + } + + return ret; +} +EXPORT_SYMBOL_GPL(mmc_regulator_enable_vqmmc); + +/** + * mmc_regulator_disable_vqmmc - disable VQMMC regulator for a host + * @mmc: the host to regulate + * + * Returns 0 or errno. Disables the regulator for vqmmc. + * Keeps track of the enable status for ensuring that calls to + * regulator_enable/disable are balanced. + */ +void mmc_regulator_disable_vqmmc(struct mmc_host *mmc) +{ + if (!IS_ERR(mmc->supply.vqmmc) && mmc->vqmmc_enabled) { + regulator_disable(mmc->supply.vqmmc); + mmc->vqmmc_enabled = false; + } +} +EXPORT_SYMBOL_GPL(mmc_regulator_disable_vqmmc); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 812e6b583b25..461d1543893b 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -450,6 +450,7 @@ struct mmc_host { unsigned int retune_paused:1; /* re-tuning is temporarily disabled */ unsigned int retune_crc_disable:1; /* don't trigger retune upon crc */ unsigned int can_dma_map_merge:1; /* merging can be used */ + unsigned int vqmmc_enabled:1; /* vqmmc regulator is enabled */ int rescan_disable; /* disable card detection */ int rescan_entered; /* used with nonremovable devices */ @@ -598,6 +599,8 @@ static inline int mmc_regulator_set_vqmmc(struct mmc_host *mmc, #endif int mmc_regulator_get_supply(struct mmc_host *mmc); +int mmc_regulator_enable_vqmmc(struct mmc_host *mmc); +void mmc_regulator_disable_vqmmc(struct mmc_host *mmc); static inline int mmc_card_is_removable(struct mmc_host *host) { -- cgit v1.2.3 From e3f0d2213dba10900a1eca08e775c37e1cf8e69f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 11 Mar 2023 23:41:21 +0100 Subject: mmc: meson-gx: use new helpers mmc_regulator_enable/disable_vqmmc Use new helpers mmc_regulator_enable/disable_vqmmc to simplify the code. Signed-off-by: Heiner Kallweit Acked-by: Martin Blumenstingl Link: https://lore.kernel.org/r/2ceb62da-07e6-bafc-c29e-13cc1cdde93a@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-gx-mmc.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 28e04dc4efb6..b8514d9d5e73 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -174,7 +174,6 @@ struct meson_host { int irq; - bool vqmmc_enabled; bool needs_pre_post_req; spinlock_t lock; @@ -605,11 +604,7 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) switch (ios->power_mode) { case MMC_POWER_OFF: mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); - - if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { - regulator_disable(mmc->supply.vqmmc); - host->vqmmc_enabled = false; - } + mmc_regulator_disable_vqmmc(mmc); break; @@ -619,15 +614,7 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) break; case MMC_POWER_ON: - if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { - int ret = regulator_enable(mmc->supply.vqmmc); - - if (ret < 0) - dev_err(host->dev, - "failed to enable vqmmc regulator\n"); - else - host->vqmmc_enabled = true; - } + mmc_regulator_enable_vqmmc(mmc); break; } @@ -1179,7 +1166,6 @@ static int meson_mmc_probe(struct platform_device *pdev) "amlogic,dram-access-quirk"); /* Get regulators and the supported OCR mask */ - host->vqmmc_enabled = false; ret = mmc_regulator_get_supply(mmc); if (ret) return ret; -- cgit v1.2.3 From b8548e387f2ab2d1bfeeadd28d0739825eae3c93 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 14 Mar 2023 13:52:59 +0100 Subject: dt-bindings: mmc: sdhci-msm: Document QCM2290 SDHCI Document the SDHCI on QCM2290. Signed-off-by: Konrad Dybcio Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230314-topic-2290_compats-v1-4-47e26c3c0365@linaro.org Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index 64df6919abaf..7d4c5ca25e0d 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -36,6 +36,7 @@ properties: - enum: - qcom,ipq5332-sdhci - qcom,ipq9574-sdhci + - qcom,qcm2290-sdhci - qcom,qcs404-sdhci - qcom,sc7180-sdhci - qcom,sc7280-sdhci -- cgit v1.2.3 From 6fb11c1812d337e2cc0dd482ffd99fce1b3f88e0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Mar 2023 21:39:01 +0100 Subject: mmc: sdhci: drop useless sdhci_get_compatibility() !OF stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sdhci_get_compatibility() uses OF functions which have stubs for !OF case, thus entire CONFIG_OF ifdef can be dropped. This also fixes !CONFIG_OF W=1 warning: drivers/mmc/host/sdhci-pltfm.c:76:6: error: no previous prototype for ‘sdhci_get_compatibility’ [-Werror=missing-prototypes] Signed-off-by: Krzysztof Kozlowski Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230314203901.20803-1-krzysztof.kozlowski@linaro.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pltfm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 328b132bbe57..673e750a8490 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -54,7 +54,6 @@ static bool sdhci_wp_inverted(struct device *dev) #endif /* CONFIG_PPC */ } -#ifdef CONFIG_OF static void sdhci_get_compatibility(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); @@ -72,9 +71,6 @@ static void sdhci_get_compatibility(struct platform_device *pdev) of_device_is_compatible(np, "fsl,mpc8536-esdhc")) host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; } -#else -void sdhci_get_compatibility(struct platform_device *pdev) {} -#endif /* CONFIG_OF */ void sdhci_get_property(struct platform_device *pdev) { -- cgit v1.2.3 From 220b484fa6e027e6fd296422513f2e7a76f7e6cf Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 15 Mar 2023 13:22:31 +0800 Subject: mmc: dw_mmc-pltfm: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Link: https://lore.kernel.org/r/20230315052231.21212-1-yang.lee@linux.alibaba.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-pltfm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 13e55cff8237..48b7da2b86b3 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -46,8 +46,7 @@ int dw_mci_pltfm_register(struct platform_device *pdev, host->irq_flags = 0; host->pdata = pdev->dev.platform_data; - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - host->regs = devm_ioremap_resource(&pdev->dev, regs); + host->regs = devm_platform_get_and_ioremap_resource(pdev, 0, ®s); if (IS_ERR(host->regs)) return PTR_ERR(host->regs); -- cgit v1.2.3 From e3d1672741eda6763426a467e5fe36c7147a139e Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 15 Mar 2023 13:31:27 +0800 Subject: mmc: jz4740: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Link: https://lore.kernel.org/r/20230315053127.33855-1-yang.lee@linux.alibaba.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/jz4740_mmc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 698450afa7bb..1846a05210e3 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -1079,8 +1079,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev) goto err_free_host; } - host->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - host->base = devm_ioremap_resource(&pdev->dev, host->mem_res); + host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &host->mem_res); if (IS_ERR(host->base)) { ret = PTR_ERR(host->base); goto err_free_host; -- cgit v1.2.3 From 73226532da9554f45e4703244b0b0f9a04ae2bd7 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 15 Mar 2023 13:34:34 +0800 Subject: mmc: omap: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Link: https://lore.kernel.org/r/20230315053434.38316-1-yang.lee@linux.alibaba.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/omap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 57d39283924d..ce78edfb402b 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1345,8 +1345,7 @@ static int mmc_omap_probe(struct platform_device *pdev) if (irq < 0) return -ENXIO; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - host->virt_base = devm_ioremap_resource(&pdev->dev, res); + host->virt_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(host->virt_base)) return PTR_ERR(host->virt_base); -- cgit v1.2.3 From c66c55bec586de84bfccb361c13a70f5b79dd187 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 15 Mar 2023 13:41:13 +0800 Subject: mmc: owl-mmc: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20230315054113.48898-1-yang.lee@linux.alibaba.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/owl-mmc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 3dc143b03939..6f9d31a886ba 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -578,8 +578,7 @@ static int owl_mmc_probe(struct platform_device *pdev) owl_host->mmc = mmc; spin_lock_init(&owl_host->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - owl_host->base = devm_ioremap_resource(&pdev->dev, res); + owl_host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(owl_host->base)) { ret = PTR_ERR(owl_host->base); goto err_free_host; -- cgit v1.2.3 From 288b7baf090b7ea2ac30c09293df00b03e874458 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 15 Mar 2023 13:50:23 +0800 Subject: mmc: sdhci-of-aspeed: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230315055023.61779-1-yang.lee@linux.alibaba.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-aspeed.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index ba6677bf7372..25b4073f698b 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -547,8 +547,7 @@ static int aspeed_sdc_probe(struct platform_device *pdev) return ret; } - sdc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sdc->regs = devm_ioremap_resource(&pdev->dev, sdc->res); + sdc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &sdc->res); if (IS_ERR(sdc->regs)) { ret = PTR_ERR(sdc->regs); goto err_clk; -- cgit v1.2.3 From cf2679018190c75dea87196528e31936da8986aa Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 15 Mar 2023 13:53:55 +0800 Subject: mmc: usdhi6rol0: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Link: https://lore.kernel.org/r/20230315055355.66733-1-yang.lee@linux.alibaba.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/usdhi6rol0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 99515be6e5e5..2f59917b105e 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1790,8 +1790,7 @@ static int usdhi6_probe(struct platform_device *pdev) host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs"); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - host->base = devm_ioremap_resource(dev, res); + host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(host->base)) { ret = PTR_ERR(host->base); goto e_free_mmc; -- cgit v1.2.3 From 189f7370319d2fc3051af5ac0cf9a748931553e9 Mon Sep 17 00:00:00 2001 From: "A, Rashmi" Date: Thu, 16 Mar 2023 17:35:46 +0530 Subject: mmc: sdhci-of-arasan: Remove Intel Thunder Bay SOC support Remove Thunder Bay specific code as the product got cancelled and there are no end customers or users. Signed-off-by: A, Rashmi Reviewed-by: Hunter, Adrian Link: https://lore.kernel.org/r/20230316120549.21486-2-rashmi.a@intel.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index deb67daf179f..72f0595c57d3 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -193,13 +193,6 @@ static const struct sdhci_arasan_soc_ctl_map intel_lgm_sdxc_soc_ctl_map = { .hiword_update = false, }; -static const struct sdhci_arasan_soc_ctl_map thunderbay_soc_ctl_map = { - .baseclkfreq = { .reg = 0x0, .width = 8, .shift = 14 }, - .clockmultiplier = { .reg = 0x4, .width = 8, .shift = 14 }, - .support64b = { .reg = 0x4, .width = 1, .shift = 24 }, - .hiword_update = false, -}; - static const struct sdhci_arasan_soc_ctl_map intel_keembay_soc_ctl_map = { .baseclkfreq = { .reg = 0x0, .width = 8, .shift = 14 }, .clockmultiplier = { .reg = 0x4, .width = 8, .shift = 14 }, @@ -465,15 +458,6 @@ static const struct sdhci_pltfm_data sdhci_arasan_cqe_pdata = { SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, }; -static const struct sdhci_pltfm_data sdhci_arasan_thunderbay_pdata = { - .ops = &sdhci_arasan_cqe_ops, - .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, - .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | - SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | - SDHCI_QUIRK2_STOP_WITH_TC | - SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, -}; - #ifdef CONFIG_PM_SLEEP /** * sdhci_arasan_suspend - Suspend method for the driver @@ -1150,12 +1134,6 @@ static struct sdhci_arasan_of_data sdhci_arasan_generic_data = { .clk_ops = &arasan_clk_ops, }; -static const struct sdhci_arasan_of_data sdhci_arasan_thunderbay_data = { - .soc_ctl_map = &thunderbay_soc_ctl_map, - .pdata = &sdhci_arasan_thunderbay_pdata, - .clk_ops = &arasan_clk_ops, -}; - static const struct sdhci_pltfm_data sdhci_keembay_emmc_pdata = { .ops = &sdhci_arasan_cqe_ops, .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | @@ -1289,10 +1267,6 @@ static const struct of_device_id sdhci_arasan_of_match[] = { .compatible = "intel,keembay-sdhci-5.1-sdio", .data = &intel_keembay_sdio_data, }, - { - .compatible = "intel,thunderbay-sdhci-5.1", - .data = &sdhci_arasan_thunderbay_data, - }, /* Generic compatible below here */ { .compatible = "arasan,sdhci-8.9a", @@ -1723,8 +1697,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev) if (of_device_is_compatible(np, "intel,keembay-sdhci-5.1-emmc") || of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sd") || - of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio") || - of_device_is_compatible(np, "intel,thunderbay-sdhci-5.1")) { + of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio")) { sdhci_arasan_update_clockmultiplier(host, 0x0); sdhci_arasan_update_support64b(host, 0x0); -- cgit v1.2.3 From 8e8559ddfbb6289477d15f7a2f7db87ea3f75b57 Mon Sep 17 00:00:00 2001 From: "A, Rashmi" Date: Thu, 16 Mar 2023 17:35:47 +0530 Subject: dt-bindings: mmc: Remove bindings for Intel Thunder Bay SoC" Remove Thunder Bay specific code as the product got cancelled and there are no end customers or users. Signed-off-by: A, Rashmi Reviewed-by: Hunter, Adrian Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230316120549.21486-3-rashmi.a@intel.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/arasan,sdhci.yaml | 25 ---------------------- 1 file changed, 25 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml b/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml index 8296c34cfa00..e8e8b48dc5e5 100644 --- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml @@ -88,12 +88,6 @@ properties: description: For this device it is strongly suggested to include arasan,soc-ctl-syscon. - - items: - - const: intel,thunderbay-sdhci-5.1 # Intel Thunder Bay eMMC PHY - - const: arasan,sdhci-5.1 - description: - For this device it is strongly suggested to include - clock-output-names and '#clock-cells'. reg: maxItems: 1 @@ -309,22 +303,3 @@ examples: <&scmi_clk KEEM_BAY_PSS_SD0>; arasan,soc-ctl-syscon = <&sd0_phy_syscon>; }; - - - | - #define EMMC_XIN_CLK - #define EMMC_AXI_CLK - #define TBH_PSS_EMMC_RST_N - mmc@80420000 { - compatible = "intel,thunderbay-sdhci-5.1", "arasan,sdhci-5.1"; - interrupts = ; - reg = <0x80420000 0x400>; - clocks = <&scmi_clk EMMC_XIN_CLK>, - <&scmi_clk EMMC_AXI_CLK>; - clock-names = "clk_xin", "clk_ahb"; - phys = <&emmc_phy>; - phy-names = "phy_arasan"; - assigned-clocks = <&scmi_clk EMMC_XIN_CLK>; - clock-output-names = "emmc_cardclock"; - resets = <&rst_pss1 TBH_PSS_EMMC_RST_N>; - #clock-cells = <0x0>; - }; -- cgit v1.2.3 From cc47d2cf6795c545a257a2e5eda17a00a59da199 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 19 Mar 2023 12:47:44 -0400 Subject: mmc: sdricoh_cs: remove unused sdricoh_readw function clang with W=1 reports drivers/mmc/host/sdricoh_cs.c:104:28: error: unused function 'sdricoh_readw' [-Werror,-Wunused-function] static inline unsigned int sdricoh_readw(struct sdricoh_host *host, ^ This function is not used, so remove it. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20230319164744.1707169-1-trix@redhat.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdricoh_cs.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c index 76a8cd3a186f..57b8c1a96756 100644 --- a/drivers/mmc/host/sdricoh_cs.c +++ b/drivers/mmc/host/sdricoh_cs.c @@ -101,14 +101,6 @@ static inline void sdricoh_writel(struct sdricoh_host *host, unsigned int reg, } -static inline unsigned int sdricoh_readw(struct sdricoh_host *host, - unsigned int reg) -{ - unsigned int value = readw(host->iobase + reg); - dev_vdbg(host->dev, "rb %x 0x%x\n", reg, value); - return value; -} - static inline void sdricoh_writew(struct sdricoh_host *host, unsigned int reg, unsigned short value) { -- cgit v1.2.3 From a72b7bbc700a47672ff95ce41a6d59b3d4dbb79b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Sun, 19 Mar 2023 12:30:06 -0500 Subject: dt-bindings: mmc: fujitsu: Add Socionext Synquacer Add support for Socionext Synquacer SDHCI. This binding has been in use for some time. The interrupts were not documented. The driver only uses the first interrupt, but the DT and example have 2 interrupts. The 2nd one is unknown. "dma-coherent" was also not documented, but is used on Synquacer. Signed-off-by: Rob Herring Reviewed-by: Krzysztof Kozlowski Reviewed-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/20230319173006.30455-1-robh@kernel.org Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml b/Documentation/devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml index 73d747e917f3..430b62899397 100644 --- a/Documentation/devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml +++ b/Documentation/devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml @@ -14,9 +14,13 @@ allOf: properties: compatible: - enum: - - fujitsu,mb86s70-sdhci-3.0 - - socionext,f-sdh30-e51-mmc + oneOf: + - items: + - const: socionext,synquacer-sdhci + - const: fujitsu,mb86s70-sdhci-3.0 + - enum: + - fujitsu,mb86s70-sdhci-3.0 + - socionext,f-sdh30-e51-mmc reg: maxItems: 1 @@ -29,6 +33,11 @@ properties: - const: iface - const: core + dma-coherent: true + + interrupts: + maxItems: 2 + resets: maxItems: 1 -- cgit v1.2.3 From f6ca8f906bc3073840d832484865757392be2819 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Tue, 21 Mar 2023 19:01:01 +0100 Subject: mmc: core: Log about empty non-removable slots Failing to detect a non-removable card shouldn't happen. Let's log a message about it to inform that we have problem that ought to be fixed. Signed-off-by: Marc Gonzalez Link: https://lore.kernel.org/r/d2444591-c91b-a94d-71e2-9dedc3b6c514@free.fr Signed-off-by: Ulf Hansson --- drivers/mmc/core/core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 426c7f66b349..3d3e0ca52614 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2257,6 +2257,11 @@ void mmc_rescan(struct work_struct *work) break; } + /* A non-removable card should have been detected by now. */ + if (!mmc_card_is_removable(host) && !host->bus_ops) + pr_info("%s: Failed to initialize a non-removable card", + mmc_hostname(host)); + /* * Ignore the command timeout errors observed during * the card init as those are excepted. -- cgit v1.2.3 From 0dd8316037a2a6d85b2be208bef9991de7b42170 Mon Sep 17 00:00:00 2001 From: Georgii Kruglov Date: Tue, 21 Mar 2023 23:37:15 +0300 Subject: mmc: sdhci-of-esdhc: fix quirk to ignore command inhibit for data If spec_reg is equal to 'SDHCI_PRESENT_STATE', esdhc_readl_fixup() fixes up register value and returns it immediately. As a result, the further block (spec_reg == SDHCI_PRESENT_STATE) &&(esdhc->quirk_ignore_data_inhibit == true), is never executed. The patch merges the second block into the first one. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 1f1929f3f2fa ("mmc: sdhci-of-esdhc: add quirk to ignore command inhibit for data") Signed-off-by: Georgii Kruglov Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230321203715.3975-1-georgy.kruglov@yandex.ru Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-esdhc.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 4712adac7f7c..48ca1cf15b19 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -133,6 +133,7 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host, return ret; } } + /* * The DAT[3:0] line signal levels and the CMD line signal level are * not compatible with standard SDHC register. The line signal levels @@ -144,6 +145,16 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host, ret = value & 0x000fffff; ret |= (value >> 4) & SDHCI_DATA_LVL_MASK; ret |= (value << 1) & SDHCI_CMD_LVL; + + /* + * Some controllers have unreliable Data Line Active + * bit for commands with busy signal. This affects + * Command Inhibit (data) bit. Just ignore it since + * MMC core driver has already polled card status + * with CMD13 after any command with busy siganl. + */ + if (esdhc->quirk_ignore_data_inhibit) + ret &= ~SDHCI_DATA_INHIBIT; return ret; } @@ -158,19 +169,6 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host, return ret; } - /* - * Some controllers have unreliable Data Line Active - * bit for commands with busy signal. This affects - * Command Inhibit (data) bit. Just ignore it since - * MMC core driver has already polled card status - * with CMD13 after any command with busy siganl. - */ - if ((spec_reg == SDHCI_PRESENT_STATE) && - (esdhc->quirk_ignore_data_inhibit == true)) { - ret = value & ~SDHCI_DATA_INHIBIT; - return ret; - } - ret = value; return ret; } -- cgit v1.2.3 From 4fddc647fe5a77809eaa0be1f489694efb0590af Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 28 Mar 2023 14:07:40 +0800 Subject: dt-bindings: mmc: fsl-imx-esdhc: ref sdhci-common.yaml Since the esdhc controller is sdhci compatible, the fsl-imx-esdhc.yaml should ref sdhci-common.yaml to use 'sdhci-caps-mask' property. Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20230328060740.1984239-1-peng.fan@oss.nxp.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml index 7f721fbfb009..fbfd822b9270 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml @@ -10,7 +10,7 @@ maintainers: - Shawn Guo allOf: - - $ref: mmc-controller.yaml + - $ref: sdhci-common.yaml# description: | The Enhanced Secure Digital Host Controller on Freescale i.MX family -- cgit v1.2.3 From 5762451d647cda7aa12c2c001330802f03a161a9 Mon Sep 17 00:00:00 2001 From: Yu Zhe Date: Tue, 28 Mar 2023 11:10:49 +0800 Subject: mmc: core: remove unnecessary (void*) conversions Pointer variables of void * type do not require type cast. Signed-off-by: Yu Zhe Link: https://lore.kernel.org/r/20230328031049.22749-1-yuzhe@nfschina.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/debugfs.c | 2 +- drivers/mmc/core/mmc_test.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index fe6808771bc7..2c97b94aab23 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -246,7 +246,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(mmc_err_state, mmc_err_state_get, NULL, "%llu\n"); static int mmc_err_stats_show(struct seq_file *file, void *data) { - struct mmc_host *host = (struct mmc_host *)file->private; + struct mmc_host *host = file->private; const char *desc[MMC_ERR_MAX] = { [MMC_ERR_CMD_TIMEOUT] = "Command Timeout Occurred", [MMC_ERR_CMD_CRC] = "Command CRC Errors Occurred", diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c index 156d34b2ed4d..0f6a563103fd 100644 --- a/drivers/mmc/core/mmc_test.c +++ b/drivers/mmc/core/mmc_test.c @@ -3045,7 +3045,7 @@ static LIST_HEAD(mmc_test_file_test); static int mtf_test_show(struct seq_file *sf, void *data) { - struct mmc_card *card = (struct mmc_card *)sf->private; + struct mmc_card *card = sf->private; struct mmc_test_general_result *gr; mutex_lock(&mmc_test_lock); @@ -3079,8 +3079,8 @@ static int mtf_test_open(struct inode *inode, struct file *file) static ssize_t mtf_test_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { - struct seq_file *sf = (struct seq_file *)file->private_data; - struct mmc_card *card = (struct mmc_card *)sf->private; + struct seq_file *sf = file->private_data; + struct mmc_card *card = sf->private; struct mmc_test_card *test; long testcase; int ret; -- cgit v1.2.3 From 9d2e77ff2bd3b94c930a1f5b75abada7e196fa6d Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Fri, 31 Mar 2023 15:46:18 +0530 Subject: mmc: sdhci_am654: Add support for PM suspend/resume Add support for suspend/resume and pm_runtime resume/suspend. Signed-off-by: Aswath Govindraju Signed-off-by: Georgi Vlaev Signed-off-by: Vignesh Raghavendra Link: https://lore.kernel.org/r/20230331101619.4117312-1-vigneshr@ti.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 147 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 131 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 672d37ea98d0..7cdf0f54e3a5 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -85,6 +85,7 @@ #define DRIVER_STRENGTH_40_OHM 0x4 #define CLOCK_TOO_SLOW_HZ 50000000 +#define SDHCI_AM654_AUTOSUSPEND_DELAY -1 /* Command Queue Host Controller Interface Base address */ #define SDHCI_AM654_CQE_BASE_ADDR 0x200 @@ -808,16 +809,10 @@ static int sdhci_am654_probe(struct platform_device *pdev) pltfm_host->clk = clk_xin; - /* Clocks are enabled using pm_runtime */ - pm_runtime_enable(dev); - ret = pm_runtime_resume_and_get(dev); - if (ret) - goto pm_runtime_disable; - base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(base)) { ret = PTR_ERR(base); - goto pm_runtime_put; + goto err_pltfm_free; } sdhci_am654->base = devm_regmap_init_mmio(dev, base, @@ -825,31 +820,47 @@ static int sdhci_am654_probe(struct platform_device *pdev) if (IS_ERR(sdhci_am654->base)) { dev_err(dev, "Failed to initialize regmap\n"); ret = PTR_ERR(sdhci_am654->base); - goto pm_runtime_put; + goto err_pltfm_free; } ret = sdhci_am654_get_of_property(pdev, sdhci_am654); if (ret) - goto pm_runtime_put; + goto err_pltfm_free; ret = mmc_of_parse(host->mmc); if (ret) { dev_err_probe(dev, ret, "parsing dt failed\n"); - goto pm_runtime_put; + goto err_pltfm_free; } host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; + pm_runtime_get_noresume(dev); + ret = pm_runtime_set_active(dev); + if (ret) + goto pm_put; + pm_runtime_enable(dev); + ret = clk_prepare_enable(pltfm_host->clk); + if (ret) + goto pm_disable; + ret = sdhci_am654_init(host); if (ret) - goto pm_runtime_put; + goto clk_disable; + /* Setting up autosuspend */ + pm_runtime_set_autosuspend_delay(dev, SDHCI_AM654_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); return 0; -pm_runtime_put: - pm_runtime_put_sync(dev); -pm_runtime_disable: +clk_disable: + clk_disable_unprepare(pltfm_host->clk); +pm_disable: pm_runtime_disable(dev); +pm_put: + pm_runtime_put_noidle(dev); err_pltfm_free: sdhci_pltfm_free(pdev); return ret; @@ -858,23 +869,127 @@ err_pltfm_free: static int sdhci_am654_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); int ret; - sdhci_remove_host(host, true); - ret = pm_runtime_put_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) return ret; + sdhci_remove_host(host, true); + clk_disable_unprepare(pltfm_host->clk); pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); sdhci_pltfm_free(pdev); + return 0; +} + +#ifdef CONFIG_PM +static int sdhci_am654_restore(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + u32 ctl_cfg_2 = 0; + u32 val; + int ret; + + if (sdhci_am654->flags & DLL_CALIB) { + regmap_read(sdhci_am654->base, PHY_STAT1, &val); + if (~val & CALDONE_MASK) { + /* Calibrate IO lines */ + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, + PDB_MASK, PDB_MASK); + ret = regmap_read_poll_timeout(sdhci_am654->base, + PHY_STAT1, val, + val & CALDONE_MASK, + 1, 20); + if (ret) + return ret; + } + } + + /* Enable pins by setting IO mux to 0 */ + if (sdhci_am654->flags & IOMUX_PRESENT) + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, + IOMUX_ENABLE_MASK, 0); + /* Set slot type based on SD or eMMC */ + if (host->mmc->caps & MMC_CAP_NONREMOVABLE) + ctl_cfg_2 = SLOTTYPE_EMBEDDED; + + regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK, + ctl_cfg_2); + + regmap_read(sdhci_am654->base, CTL_CFG_3, &val); + if (~val & TUNINGFORSDR50_MASK) + /* Enable tuning for SDR50 */ + regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK, + TUNINGFORSDR50_MASK); + + return 0; +} + +static int sdhci_am654_runtime_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + int ret; + + if (host->tuning_mode != SDHCI_TUNING_MODE_3) + mmc_retune_needed(host->mmc); + + ret = cqhci_suspend(host->mmc); + if (ret) + return ret; + + ret = sdhci_runtime_suspend_host(host); + if (ret) + return ret; + + /* disable the clock */ + clk_disable_unprepare(pltfm_host->clk); return 0; } +static int sdhci_am654_runtime_resume(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + int ret; + + /* Enable the clock */ + ret = clk_prepare_enable(pltfm_host->clk); + if (ret) + return ret; + + ret = sdhci_am654_restore(host); + if (ret) + return ret; + + ret = sdhci_runtime_resume_host(host, 0); + if (ret) + return ret; + + ret = cqhci_resume(host->mmc); + if (ret) + return ret; + + return 0; +} +#endif + +static const struct dev_pm_ops sdhci_am654_dev_pm_ops = { + SET_RUNTIME_PM_OPS(sdhci_am654_runtime_suspend, + sdhci_am654_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + static struct platform_driver sdhci_am654_driver = { .driver = { .name = "sdhci-am654", .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .pm = &sdhci_am654_dev_pm_ops, .of_match_table = sdhci_am654_of_match, }, .probe = sdhci_am654_probe, -- cgit v1.2.3 From 8aa7206411fce5a2c6e2643df5c91e6d3e583ba8 Mon Sep 17 00:00:00 2001 From: Sai Krishna Potthuri Date: Mon, 3 Apr 2023 15:55:49 +0530 Subject: dt-bindings: mmc: arasan,sdci: Add Xilinx Versal Net compatible Add Xilinx Versal Net compatible to support eMMC 5.1 PHY. Signed-off-by: Sai Krishna Potthuri Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230403102551.3763054-2-sai.krishna.potthuri@amd.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml b/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml index e8e8b48dc5e5..a6c19a6cc99e 100644 --- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml @@ -27,6 +27,7 @@ allOf: enum: - xlnx,zynqmp-8.9a - xlnx,versal-8.9a + - xlnx,versal-net-emmc then: properties: clock-output-names: @@ -62,6 +63,10 @@ properties: description: For this device it is strongly suggested to include clock-output-names and '#clock-cells'. + - const: xlnx,versal-net-emmc # Versal Net eMMC PHY + description: + For this device it is strongly suggested to include + clock-output-names and '#clock-cells'. - items: - const: intel,lgm-sdhci-5.1-emmc # Intel LGM eMMC PHY - const: arasan,sdhci-5.1 -- cgit v1.2.3 From b095f4f52b1a8e926f0f39b3c01a8bab6a667438 Mon Sep 17 00:00:00 2001 From: Swati Agarwal Date: Mon, 3 Apr 2023 15:55:50 +0530 Subject: mmc: sdhci-of-arasan: Add support for eMMC5.1 on Xilinx Versal Net platform Add support for eMMC5.1 on Xilinx Versal Net platform - Add new compatible string(xlnx,versal-net-emmc). - Add support for PHY which is part of Host Controller register space. - Add DLL and Delay Chain mode support and corresponding tap delays for all eMMC modes. - Add Strobe select tap for HS400 mode. Signed-off-by: Swati Agarwal Co-developed-by: Sai Krishna Potthuri Signed-off-by: Sai Krishna Potthuri Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230403102551.3763054-3-sai.krishna.potthuri@amd.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 235 +++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 72f0595c57d3..20aa08484315 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -41,11 +41,41 @@ #define VENDOR_ENHANCED_STROBE BIT(0) #define PHY_CLK_TOO_SLOW_HZ 400000 +#define MIN_PHY_CLK_HZ 50000000 #define SDHCI_ITAPDLY_CHGWIN 0x200 #define SDHCI_ITAPDLY_ENABLE 0x100 #define SDHCI_OTAPDLY_ENABLE 0x40 +#define PHY_CTRL_REG1 0x270 +#define PHY_CTRL_ITAPDLY_ENA_MASK BIT(0) +#define PHY_CTRL_ITAPDLY_SEL_MASK GENMASK(5, 1) +#define PHY_CTRL_ITAPDLY_SEL_SHIFT 1 +#define PHY_CTRL_ITAP_CHG_WIN_MASK BIT(6) +#define PHY_CTRL_OTAPDLY_ENA_MASK BIT(8) +#define PHY_CTRL_OTAPDLY_SEL_MASK GENMASK(15, 12) +#define PHY_CTRL_OTAPDLY_SEL_SHIFT 12 +#define PHY_CTRL_STRB_SEL_MASK GENMASK(23, 16) +#define PHY_CTRL_STRB_SEL_SHIFT 16 +#define PHY_CTRL_TEST_CTRL_MASK GENMASK(31, 24) + +#define PHY_CTRL_REG2 0x274 +#define PHY_CTRL_EN_DLL_MASK BIT(0) +#define PHY_CTRL_DLL_RDY_MASK BIT(1) +#define PHY_CTRL_FREQ_SEL_MASK GENMASK(6, 4) +#define PHY_CTRL_FREQ_SEL_SHIFT 4 +#define PHY_CTRL_SEL_DLY_TX_MASK BIT(16) +#define PHY_CTRL_SEL_DLY_RX_MASK BIT(17) +#define FREQSEL_200M_170M 0x0 +#define FREQSEL_170M_140M 0x1 +#define FREQSEL_140M_110M 0x2 +#define FREQSEL_110M_80M 0x3 +#define FREQSEL_80M_50M 0x4 +#define FREQSEL_275M_250M 0x5 +#define FREQSEL_250M_225M 0x6 +#define FREQSEL_225M_200M 0x7 +#define PHY_DLL_TIMEOUT_MS 100 + /* Default settings for ZynqMP Clock Phases */ #define ZYNQMP_ICLK_PHASE {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0} #define ZYNQMP_OCLK_PHASE {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0} @@ -53,6 +83,11 @@ #define VERSAL_ICLK_PHASE {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0} #define VERSAL_OCLK_PHASE {0, 60, 48, 0, 48, 72, 90, 36, 60, 90, 0} +#define VERSAL_NET_EMMC_ICLK_PHASE {0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0} +#define VERSAL_NET_EMMC_OCLK_PHASE {0, 113, 0, 0, 0, 0, 0, 0, 113, 79, 45} + +#define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL 0X77 + /* * On some SoCs the syscon area has a feature where the upper 16-bits of * each 32-bit register act as a write mask for the lower 16-bits. This allows @@ -135,6 +170,7 @@ struct sdhci_arasan_clk_data { * @clk_ahb: Pointer to the AHB clock * @phy: Pointer to the generic phy * @is_phy_on: True if the PHY is on; false if not. + * @internal_phy_reg: True if the PHY is within the Host controller. * @has_cqe: True if controller has command queuing engine. * @clk_data: Struct for the Arasan Controller Clock Data. * @clk_ops: Struct for the Arasan Controller Clock Operations. @@ -147,6 +183,7 @@ struct sdhci_arasan_data { struct clk *clk_ahb; struct phy *phy; bool is_phy_on; + bool internal_phy_reg; bool has_cqe; struct sdhci_arasan_clk_data clk_data; @@ -200,6 +237,61 @@ static const struct sdhci_arasan_soc_ctl_map intel_keembay_soc_ctl_map = { .hiword_update = false, }; +static void sdhci_arasan_phy_set_delaychain(struct sdhci_host *host, bool enable) +{ + u32 reg; + + reg = readl(host->ioaddr + PHY_CTRL_REG2); + if (enable) + reg |= (PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK); + else + reg &= ~(PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK); + + writel(reg, host->ioaddr + PHY_CTRL_REG2); +} + +static int sdhci_arasan_phy_set_dll(struct sdhci_host *host, bool enable) +{ + u32 reg; + + reg = readl(host->ioaddr + PHY_CTRL_REG2); + if (enable) + reg |= PHY_CTRL_EN_DLL_MASK; + else + reg &= ~PHY_CTRL_EN_DLL_MASK; + + writel(reg, host->ioaddr + PHY_CTRL_REG2); + + if (!enable) + return 0; + + return readl_relaxed_poll_timeout(host->ioaddr + PHY_CTRL_REG2, reg, + (reg & PHY_CTRL_DLL_RDY_MASK), 10, + 1000 * PHY_DLL_TIMEOUT_MS); +} + +static void sdhci_arasan_phy_dll_set_freq(struct sdhci_host *host, int clock) +{ + u32 reg, freq_sel, freq; + + freq = DIV_ROUND_CLOSEST(clock, 1000000); + if (freq <= 200 && freq > 170) + freq_sel = FREQSEL_200M_170M; + else if (freq <= 170 && freq > 140) + freq_sel = FREQSEL_170M_140M; + else if (freq <= 140 && freq > 110) + freq_sel = FREQSEL_140M_110M; + else if (freq <= 110 && freq > 80) + freq_sel = FREQSEL_110M_80M; + else + freq_sel = FREQSEL_80M_50M; + + reg = readl(host->ioaddr + PHY_CTRL_REG2); + reg &= ~PHY_CTRL_FREQ_SEL_MASK; + reg |= (freq_sel << PHY_CTRL_FREQ_SEL_SHIFT); + writel(reg, host->ioaddr + PHY_CTRL_REG2); +} + /** * sdhci_arasan_syscon_write - Write to a field in soc_ctl registers * @@ -317,8 +409,21 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock) if (clk_data->set_clk_delays) clk_data->set_clk_delays(host); + if (sdhci_arasan->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) { + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + sdhci_arasan_phy_set_dll(host, 0); + sdhci_arasan_phy_set_delaychain(host, 0); + sdhci_arasan_phy_dll_set_freq(host, clock); + } else if (sdhci_arasan->internal_phy_reg) { + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + sdhci_arasan_phy_set_delaychain(host, 1); + } + sdhci_set_clock(host, clock); + if (sdhci_arasan->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) + sdhci_arasan_phy_set_dll(host, 1); + if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE) /* * Some controllers immediately report SDHCI_CLOCK_INT_STABLE @@ -881,6 +986,101 @@ static const struct clk_ops versal_sampleclk_ops = { .set_phase = sdhci_versal_sampleclk_set_phase, }; +static int sdhci_versal_net_emmc_sdcardclk_set_phase(struct clk_hw *hw, int degrees) +{ + struct sdhci_arasan_clk_data *clk_data = + container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw); + struct sdhci_arasan_data *sdhci_arasan = + container_of(clk_data, struct sdhci_arasan_data, clk_data); + struct sdhci_host *host = sdhci_arasan->host; + u8 tap_delay, tap_max = 0; + + switch (host->timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_MMC_DDR52: + tap_max = 16; + break; + case MMC_TIMING_MMC_HS200: + case MMC_TIMING_MMC_HS400: + /* For 200MHz clock, 32 Taps are available */ + tap_max = 32; + break; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + /* Set the Clock Phase */ + if (tap_delay) { + u32 regval; + + regval = sdhci_readl(host, PHY_CTRL_REG1); + regval |= PHY_CTRL_OTAPDLY_ENA_MASK; + sdhci_writel(host, regval, PHY_CTRL_REG1); + regval &= ~PHY_CTRL_OTAPDLY_SEL_MASK; + regval |= tap_delay << PHY_CTRL_OTAPDLY_SEL_SHIFT; + sdhci_writel(host, regval, PHY_CTRL_REG1); + } + + return 0; +} + +static const struct clk_ops versal_net_sdcardclk_ops = { + .recalc_rate = sdhci_arasan_sdcardclk_recalc_rate, + .set_phase = sdhci_versal_net_emmc_sdcardclk_set_phase, +}; + +static int sdhci_versal_net_emmc_sampleclk_set_phase(struct clk_hw *hw, int degrees) +{ + struct sdhci_arasan_clk_data *clk_data = + container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw); + struct sdhci_arasan_data *sdhci_arasan = + container_of(clk_data, struct sdhci_arasan_data, clk_data); + struct sdhci_host *host = sdhci_arasan->host; + u8 tap_delay, tap_max = 0; + u32 regval; + + switch (host->timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_MMC_DDR52: + tap_max = 32; + break; + case MMC_TIMING_MMC_HS400: + /* Strobe select tap point for strb90 and strb180 */ + regval = sdhci_readl(host, PHY_CTRL_REG1); + regval &= ~PHY_CTRL_STRB_SEL_MASK; + regval |= VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL << PHY_CTRL_STRB_SEL_SHIFT; + sdhci_writel(host, regval, PHY_CTRL_REG1); + break; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + /* Set the Clock Phase */ + if (tap_delay) { + regval = sdhci_readl(host, PHY_CTRL_REG1); + regval |= PHY_CTRL_ITAP_CHG_WIN_MASK; + sdhci_writel(host, regval, PHY_CTRL_REG1); + regval |= PHY_CTRL_ITAPDLY_ENA_MASK; + sdhci_writel(host, regval, PHY_CTRL_REG1); + regval &= ~PHY_CTRL_ITAPDLY_SEL_MASK; + regval |= tap_delay << PHY_CTRL_ITAPDLY_SEL_SHIFT; + sdhci_writel(host, regval, PHY_CTRL_REG1); + regval &= ~PHY_CTRL_ITAP_CHG_WIN_MASK; + sdhci_writel(host, regval, PHY_CTRL_REG1); + } + + return 0; +} + +static const struct clk_ops versal_net_sampleclk_ops = { + .recalc_rate = sdhci_arasan_sampleclk_recalc_rate, + .set_phase = sdhci_versal_net_emmc_sampleclk_set_phase, +}; + static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 deviceid) { u16 clk; @@ -1091,7 +1291,17 @@ static void arasan_dt_parse_clk_phases(struct device *dev, clk_data->clk_phase_out[i] = versal_oclk_phase[i]; } } + if (of_device_is_compatible(dev->of_node, "xlnx,versal-net-emmc")) { + u32 versal_net_iclk_phase[MMC_TIMING_MMC_HS400 + 1] = + VERSAL_NET_EMMC_ICLK_PHASE; + u32 versal_net_oclk_phase[MMC_TIMING_MMC_HS400 + 1] = + VERSAL_NET_EMMC_OCLK_PHASE; + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { + clk_data->clk_phase_in[i] = versal_net_iclk_phase[i]; + clk_data->clk_phase_out[i] = versal_net_oclk_phase[i]; + } + } arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_LEGACY, "clk-phase-legacy"); arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS, @@ -1203,6 +1413,14 @@ static const struct sdhci_pltfm_data sdhci_arasan_zynqmp_pdata = { SDHCI_QUIRK2_STOP_WITH_TC, }; +static const struct sdhci_pltfm_data sdhci_arasan_versal_net_pdata = { + .ops = &sdhci_arasan_ops, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | + SDHCI_QUIRK2_STOP_WITH_TC | + SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, +}; + static const struct sdhci_arasan_clk_ops zynqmp_clk_ops = { .sdcardclk_ops = &zynqmp_sdcardclk_ops, .sampleclk_ops = &zynqmp_sampleclk_ops, @@ -1223,6 +1441,16 @@ static struct sdhci_arasan_of_data sdhci_arasan_versal_data = { .clk_ops = &versal_clk_ops, }; +static const struct sdhci_arasan_clk_ops versal_net_clk_ops = { + .sdcardclk_ops = &versal_net_sdcardclk_ops, + .sampleclk_ops = &versal_net_sampleclk_ops, +}; + +static struct sdhci_arasan_of_data sdhci_arasan_versal_net_data = { + .pdata = &sdhci_arasan_versal_net_pdata, + .clk_ops = &versal_net_clk_ops, +}; + static struct sdhci_arasan_of_data intel_keembay_emmc_data = { .soc_ctl_map = &intel_keembay_soc_ctl_map, .pdata = &sdhci_keembay_emmc_pdata, @@ -1288,6 +1516,10 @@ static const struct of_device_id sdhci_arasan_of_match[] = { .compatible = "xlnx,versal-8.9a", .data = &sdhci_arasan_versal_data, }, + { + .compatible = "xlnx,versal-net-emmc", + .data = &sdhci_arasan_versal_net_data, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match); @@ -1761,6 +1993,9 @@ static int sdhci_arasan_probe(struct platform_device *pdev) host->mmc->caps2 |= MMC_CAP2_CQE_DCMD; } + if (of_device_is_compatible(np, "xlnx,versal-net-emmc")) + sdhci_arasan->internal_phy_reg = true; + ret = sdhci_arasan_add_host(sdhci_arasan); if (ret) goto err_add_host; -- cgit v1.2.3 From 9fab93895fb6f4309b2e0a2e03a87da7d4dad643 Mon Sep 17 00:00:00 2001 From: Sai Krishna Potthuri Date: Mon, 3 Apr 2023 15:55:51 +0530 Subject: mmc: sdhci-of-arasan: Skip setting clock delay for 400KHz Clock delay settings are not defined for 400KHz, so add frequency check to skip calling the clock delay settings when frequency is <=400KHz. Signed-off-by: Sai Krishna Potthuri Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230403102551.3763054-4-sai.krishna.potthuri@amd.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 20aa08484315..294dd605fd2b 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -406,7 +406,7 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock) } /* Set the Input and Output Clock Phase Delays */ - if (clk_data->set_clk_delays) + if (clk_data->set_clk_delays && clock > PHY_CLK_TOO_SLOW_HZ) clk_data->set_clk_delays(host); if (sdhci_arasan->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) { -- cgit v1.2.3 From f695c5f952f28bf4ba74a7862ae20bae27568770 Mon Sep 17 00:00:00 2001 From: Bean Huo Date: Tue, 4 Apr 2023 00:17:54 +0200 Subject: mmc: core: Remove unused macro mmc_req_rel_wr There is no user for macro mmc_req_rel_wr, so delete it. Signed-off-by: Bean Huo Link: https://lore.kernel.org/r/20230403221754.16168-1-beanhuo@iokpp.de Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 672ab90c4b2d..00c33edb9fb9 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -76,8 +76,6 @@ MODULE_ALIAS("mmc:block"); #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) #define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8) -#define mmc_req_rel_wr(req) ((req->cmd_flags & REQ_FUA) && \ - (rq_data_dir(req) == WRITE)) static DEFINE_MUTEX(block_mutex); /* -- cgit v1.2.3 From 82e4726b00e9e9bf7bf2ce3cc19532fe084005a4 Mon Sep 17 00:00:00 2001 From: Brad Larson Date: Mon, 10 Apr 2023 11:45:13 -0700 Subject: dt-bindings: mmc: cdns: Add AMD Pensando Elba SoC AMD Pensando Elba ARM 64-bit SoC is integrated with this IP and explicitly controls byte-lane enables. Signed-off-by: Brad Larson Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230410184526.15990-3-blarson@amd.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/cdns,sdhci.yaml | 27 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml b/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml index adacd0535c14..6c40611405a0 100644 --- a/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/cdns,sdhci.yaml @@ -9,19 +9,18 @@ title: Cadence SD/SDIO/eMMC Host Controller (SD4HC) maintainers: - Masahiro Yamada -allOf: - - $ref: mmc-controller.yaml - properties: compatible: items: - enum: + - amd,pensando-elba-sd4hc - microchip,mpfs-sd4hc - socionext,uniphier-sd4hc - const: cdns,sd4hc reg: - maxItems: 1 + minItems: 1 + maxItems: 2 interrupts: maxItems: 1 @@ -120,6 +119,26 @@ required: - interrupts - clocks +allOf: + - $ref: mmc-controller.yaml + - if: + properties: + compatible: + contains: + const: amd,pensando-elba-sd4hc + then: + properties: + reg: + items: + - description: Host controller registers + - description: Elba byte-lane enable register for writes + required: + - resets + else: + properties: + reg: + maxItems: 1 + unevaluatedProperties: false examples: -- cgit v1.2.3 From d3e32f8478912568cad7472db3980635bf8766e3 Mon Sep 17 00:00:00 2001 From: Brad Larson Date: Mon, 10 Apr 2023 11:45:22 -0700 Subject: mmc: sdhci-cadence: Enable device specific override of writel() SoCs with device specific Cadence implementation, such as setting byte-enables before the write, need to override writel(). Add a callback where the default is writel() for all existing chips. Signed-off-by: Brad Larson Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230410184526.15990-12-blarson@amd.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-cadence.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index 6f2de54a5987..708d4297f241 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -67,6 +67,7 @@ struct sdhci_cdns_phy_param { struct sdhci_cdns_priv { void __iomem *hrs_addr; bool enhanced_strobe; + void (*priv_writel)(struct sdhci_cdns_priv *priv, u32 val, void __iomem *reg); unsigned int nr_phy_params; struct sdhci_cdns_phy_param phy_params[]; }; @@ -90,6 +91,12 @@ static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = { { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, }, }; +static inline void cdns_writel(struct sdhci_cdns_priv *priv, u32 val, + void __iomem *reg) +{ + writel(val, reg); +} + static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv, u8 addr, u8 data) { @@ -104,17 +111,17 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv, tmp = FIELD_PREP(SDHCI_CDNS_HRS04_WDATA, data) | FIELD_PREP(SDHCI_CDNS_HRS04_ADDR, addr); - writel(tmp, reg); + priv->priv_writel(priv, tmp, reg); tmp |= SDHCI_CDNS_HRS04_WR; - writel(tmp, reg); + priv->priv_writel(priv, tmp, reg); ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10); if (ret) return ret; tmp &= ~SDHCI_CDNS_HRS04_WR; - writel(tmp, reg); + priv->priv_writel(priv, tmp, reg); ret = readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS04_ACK), 0, 10); @@ -191,7 +198,7 @@ static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_priv *priv, u32 mode) tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06); tmp &= ~SDHCI_CDNS_HRS06_MODE; tmp |= FIELD_PREP(SDHCI_CDNS_HRS06_MODE, mode); - writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06); + priv->priv_writel(priv, tmp, priv->hrs_addr + SDHCI_CDNS_HRS06); } static u32 sdhci_cdns_get_emmc_mode(struct sdhci_cdns_priv *priv) @@ -223,7 +230,7 @@ static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val) */ for (i = 0; i < 2; i++) { tmp |= SDHCI_CDNS_HRS06_TUNE_UP; - writel(tmp, reg); + priv->priv_writel(priv, tmp, reg); ret = readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS06_TUNE_UP), @@ -386,6 +393,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev) priv->nr_phy_params = nr_phy_params; priv->hrs_addr = host->ioaddr; priv->enhanced_strobe = false; + priv->priv_writel = cdns_writel; host->ioaddr += SDHCI_CDNS_SRS_BASE; host->mmc_host_ops.hs400_enhanced_strobe = sdhci_cdns_hs400_enhanced_strobe; -- cgit v1.2.3 From e095b78ef2db903fefaf148ee14dcb92ebd1af87 Mon Sep 17 00:00:00 2001 From: Brad Larson Date: Mon, 10 Apr 2023 11:45:23 -0700 Subject: mmc: sdhci-cadence: Support device specific init during probe Move struct sdhci_pltfm_data under new struct sdhci_cdns_drv_data. Add an init() into sdhci_cdns_drv_data for platform specific device initialization in the device probe which is not used for existing devices. Signed-off-by: Brad Larson Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230410184526.15990-13-blarson@amd.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-cadence.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index 708d4297f241..c528a25f48b8 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -77,6 +77,11 @@ struct sdhci_cdns_phy_cfg { u8 addr; }; +struct sdhci_cdns_drv_data { + int (*init)(struct platform_device *pdev); + const struct sdhci_pltfm_data pltfm_data; +}; + static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = { { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, }, { "cdns,phy-input-delay-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, }, @@ -325,13 +330,17 @@ static const struct sdhci_ops sdhci_cdns_ops = { .set_uhs_signaling = sdhci_cdns_set_uhs_signaling, }; -static const struct sdhci_pltfm_data sdhci_cdns_uniphier_pltfm_data = { - .ops = &sdhci_cdns_ops, - .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, +static const struct sdhci_cdns_drv_data sdhci_cdns_uniphier_drv_data = { + .pltfm_data = { + .ops = &sdhci_cdns_ops, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, + }, }; -static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = { - .ops = &sdhci_cdns_ops, +static const struct sdhci_cdns_drv_data sdhci_cdns_drv_data = { + .pltfm_data = { + .ops = &sdhci_cdns_ops, + }, }; static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc, @@ -357,7 +366,7 @@ static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc, static int sdhci_cdns_probe(struct platform_device *pdev) { struct sdhci_host *host; - const struct sdhci_pltfm_data *data; + const struct sdhci_cdns_drv_data *data; struct sdhci_pltfm_host *pltfm_host; struct sdhci_cdns_priv *priv; struct clk *clk; @@ -376,10 +385,10 @@ static int sdhci_cdns_probe(struct platform_device *pdev) data = of_device_get_match_data(dev); if (!data) - data = &sdhci_cdns_pltfm_data; + data = &sdhci_cdns_drv_data; nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node); - host = sdhci_pltfm_init(pdev, data, + host = sdhci_pltfm_init(pdev, &data->pltfm_data, struct_size(priv, phy_params, nr_phy_params)); if (IS_ERR(host)) { ret = PTR_ERR(host); @@ -397,6 +406,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev) host->ioaddr += SDHCI_CDNS_SRS_BASE; host->mmc_host_ops.hs400_enhanced_strobe = sdhci_cdns_hs400_enhanced_strobe; + if (data->init) { + ret = data->init(pdev); + if (ret) + goto free; + } sdhci_enable_v4_mode(host); __sdhci_read_caps(host, &version, NULL, NULL); @@ -461,7 +475,7 @@ static const struct dev_pm_ops sdhci_cdns_pm_ops = { static const struct of_device_id sdhci_cdns_match[] = { { .compatible = "socionext,uniphier-sd4hc", - .data = &sdhci_cdns_uniphier_pltfm_data, + .data = &sdhci_cdns_uniphier_drv_data, }, { .compatible = "cdns,sd4hc" }, { /* sentinel */ } -- cgit v1.2.3 From b5dbcf1f1d1a7349ca731c22dda7d429151956ac Mon Sep 17 00:00:00 2001 From: Brad Larson Date: Mon, 10 Apr 2023 11:45:24 -0700 Subject: mmc: sdhci-cadence: Add AMD Pensando Elba SoC support Add support for AMD Pensando Elba SoC which explicitly controls byte-lane enables on writes. Select MMC_SDHCI_IO_ACCESSORS for MMC_SDHCI_CADENCE which allows Elba SoC sdhci_elba_ops to overwrite the SDHCI IO memory accessors Signed-off-by: Brad Larson Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20230410184526.15990-14-blarson@amd.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 1 + drivers/mmc/host/sdhci-cadence.c | 98 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 4745fe217ade..9f793892123c 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -255,6 +255,7 @@ config MMC_SDHCI_CADENCE tristate "SDHCI support for the Cadence SD/SDIO/eMMC controller" depends on MMC_SDHCI_PLTFM depends on OF + select MMC_SDHCI_IO_ACCESSORS help This selects the Cadence SD/SDIO/eMMC driver. diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index c528a25f48b8..5d1e9cef74f5 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -66,6 +66,8 @@ struct sdhci_cdns_phy_param { struct sdhci_cdns_priv { void __iomem *hrs_addr; + void __iomem *ctl_addr; /* write control */ + spinlock_t wrlock; /* write lock */ bool enhanced_strobe; void (*priv_writel)(struct sdhci_cdns_priv *priv, u32 val, void __iomem *reg); unsigned int nr_phy_params; @@ -321,6 +323,91 @@ static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host, sdhci_set_uhs_signaling(host, timing); } +/* Elba control register bits [6:3] are byte-lane enables */ +#define ELBA_BYTE_ENABLE_MASK(x) ((x) << 3) + +/* + * The Pensando Elba SoC explicitly controls byte-lane enabling on writes + * which includes writes to the HRS registers. The write lock (wrlock) + * is used to ensure byte-lane enable, using write control (ctl_addr), + * occurs before the data write. + */ +static void elba_priv_writel(struct sdhci_cdns_priv *priv, u32 val, + void __iomem *reg) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->wrlock, flags); + writel(GENMASK(7, 3), priv->ctl_addr); + writel(val, reg); + spin_unlock_irqrestore(&priv->wrlock, flags); +} + +static void elba_write_l(struct sdhci_host *host, u32 val, int reg) +{ + elba_priv_writel(sdhci_cdns_priv(host), val, host->ioaddr + reg); +} + +static void elba_write_w(struct sdhci_host *host, u16 val, int reg) +{ + struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); + u32 shift = reg & GENMASK(1, 0); + unsigned long flags; + u32 byte_enables; + + byte_enables = GENMASK(1, 0) << shift; + spin_lock_irqsave(&priv->wrlock, flags); + writel(ELBA_BYTE_ENABLE_MASK(byte_enables), priv->ctl_addr); + writew(val, host->ioaddr + reg); + spin_unlock_irqrestore(&priv->wrlock, flags); +} + +static void elba_write_b(struct sdhci_host *host, u8 val, int reg) +{ + struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); + u32 shift = reg & GENMASK(1, 0); + unsigned long flags; + u32 byte_enables; + + byte_enables = BIT(0) << shift; + spin_lock_irqsave(&priv->wrlock, flags); + writel(ELBA_BYTE_ENABLE_MASK(byte_enables), priv->ctl_addr); + writeb(val, host->ioaddr + reg); + spin_unlock_irqrestore(&priv->wrlock, flags); +} + +static const struct sdhci_ops sdhci_elba_ops = { + .write_l = elba_write_l, + .write_w = elba_write_w, + .write_b = elba_write_b, + .set_clock = sdhci_set_clock, + .get_timeout_clock = sdhci_cdns_get_timeout_clock, + .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, + .set_uhs_signaling = sdhci_cdns_set_uhs_signaling, +}; + +static int elba_drv_init(struct platform_device *pdev) +{ + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); + void __iomem *ioaddr; + + host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA; + spin_lock_init(&priv->wrlock); + + /* Byte-lane control register */ + ioaddr = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(ioaddr)) + return PTR_ERR(ioaddr); + + priv->ctl_addr = ioaddr; + priv->priv_writel = elba_priv_writel; + writel(ELBA_BYTE_ENABLE_MASK(0xf), priv->ctl_addr); + + return 0; +} + static const struct sdhci_ops sdhci_cdns_ops = { .set_clock = sdhci_set_clock, .get_timeout_clock = sdhci_cdns_get_timeout_clock, @@ -337,6 +424,13 @@ static const struct sdhci_cdns_drv_data sdhci_cdns_uniphier_drv_data = { }, }; +static const struct sdhci_cdns_drv_data sdhci_elba_drv_data = { + .init = elba_drv_init, + .pltfm_data = { + .ops = &sdhci_elba_ops, + }, +}; + static const struct sdhci_cdns_drv_data sdhci_cdns_drv_data = { .pltfm_data = { .ops = &sdhci_cdns_ops, @@ -477,6 +571,10 @@ static const struct of_device_id sdhci_cdns_match[] = { .compatible = "socionext,uniphier-sd4hc", .data = &sdhci_cdns_uniphier_drv_data, }, + { + .compatible = "amd,pensando-elba-sd4hc", + .data = &sdhci_elba_drv_data, + }, { .compatible = "cdns,sd4hc" }, { /* sentinel */ } }; -- cgit v1.2.3 From aad53d4ee7569d82cbc8ee14dacf3b8011fe827a Mon Sep 17 00:00:00 2001 From: Brad Larson Date: Mon, 10 Apr 2023 11:45:25 -0700 Subject: mmc: sdhci-cadence: Support mmc hardware reset Add support for mmc hardware reset using a reset-controller that would need to be enabled in the device tree with a supporting driver. The default is disabled for all existing designs. Signed-off-by: Brad Larson Acked-by: Adrian Hunter Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20230410184526.15990-15-blarson@amd.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-cadence.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index 5d1e9cef74f5..b24aa27da50c 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "sdhci-pltfm.h" @@ -70,6 +71,7 @@ struct sdhci_cdns_priv { spinlock_t wrlock; /* write lock */ bool enhanced_strobe; void (*priv_writel)(struct sdhci_cdns_priv *priv, u32 val, void __iomem *reg); + struct reset_control *rst_hw; unsigned int nr_phy_params; struct sdhci_cdns_phy_param phy_params[]; }; @@ -457,6 +459,22 @@ static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc, SDHCI_CDNS_HRS06_MODE_MMC_HS400); } +static void sdhci_cdns_mmc_hw_reset(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host); + + dev_dbg(mmc_dev(host->mmc), "emmc hardware reset\n"); + + reset_control_assert(priv->rst_hw); + /* For eMMC, minimum is 1us but give it 3us for good measure */ + udelay(3); + + reset_control_deassert(priv->rst_hw); + /* For eMMC, minimum is 200us but give it 300us for good measure */ + usleep_range(300, 1000); +} + static int sdhci_cdns_probe(struct platform_device *pdev) { struct sdhci_host *host; @@ -520,6 +538,15 @@ static int sdhci_cdns_probe(struct platform_device *pdev) if (ret) goto free; + if (host->mmc->caps & MMC_CAP_HW_RESET) { + priv->rst_hw = devm_reset_control_get_optional_exclusive(dev, NULL); + if (IS_ERR(priv->rst_hw)) + return dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw), + "reset controller error\n"); + if (priv->rst_hw) + host->mmc_host_ops.card_hw_reset = sdhci_cdns_mmc_hw_reset; + } + ret = sdhci_add_host(host); if (ret) goto free; -- cgit v1.2.3 From 45f54c9c18582c9d3af14fceaf44f7346c01a123 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Wed, 12 Apr 2023 04:47:58 -0400 Subject: mmc: vub300: remove unreachable code The function sched_partition_show cannot execute return, delete the invalid code. Signed-off-by: Bo Liu Link: https://lore.kernel.org/r/20230412084758.2673-1-liubo03@inspur.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/vub300.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index 72f65f32abbc..e4c4bfac3763 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -1341,8 +1341,6 @@ static void __download_offload_pseudocode(struct vub300_mmc_host *vub300, return; } - return; - copy_error_message: strncpy(vub300->vub_name, "SDIO pseudocode download failed", sizeof(vub300->vub_name)); -- cgit v1.2.3 From 22a4455e75be443fb80784175bb70f40ba6d0c52 Mon Sep 17 00:00:00 2001 From: Sricharan Ramabadhran Date: Fri, 14 Apr 2023 15:59:25 +0530 Subject: dt-bindings: mmc: sdhci-msm: Document the IPQ5018 compatible Document the compatible for SDHCI on IPQ5018. Signed-off-by: Sricharan Ramabadhran Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/1681468167-11689-8-git-send-email-quic_srichara@quicinc.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index 7d4c5ca25e0d..4f2d9e8127dd 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -34,6 +34,7 @@ properties: - const: qcom,sdhci-msm-v4 # for sdcc versions less than 5.0 - items: - enum: + - qcom,ipq5018-sdhci - qcom,ipq5332-sdhci - qcom,ipq9574-sdhci - qcom,qcm2290-sdhci -- cgit v1.2.3