Lines Matching +full:re +full:- +full:tuning

1 // SPDX-License-Identifier: GPL-2.0
3 * sdhci_am654.c - SDHCI driver for TI's AM654 SOCs
5 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com
18 #include "sdhci-cqhci.h"
19 #include "sdhci-pltfm.h"
88 #define SDHCI_AM654_AUTOSUSPEND_DELAY -1
108 [MMC_TIMING_LEGACY] = {"ti,otap-del-sel-legacy",
109 "ti,itap-del-sel-legacy",
111 [MMC_TIMING_MMC_HS] = {"ti,otap-del-sel-mmc-hs",
112 "ti,itap-del-sel-mmc-hs",
114 [MMC_TIMING_SD_HS] = {"ti,otap-del-sel-sd-hs",
115 "ti,itap-del-sel-sd-hs",
117 [MMC_TIMING_UHS_SDR12] = {"ti,otap-del-sel-sdr12",
118 "ti,itap-del-sel-sdr12",
120 [MMC_TIMING_UHS_SDR25] = {"ti,otap-del-sel-sdr25",
121 "ti,itap-del-sel-sdr25",
123 [MMC_TIMING_UHS_SDR50] = {"ti,otap-del-sel-sdr50",
126 [MMC_TIMING_UHS_SDR104] = {"ti,otap-del-sel-sdr104",
129 [MMC_TIMING_UHS_DDR50] = {"ti,otap-del-sel-ddr50",
132 [MMC_TIMING_MMC_DDR52] = {"ti,otap-del-sel-ddr52",
133 "ti,itap-del-sel-ddr52",
135 [MMC_TIMING_MMC_HS200] = {"ti,otap-del-sel-hs200",
138 [MMC_TIMING_MMC_HS400] = {"ti,otap-del-sel-hs400",
185 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, in sdhci_am654_setup_dll()
188 if (sdhci_am654->flags & FREQSEL_2_BIT) { in sdhci_am654_setup_dll()
206 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); in sdhci_am654_setup_dll()
217 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, FREQSEL_MASK, in sdhci_am654_setup_dll()
222 val = sdhci_am654->trm_icp << DLL_TRIM_ICP_SHIFT; in sdhci_am654_setup_dll()
226 val |= sdhci_am654->drv_strength << DR_TY_SHIFT; in sdhci_am654_setup_dll()
227 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, mask, val); in sdhci_am654_setup_dll()
230 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, in sdhci_am654_setup_dll()
236 ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1, val, in sdhci_am654_setup_dll()
239 dev_err(mmc_dev(host->mmc), "DLL failed to relock\n"); in sdhci_am654_setup_dll()
248 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, in sdhci_am654_write_itapdly()
250 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK, in sdhci_am654_write_itapdly()
252 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYSEL_MASK, in sdhci_am654_write_itapdly()
254 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); in sdhci_am654_write_itapdly()
262 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); in sdhci_am654_setup_delay_chain()
266 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); in sdhci_am654_setup_delay_chain()
268 sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], in sdhci_am654_setup_delay_chain()
269 sdhci_am654->itap_del_ena[timing]); in sdhci_am654_setup_delay_chain()
276 unsigned char timing = host->mmc->ios.timing; in sdhci_am654_set_clock()
280 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); in sdhci_am654_set_clock()
285 otap_del_sel = sdhci_am654->otap_del_sel[timing]; in sdhci_am654_set_clock()
293 if (sdhci_am654->flags & STRBSEL_4_BIT) in sdhci_am654_set_clock()
298 val |= sdhci_am654->strb_sel << STRBSEL_SHIFT; in sdhci_am654_set_clock()
301 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); in sdhci_am654_set_clock()
305 sdhci_am654->dll_enable = true; in sdhci_am654_set_clock()
308 sdhci_am654->itap_del_ena[timing] = 0x1; in sdhci_am654_set_clock()
309 sdhci_am654->itap_del_sel[timing] = sdhci_am654->itap_del_sel[timing - 1]; in sdhci_am654_set_clock()
312 sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], in sdhci_am654_set_clock()
313 sdhci_am654->itap_del_ena[timing]); in sdhci_am654_set_clock()
316 sdhci_am654->dll_enable = false; in sdhci_am654_set_clock()
319 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, in sdhci_am654_set_clock()
320 sdhci_am654->clkbuf_sel); in sdhci_am654_set_clock()
328 unsigned char timing = host->mmc->ios.timing; in sdhci_j721e_4bit_set_clock()
335 otap_del_sel = sdhci_am654->otap_del_sel[timing]; in sdhci_j721e_4bit_set_clock()
342 itap_del_ena = sdhci_am654->itap_del_ena[timing]; in sdhci_j721e_4bit_set_clock()
343 itap_del_sel = sdhci_am654->itap_del_sel[timing]; in sdhci_j721e_4bit_set_clock()
349 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, in sdhci_j721e_4bit_set_clock()
351 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); in sdhci_j721e_4bit_set_clock()
352 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); in sdhci_j721e_4bit_set_clock()
353 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, in sdhci_j721e_4bit_set_clock()
354 sdhci_am654->clkbuf_sel); in sdhci_j721e_4bit_set_clock()
361 writeb(val, host->ioaddr + reg); in sdhci_am654_write_power_on()
363 return readb(host->ioaddr + reg); in sdhci_am654_write_power_on()
369 unsigned char timing = host->mmc->ios.timing; in sdhci_am654_write_b()
385 writeb(val, host->ioaddr + reg); in sdhci_am654_write_b()
397 dev_info(mmc_dev(host->mmc), "Power on failed\n"); in sdhci_am654_write_b()
409 if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST) { in sdhci_am654_reset()
424 * Tuning data remains in the buffer after tuning. in sdhci_am654_execute_tuning()
440 cqhci_irq(host->mmc, intmask, cmd_error, data_error); in sdhci_am654_cqhci_irq()
446 #define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)
453 struct device *dev = mmc_dev(host->mmc); in sdhci_am654_calculate_itap()
455 int prev_fail_end = -1; in sdhci_am654_calculate_itap()
459 /* Retry tuning */ in sdhci_am654_calculate_itap()
460 dev_dbg(dev, "No failing region found, retry tuning\n"); in sdhci_am654_calculate_itap()
461 return -1; in sdhci_am654_calculate_itap()
464 if (fail_window->length == ITAPDLY_LENGTH) { in sdhci_am654_calculate_itap()
465 /* Retry tuning */ in sdhci_am654_calculate_itap()
466 dev_dbg(dev, "No passing itapdly, retry tuning\n"); in sdhci_am654_calculate_itap()
467 return -1; in sdhci_am654_calculate_itap()
470 first_fail_start = fail_window->start; in sdhci_am654_calculate_itap()
471 last_fail_end = fail_window[num_fails - 1].end; in sdhci_am654_calculate_itap()
476 pass_length = start_fail - (prev_fail_end + 1); in sdhci_am654_calculate_itap()
486 pass_length = ITAPDLY_LAST_INDEX - last_fail_end; in sdhci_am654_calculate_itap()
488 pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start; in sdhci_am654_calculate_itap()
508 unsigned char timing = host->mmc->ios.timing; in sdhci_am654_do_tuning()
510 struct device *dev = mmc_dev(host->mmc); in sdhci_am654_do_tuning()
518 sdhci_am654->itap_del_ena[timing] = 0x1; in sdhci_am654_do_tuning()
521 sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]); in sdhci_am654_do_tuning()
523 curr_pass = !mmc_send_tuning(host->mmc, opcode, NULL); in sdhci_am654_do_tuning()
544 sdhci_am654->dll_enable); in sdhci_am654_do_tuning()
552 unsigned char timing = host->mmc->ios.timing; in sdhci_am654_platform_execute_tuning()
553 struct device *dev = mmc_dev(host->mmc); in sdhci_am654_platform_execute_tuning()
560 } while (++sdhci_am654->tuning_loop < RETRY_TUNING_MAX); in sdhci_am654_platform_execute_tuning()
563 dev_err(dev, "Failed to find itapdly, fail tuning\n"); in sdhci_am654_platform_execute_tuning()
564 return -1; in sdhci_am654_platform_execute_tuning()
567 dev_dbg(dev, "Passed tuning, final itapdly=%d\n", itapdly); in sdhci_am654_platform_execute_tuning()
568 sdhci_am654_write_itapdly(sdhci_am654, itapdly, sdhci_am654->itap_del_ena[timing]); in sdhci_am654_platform_execute_tuning()
570 sdhci_am654->itap_del_sel[timing] = itapdly; in sdhci_am654_platform_execute_tuning()
676 cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(struct cqhci_host), in sdhci_am654_cqe_add_host()
679 return -ENOMEM; in sdhci_am654_cqe_add_host()
681 cq_host->mmio = host->ioaddr + SDHCI_AM654_CQE_BASE_ADDR; in sdhci_am654_cqe_add_host()
682 cq_host->quirks |= CQHCI_QUIRK_SHORT_TXFR_DESC_SZ; in sdhci_am654_cqe_add_host()
683 cq_host->caps |= CQHCI_TASK_DESC_SZ_128; in sdhci_am654_cqe_add_host()
684 cq_host->ops = &sdhci_am654_cqhci_ops; in sdhci_am654_cqe_add_host()
686 host->mmc->caps2 |= MMC_CAP2_CQE; in sdhci_am654_cqe_add_host()
688 return cqhci_init(cq_host, host->mmc, 1); in sdhci_am654_cqe_add_host()
694 struct device *dev = mmc_dev(host->mmc); in sdhci_am654_get_otap_delay()
701 &sdhci_am654->otap_del_sel[i]); in sdhci_am654_get_otap_delay()
704 dev_err(dev, "Couldn't find mandatory ti,otap-del-sel-legacy\n"); in sdhci_am654_get_otap_delay()
711 * if an otap-del-sel value is not found in sdhci_am654_get_otap_delay()
714 host->mmc->caps &= ~td[i].capability; in sdhci_am654_get_otap_delay()
716 host->mmc->caps2 &= ~td[i].capability; in sdhci_am654_get_otap_delay()
721 &sdhci_am654->itap_del_sel[i]); in sdhci_am654_get_otap_delay()
723 sdhci_am654->itap_del_ena[i] = 0x1; in sdhci_am654_get_otap_delay()
741 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, 0x0); in sdhci_am654_init()
743 if (sdhci_am654->flags & DLL_CALIB) { in sdhci_am654_init()
744 regmap_read(sdhci_am654->base, PHY_STAT1, &val); in sdhci_am654_init()
747 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, in sdhci_am654_init()
749 ret = regmap_read_poll_timeout(sdhci_am654->base, in sdhci_am654_init()
759 if (sdhci_am654->flags & IOMUX_PRESENT) in sdhci_am654_init()
760 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, in sdhci_am654_init()
764 if (host->mmc->caps & MMC_CAP_NONREMOVABLE) in sdhci_am654_init()
767 regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK, in sdhci_am654_init()
770 /* Enable tuning for SDR50 */ in sdhci_am654_init()
771 regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK, in sdhci_am654_init()
774 /* Use to re-execute tuning */ in sdhci_am654_init()
775 sdhci_am654->tuning_loop = 0; in sdhci_am654_init()
803 struct device *dev = &pdev->dev; in sdhci_am654_get_of_property()
807 if (sdhci_am654->flags & DLL_PRESENT) { in sdhci_am654_get_of_property()
808 ret = device_property_read_u32(dev, "ti,trm-icp", in sdhci_am654_get_of_property()
809 &sdhci_am654->trm_icp); in sdhci_am654_get_of_property()
813 ret = device_property_read_u32(dev, "ti,driver-strength-ohm", in sdhci_am654_get_of_property()
820 sdhci_am654->drv_strength = DRIVER_STRENGTH_50_OHM; in sdhci_am654_get_of_property()
823 sdhci_am654->drv_strength = DRIVER_STRENGTH_33_OHM; in sdhci_am654_get_of_property()
826 sdhci_am654->drv_strength = DRIVER_STRENGTH_66_OHM; in sdhci_am654_get_of_property()
829 sdhci_am654->drv_strength = DRIVER_STRENGTH_100_OHM; in sdhci_am654_get_of_property()
832 sdhci_am654->drv_strength = DRIVER_STRENGTH_40_OHM; in sdhci_am654_get_of_property()
836 return -EINVAL; in sdhci_am654_get_of_property()
840 device_property_read_u32(dev, "ti,strobe-sel", &sdhci_am654->strb_sel); in sdhci_am654_get_of_property()
841 device_property_read_u32(dev, "ti,clkbuf-sel", in sdhci_am654_get_of_property()
842 &sdhci_am654->clkbuf_sel); in sdhci_am654_get_of_property()
844 if (device_property_read_bool(dev, "ti,fails-without-test-cd")) in sdhci_am654_get_of_property()
845 sdhci_am654->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST; in sdhci_am654_get_of_property()
854 .compatible = "ti,am654-sdhci-5.1",
858 .compatible = "ti,j721e-sdhci-8bit",
862 .compatible = "ti,j721e-sdhci-4bit",
866 .compatible = "ti,am64-sdhci-8bit",
870 .compatible = "ti,am64-sdhci-4bit",
874 .compatible = "ti,am62-sdhci",
890 struct device *dev = &pdev->dev; in sdhci_am654_probe()
894 match = of_match_node(sdhci_am654_of_match, pdev->dev.of_node); in sdhci_am654_probe()
895 drvdata = match->data; in sdhci_am654_probe()
899 if (soc && soc->data) in sdhci_am654_probe()
900 drvdata = soc->data; in sdhci_am654_probe()
902 host = sdhci_pltfm_init(pdev, drvdata->pdata, sizeof(*sdhci_am654)); in sdhci_am654_probe()
908 sdhci_am654->flags = drvdata->flags; in sdhci_am654_probe()
917 pltfm_host->clk = clk_xin; in sdhci_am654_probe()
925 sdhci_am654->base = devm_regmap_init_mmio(dev, base, in sdhci_am654_probe()
927 if (IS_ERR(sdhci_am654->base)) { in sdhci_am654_probe()
929 ret = PTR_ERR(sdhci_am654->base); in sdhci_am654_probe()
937 ret = mmc_of_parse(host->mmc); in sdhci_am654_probe()
943 host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; in sdhci_am654_probe()
950 ret = clk_prepare_enable(pltfm_host->clk); in sdhci_am654_probe()
966 clk_disable_unprepare(pltfm_host->clk); in sdhci_am654_probe()
980 struct device *dev = &pdev->dev; in sdhci_am654_remove()
988 clk_disable_unprepare(pltfm_host->clk); in sdhci_am654_remove()
1003 if (sdhci_am654->flags & DLL_CALIB) { in sdhci_am654_restore()
1004 regmap_read(sdhci_am654->base, PHY_STAT1, &val); in sdhci_am654_restore()
1007 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, in sdhci_am654_restore()
1009 ret = regmap_read_poll_timeout(sdhci_am654->base, in sdhci_am654_restore()
1019 if (sdhci_am654->flags & IOMUX_PRESENT) in sdhci_am654_restore()
1020 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, in sdhci_am654_restore()
1024 if (host->mmc->caps & MMC_CAP_NONREMOVABLE) in sdhci_am654_restore()
1027 regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK, in sdhci_am654_restore()
1030 regmap_read(sdhci_am654->base, CTL_CFG_3, &val); in sdhci_am654_restore()
1032 /* Enable tuning for SDR50 */ in sdhci_am654_restore()
1033 regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK, in sdhci_am654_restore()
1045 if (host->tuning_mode != SDHCI_TUNING_MODE_3) in sdhci_am654_runtime_suspend()
1046 mmc_retune_needed(host->mmc); in sdhci_am654_runtime_suspend()
1048 ret = cqhci_suspend(host->mmc); in sdhci_am654_runtime_suspend()
1057 clk_disable_unprepare(pltfm_host->clk); in sdhci_am654_runtime_suspend()
1068 ret = clk_prepare_enable(pltfm_host->clk); in sdhci_am654_runtime_resume()
1080 ret = cqhci_resume(host->mmc); in sdhci_am654_runtime_resume()
1097 .name = "sdhci-am654",