Lines Matching +full:no +full:- +full:mmc +full:- +full:hs400
1 // SPDX-License-Identifier: GPL-2.0
13 #include <linux/dma-mapping.h>
23 #include "sdhci-pltfm.h"
39 /* Tuning and auto-tuning fields in AT_CTRL_R control register */
49 #define AT_CTRL_PRE_CHANGE_DLY 0x1 /* 2-cycle latency */
51 #define AT_CTRL_POST_CHANGE_DLY 0x3 /* 4-cycle latency */
126 #define PHY_PAD_TXSLEW_CTRL_P 0x3 /* Slew control for P-Type pad TX */
128 #define PHY_PAD_TXSLEW_CTRL_N 0x3 /* Slew control for N-Type pad TX */
138 #define PHY_SDCLKDL_DC_HS400 0x18 /* delay code for HS400 mode */
168 ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
205 offset = addr & (SZ_128M - 1); in dwcmshc_adma_write_desc()
206 tmplen = SZ_128M - offset; in dwcmshc_adma_write_desc()
210 len -= tmplen; in dwcmshc_adma_write_desc()
218 if (pltfm_host->clk) in dwcmshc_get_max_clock()
221 return pltfm_host->clock; in dwcmshc_get_max_clock()
228 return clk_round_rate(pltfm_host->clk, ULONG_MAX); in rk35xx_get_max_clock()
231 static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc, in dwcmshc_check_auto_cmd23() argument
234 struct sdhci_host *host = mmc_priv(mmc); in dwcmshc_check_auto_cmd23()
237 * No matter V4 is enabled or not, ARGUMENT2 register is 32-bit in dwcmshc_check_auto_cmd23()
241 if (mrq->sbc && (mrq->sbc->arg & SDHCI_DWCMSHC_ARG2_STUFF)) in dwcmshc_check_auto_cmd23()
242 host->flags &= ~SDHCI_AUTO_CMD23; in dwcmshc_check_auto_cmd23()
244 host->flags |= SDHCI_AUTO_CMD23; in dwcmshc_check_auto_cmd23()
247 static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq) in dwcmshc_request() argument
249 dwcmshc_check_auto_cmd23(mmc, mrq); in dwcmshc_request()
251 sdhci_request(mmc, mrq); in dwcmshc_request()
270 sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R); in dwcmshc_phy_1_8v_init()
321 sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R); in dwcmshc_phy_3_3v_init()
360 if (priv->flags & FLAG_IO_FIXED_1V8) in th1520_sdhci_set_phy()
365 if ((host->mmc->caps2 & emmc_caps) == emmc_caps) { in th1520_sdhci_set_phy()
366 emmc_ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); in th1520_sdhci_set_phy()
368 sdhci_writew(host, emmc_ctrl, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); in th1520_sdhci_set_phy()
399 /* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */ in dwcmshc_set_uhs_signaling()
400 ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); in dwcmshc_set_uhs_signaling()
402 sdhci_writew(host, ctrl, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); in dwcmshc_set_uhs_signaling()
407 if (priv->flags & FLAG_IO_FIXED_1V8) in dwcmshc_set_uhs_signaling()
420 priv->delay_line = PHY_SDCLKDL_DC_HS400; in th1520_set_uhs_signaling()
426 static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc, in dwcmshc_hs400_enhanced_strobe() argument
430 struct sdhci_host *host = mmc_priv(mmc); in dwcmshc_hs400_enhanced_strobe()
433 int reg = priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL; in dwcmshc_hs400_enhanced_strobe()
436 if (ios->enhanced_strobe) in dwcmshc_hs400_enhanced_strobe()
448 struct rk35xx_priv *priv = dwc_priv->priv; in dwcmshc_rk3568_set_clock()
453 host->mmc->actual_clock = 0; in dwcmshc_rk3568_set_clock()
465 err = clk_set_rate(pltfm_host->clk, clock); in dwcmshc_rk3568_set_clock()
467 dev_err(mmc_dev(host->mmc), "fail to set clock %d", clock); in dwcmshc_rk3568_set_clock()
472 reg = dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3; in dwcmshc_rk3568_set_clock()
508 if (priv->devtype == DWCMSHC_RK3568) in dwcmshc_rk3568_set_clock()
517 err = readl_poll_timeout(host->ioaddr + DWCMSHC_EMMC_DLL_STATUS0, in dwcmshc_rk3568_set_clock()
521 dev_err(mmc_dev(host->mmc), "DLL lock timeout!\n"); in dwcmshc_rk3568_set_clock()
526 0x3 << 17 | /* pre-change delay */ in dwcmshc_rk3568_set_clock()
527 0x3 << 19; /* post-change delay */ in dwcmshc_rk3568_set_clock()
528 sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); in dwcmshc_rk3568_set_clock()
530 if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 || in dwcmshc_rk3568_set_clock()
531 host->mmc->ios.timing == MMC_TIMING_MMC_HS400) in dwcmshc_rk3568_set_clock()
532 txclk_tapnum = priv->txclk_tapnum; in dwcmshc_rk3568_set_clock()
534 if ((priv->devtype == DWCMSHC_RK3588) && host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { in dwcmshc_rk3568_set_clock()
561 struct rk35xx_priv *priv = dwc_priv->priv; in rk35xx_sdhci_reset()
563 if (mask & SDHCI_RESET_ALL && priv->reset) { in rk35xx_sdhci_reset()
564 reset_control_assert(priv->reset); in rk35xx_sdhci_reset()
566 reset_control_deassert(priv->reset); in rk35xx_sdhci_reset()
578 if (host->flags & SDHCI_HS400_TUNING) in th1520_execute_tuning()
583 val = sdhci_readl(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); in th1520_execute_tuning()
587 * - center phase select code driven in block gap interval in th1520_execute_tuning()
588 * - disable reporting of framing errors in th1520_execute_tuning()
589 * - disable software managed tuning in th1520_execute_tuning()
590 * - disable user selection of sampling window edges, in th1520_execute_tuning()
598 * - enable auto-tuning in th1520_execute_tuning()
599 * - enable sampling window threshold in th1520_execute_tuning()
600 * - stop clocks during phase code change in th1520_execute_tuning()
601 * - set max latency in cycles between tx and rx clocks in th1520_execute_tuning()
602 * - set max latency in cycles to switch output phase in th1520_execute_tuning()
603 * - set max sampling window threshold value in th1520_execute_tuning()
610 sdhci_writel(host, val, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); in th1520_execute_tuning()
611 val = sdhci_readl(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); in th1520_execute_tuning()
615 host->tuning_err = __sdhci_execute_tuning(host, opcode); in th1520_execute_tuning()
616 if (host->tuning_err) { in th1520_execute_tuning()
617 /* disable auto-tuning upon tuning error */ in th1520_execute_tuning()
619 sdhci_writel(host, val, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); in th1520_execute_tuning()
620 dev_err(mmc_dev(host->mmc), "tuning failed: %d\n", host->tuning_err); in th1520_execute_tuning()
621 return -EIO; in th1520_execute_tuning()
636 if (priv->flags & FLAG_IO_FIXED_1V8) { in th1520_sdhci_reset()
706 struct rk35xx_priv *priv = dwc_priv->priv; in dwcmshc_rk35xx_init()
708 priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc)); in dwcmshc_rk35xx_init()
709 if (IS_ERR(priv->reset)) { in dwcmshc_rk35xx_init()
710 err = PTR_ERR(priv->reset); in dwcmshc_rk35xx_init()
711 dev_err(mmc_dev(host->mmc), "failed to get reset control %d\n", err); in dwcmshc_rk35xx_init()
715 priv->rockchip_clks[0].id = "axi"; in dwcmshc_rk35xx_init()
716 priv->rockchip_clks[1].id = "block"; in dwcmshc_rk35xx_init()
717 priv->rockchip_clks[2].id = "timer"; in dwcmshc_rk35xx_init()
718 err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK35xx_MAX_CLKS, in dwcmshc_rk35xx_init()
719 priv->rockchip_clks); in dwcmshc_rk35xx_init()
721 dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err); in dwcmshc_rk35xx_init()
725 err = clk_bulk_prepare_enable(RK35xx_MAX_CLKS, priv->rockchip_clks); in dwcmshc_rk35xx_init()
727 dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err); in dwcmshc_rk35xx_init()
731 if (of_property_read_u8(mmc_dev(host->mmc)->of_node, "rockchip,txclk-tapnum", in dwcmshc_rk35xx_init()
732 &priv->txclk_tapnum)) in dwcmshc_rk35xx_init()
733 priv->txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT; in dwcmshc_rk35xx_init()
736 sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3); in dwcmshc_rk35xx_init()
750 if (host->mmc->f_max <= 52000000) { in dwcmshc_rk35xx_postinit()
751 dev_info(mmc_dev(host->mmc), "Disabling HS200/HS400, frequency too low (%d)\n", in dwcmshc_rk35xx_postinit()
752 host->mmc->f_max); in dwcmshc_rk35xx_postinit()
753 host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400); in dwcmshc_rk35xx_postinit()
754 host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR); in dwcmshc_rk35xx_postinit()
760 .compatible = "rockchip,rk3588-dwcmshc",
764 .compatible = "rockchip,rk3568-dwcmshc",
768 .compatible = "snps,dwcmshc-sdhci",
772 .compatible = "thead,th1520-dwcmshc",
792 struct device *dev = &pdev->dev; in dwcmshc_probe()
801 pltfm_data = device_get_match_data(&pdev->dev); in dwcmshc_probe()
803 dev_err(&pdev->dev, "Error: No device match data found\n"); in dwcmshc_probe()
804 return -ENODEV; in dwcmshc_probe()
818 host->adma_table_cnt += extra; in dwcmshc_probe()
823 if (dev->of_node) { in dwcmshc_probe()
824 pltfm_host->clk = devm_clk_get(dev, "core"); in dwcmshc_probe()
825 if (IS_ERR(pltfm_host->clk)) { in dwcmshc_probe()
826 err = PTR_ERR(pltfm_host->clk); in dwcmshc_probe()
830 err = clk_prepare_enable(pltfm_host->clk); in dwcmshc_probe()
834 priv->bus_clk = devm_clk_get(dev, "bus"); in dwcmshc_probe()
835 if (!IS_ERR(priv->bus_clk)) in dwcmshc_probe()
836 clk_prepare_enable(priv->bus_clk); in dwcmshc_probe()
839 err = mmc_of_parse(host->mmc); in dwcmshc_probe()
845 priv->vendor_specific_area1 = in dwcmshc_probe()
848 host->mmc_host_ops.request = dwcmshc_request; in dwcmshc_probe()
849 host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe; in dwcmshc_probe()
852 rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk35xx_priv), GFP_KERNEL); in dwcmshc_probe()
854 err = -ENOMEM; in dwcmshc_probe()
858 if (of_device_is_compatible(pdev->dev.of_node, "rockchip,rk3588-dwcmshc")) in dwcmshc_probe()
859 rk_priv->devtype = DWCMSHC_RK3588; in dwcmshc_probe()
861 rk_priv->devtype = DWCMSHC_RK3568; in dwcmshc_probe()
863 priv->priv = rk_priv; in dwcmshc_probe()
871 priv->delay_line = PHY_SDCLKDL_DC_DEFAULT; in dwcmshc_probe()
873 if (device_property_read_bool(dev, "mmc-ddr-1_8v") || in dwcmshc_probe()
874 device_property_read_bool(dev, "mmc-hs200-1_8v") || in dwcmshc_probe()
875 device_property_read_bool(dev, "mmc-hs400-1_8v")) in dwcmshc_probe()
876 priv->flags |= FLAG_IO_FIXED_1V8; in dwcmshc_probe()
878 priv->flags &= ~FLAG_IO_FIXED_1V8; in dwcmshc_probe()
886 if (priv->flags & FLAG_IO_FIXED_1V8) { in dwcmshc_probe()
887 host->flags &= ~SDHCI_SIGNALING_330; in dwcmshc_probe()
888 host->flags |= SDHCI_SIGNALING_180; in dwcmshc_probe()
899 host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; in dwcmshc_probe()
926 clk_disable_unprepare(pltfm_host->clk); in dwcmshc_probe()
927 clk_disable_unprepare(priv->bus_clk); in dwcmshc_probe()
930 rk_priv->rockchip_clks); in dwcmshc_probe()
941 struct rk35xx_priv *rk_priv = priv->priv; in dwcmshc_remove()
945 clk_disable_unprepare(pltfm_host->clk); in dwcmshc_remove()
946 clk_disable_unprepare(priv->bus_clk); in dwcmshc_remove()
949 rk_priv->rockchip_clks); in dwcmshc_remove()
959 struct rk35xx_priv *rk_priv = priv->priv; in dwcmshc_suspend()
968 clk_disable_unprepare(pltfm_host->clk); in dwcmshc_suspend()
969 if (!IS_ERR(priv->bus_clk)) in dwcmshc_suspend()
970 clk_disable_unprepare(priv->bus_clk); in dwcmshc_suspend()
974 rk_priv->rockchip_clks); in dwcmshc_suspend()
984 struct rk35xx_priv *rk_priv = priv->priv; in dwcmshc_resume()
987 ret = clk_prepare_enable(pltfm_host->clk); in dwcmshc_resume()
991 if (!IS_ERR(priv->bus_clk)) { in dwcmshc_resume()
992 ret = clk_prepare_enable(priv->bus_clk); in dwcmshc_resume()
999 rk_priv->rockchip_clks); in dwcmshc_resume()
1013 rk_priv->rockchip_clks); in dwcmshc_resume()
1015 if (!IS_ERR(priv->bus_clk)) in dwcmshc_resume()
1016 clk_disable_unprepare(priv->bus_clk); in dwcmshc_resume()
1018 clk_disable_unprepare(pltfm_host->clk); in dwcmshc_resume()
1075 .name = "sdhci-dwcmshc",