Lines Matching +full:itap +full:- +full:del +full:- +full:sel +full:- +full:sdr25

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",
186 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, in sdhci_am654_setup_dll()
189 if (sdhci_am654->flags & FREQSEL_2_BIT) { in sdhci_am654_setup_dll()
207 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); in sdhci_am654_setup_dll()
218 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, FREQSEL_MASK, in sdhci_am654_setup_dll()
223 val = sdhci_am654->trm_icp << DLL_TRIM_ICP_SHIFT; in sdhci_am654_setup_dll()
227 val |= sdhci_am654->drv_strength << DR_TY_SHIFT; in sdhci_am654_setup_dll()
228 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, mask, val); in sdhci_am654_setup_dll()
231 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, in sdhci_am654_setup_dll()
237 ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1, val, in sdhci_am654_setup_dll()
240 dev_err(mmc_dev(host->mmc), "DLL failed to relock\n"); in sdhci_am654_setup_dll()
249 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, in sdhci_am654_write_itapdly()
251 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK, in sdhci_am654_write_itapdly()
253 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYSEL_MASK, in sdhci_am654_write_itapdly()
255 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); in sdhci_am654_write_itapdly()
263 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); in sdhci_am654_setup_delay_chain()
267 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); in sdhci_am654_setup_delay_chain()
269 sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], in sdhci_am654_setup_delay_chain()
270 sdhci_am654->itap_del_ena[timing]); in sdhci_am654_setup_delay_chain()
277 unsigned char timing = host->mmc->ios.timing; in sdhci_am654_set_clock()
281 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); in sdhci_am654_set_clock()
286 otap_del_sel = sdhci_am654->otap_del_sel[timing]; in sdhci_am654_set_clock()
294 if (sdhci_am654->flags & STRBSEL_4_BIT) in sdhci_am654_set_clock()
299 val |= sdhci_am654->strb_sel << STRBSEL_SHIFT; in sdhci_am654_set_clock()
302 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); in sdhci_am654_set_clock()
306 sdhci_am654->dll_enable = true; in sdhci_am654_set_clock()
309 sdhci_am654->itap_del_ena[timing] = 0x1; in sdhci_am654_set_clock()
310 sdhci_am654->itap_del_sel[timing] = sdhci_am654->itap_del_sel[timing - 1]; in sdhci_am654_set_clock()
313 sdhci_am654_write_itapdly(sdhci_am654, sdhci_am654->itap_del_sel[timing], in sdhci_am654_set_clock()
314 sdhci_am654->itap_del_ena[timing]); in sdhci_am654_set_clock()
317 sdhci_am654->dll_enable = false; in sdhci_am654_set_clock()
320 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, in sdhci_am654_set_clock()
321 sdhci_am654->clkbuf_sel); in sdhci_am654_set_clock()
329 unsigned char timing = host->mmc->ios.timing; in sdhci_j721e_4bit_set_clock()
336 otap_del_sel = sdhci_am654->otap_del_sel[timing]; in sdhci_j721e_4bit_set_clock()
343 itap_del_ena = sdhci_am654->itap_del_ena[timing]; in sdhci_j721e_4bit_set_clock()
344 itap_del_sel = sdhci_am654->itap_del_sel[timing]; in sdhci_j721e_4bit_set_clock()
350 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, in sdhci_j721e_4bit_set_clock()
352 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); in sdhci_j721e_4bit_set_clock()
353 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); in sdhci_j721e_4bit_set_clock()
354 regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, in sdhci_j721e_4bit_set_clock()
355 sdhci_am654->clkbuf_sel); in sdhci_j721e_4bit_set_clock()
367 if ((sdhci_am654->quirks & SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA) && in sdhci_am654_start_signal_voltage_switch()
368 ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { in sdhci_am654_start_signal_voltage_switch()
369 if (!IS_ERR(mmc->supply.vqmmc)) { in sdhci_am654_start_signal_voltage_switch()
374 return -EIO; in sdhci_am654_start_signal_voltage_switch()
385 writeb(val, host->ioaddr + reg); in sdhci_am654_write_power_on()
387 return readb(host->ioaddr + reg); in sdhci_am654_write_power_on()
393 unsigned char timing = host->mmc->ios.timing; in sdhci_am654_write_b()
409 writeb(val, host->ioaddr + reg); in sdhci_am654_write_b()
421 dev_info(mmc_dev(host->mmc), "Power on failed\n"); in sdhci_am654_write_b()
433 if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST) { in sdhci_am654_reset()
464 cqhci_irq(host->mmc, intmask, cmd_error, data_error); in sdhci_am654_cqhci_irq()
470 #define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)
475 u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0; in sdhci_am654_calculate_itap() local
477 struct device *dev = mmc_dev(host->mmc); in sdhci_am654_calculate_itap()
479 int prev_fail_end = -1; in sdhci_am654_calculate_itap()
485 return -1; in sdhci_am654_calculate_itap()
488 if (fail_window->length == ITAPDLY_LENGTH) { in sdhci_am654_calculate_itap()
491 return -1; in sdhci_am654_calculate_itap()
494 first_fail_start = fail_window->start; in sdhci_am654_calculate_itap()
495 last_fail_end = fail_window[num_fails - 1].end; in sdhci_am654_calculate_itap()
500 pass_length = start_fail - (prev_fail_end + 1); in sdhci_am654_calculate_itap()
510 pass_length = ITAPDLY_LAST_INDEX - last_fail_end; in sdhci_am654_calculate_itap()
512 pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start; in sdhci_am654_calculate_itap()
520 itap = pass_window.start + (pass_window.length >> 1); in sdhci_am654_calculate_itap()
522 itap = (pass_window.start + (pass_window.length >> 1)) % ITAPDLY_LENGTH; in sdhci_am654_calculate_itap()
524 return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap; in sdhci_am654_calculate_itap()
532 unsigned char timing = host->mmc->ios.timing; in sdhci_am654_do_tuning()
534 struct device *dev = mmc_dev(host->mmc); in sdhci_am654_do_tuning()
535 u8 curr_pass, itap; in sdhci_am654_do_tuning() local
542 sdhci_am654->itap_del_ena[timing] = 0x1; in sdhci_am654_do_tuning()
544 for (itap = 0; itap < ITAPDLY_LENGTH; itap++) { in sdhci_am654_do_tuning()
545 sdhci_am654_write_itapdly(sdhci_am654, itap, sdhci_am654->itap_del_ena[timing]); in sdhci_am654_do_tuning()
547 curr_pass = !mmc_send_tuning(host->mmc, opcode, NULL); in sdhci_am654_do_tuning()
550 fail_window[fail_index].start = itap; in sdhci_am654_do_tuning()
553 fail_window[fail_index].end = itap; in sdhci_am654_do_tuning()
555 dev_dbg(dev, "Failed itapdly=%d\n", itap); in sdhci_am654_do_tuning()
568 sdhci_am654->dll_enable); in sdhci_am654_do_tuning()
576 unsigned char timing = host->mmc->ios.timing; in sdhci_am654_platform_execute_tuning()
577 struct device *dev = mmc_dev(host->mmc); in sdhci_am654_platform_execute_tuning()
584 } while (++sdhci_am654->tuning_loop < RETRY_TUNING_MAX); in sdhci_am654_platform_execute_tuning()
588 return -1; in sdhci_am654_platform_execute_tuning()
592 sdhci_am654_write_itapdly(sdhci_am654, itapdly, sdhci_am654->itap_del_ena[timing]); in sdhci_am654_platform_execute_tuning()
594 sdhci_am654->itap_del_sel[timing] = itapdly; in sdhci_am654_platform_execute_tuning()
700 cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(struct cqhci_host), in sdhci_am654_cqe_add_host()
703 return -ENOMEM; in sdhci_am654_cqe_add_host()
705 cq_host->mmio = host->ioaddr + SDHCI_AM654_CQE_BASE_ADDR; in sdhci_am654_cqe_add_host()
706 cq_host->quirks |= CQHCI_QUIRK_SHORT_TXFR_DESC_SZ; in sdhci_am654_cqe_add_host()
707 cq_host->caps |= CQHCI_TASK_DESC_SZ_128; in sdhci_am654_cqe_add_host()
708 cq_host->ops = &sdhci_am654_cqhci_ops; in sdhci_am654_cqe_add_host()
710 host->mmc->caps2 |= MMC_CAP2_CQE; in sdhci_am654_cqe_add_host()
712 return cqhci_init(cq_host, host->mmc, 1); in sdhci_am654_cqe_add_host()
718 struct device *dev = mmc_dev(host->mmc); in sdhci_am654_get_otap_delay()
725 &sdhci_am654->otap_del_sel[i]); in sdhci_am654_get_otap_delay()
728 dev_err(dev, "Couldn't find mandatory ti,otap-del-sel-legacy\n"); in sdhci_am654_get_otap_delay()
735 * if an otap-del-sel value is not found in sdhci_am654_get_otap_delay()
738 host->mmc->caps &= ~td[i].capability; in sdhci_am654_get_otap_delay()
740 host->mmc->caps2 &= ~td[i].capability; in sdhci_am654_get_otap_delay()
745 &sdhci_am654->itap_del_sel[i]); in sdhci_am654_get_otap_delay()
747 sdhci_am654->itap_del_ena[i] = 0x1; in sdhci_am654_get_otap_delay()
765 regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, 0x0); in sdhci_am654_init()
767 if (sdhci_am654->flags & DLL_CALIB) { in sdhci_am654_init()
768 regmap_read(sdhci_am654->base, PHY_STAT1, &val); in sdhci_am654_init()
771 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, in sdhci_am654_init()
773 ret = regmap_read_poll_timeout(sdhci_am654->base, in sdhci_am654_init()
783 if (sdhci_am654->flags & IOMUX_PRESENT) in sdhci_am654_init()
784 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, in sdhci_am654_init()
788 if (host->mmc->caps & MMC_CAP_NONREMOVABLE) in sdhci_am654_init()
791 regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK, in sdhci_am654_init()
795 regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK, in sdhci_am654_init()
798 /* Use to re-execute tuning */ in sdhci_am654_init()
799 sdhci_am654->tuning_loop = 0; in sdhci_am654_init()
827 struct device *dev = &pdev->dev; in sdhci_am654_get_of_property()
831 if (sdhci_am654->flags & DLL_PRESENT) { in sdhci_am654_get_of_property()
832 ret = device_property_read_u32(dev, "ti,trm-icp", in sdhci_am654_get_of_property()
833 &sdhci_am654->trm_icp); in sdhci_am654_get_of_property()
837 ret = device_property_read_u32(dev, "ti,driver-strength-ohm", in sdhci_am654_get_of_property()
844 sdhci_am654->drv_strength = DRIVER_STRENGTH_50_OHM; in sdhci_am654_get_of_property()
847 sdhci_am654->drv_strength = DRIVER_STRENGTH_33_OHM; in sdhci_am654_get_of_property()
850 sdhci_am654->drv_strength = DRIVER_STRENGTH_66_OHM; in sdhci_am654_get_of_property()
853 sdhci_am654->drv_strength = DRIVER_STRENGTH_100_OHM; in sdhci_am654_get_of_property()
856 sdhci_am654->drv_strength = DRIVER_STRENGTH_40_OHM; in sdhci_am654_get_of_property()
860 return -EINVAL; in sdhci_am654_get_of_property()
864 device_property_read_u32(dev, "ti,strobe-sel", &sdhci_am654->strb_sel); in sdhci_am654_get_of_property()
865 device_property_read_u32(dev, "ti,clkbuf-sel", in sdhci_am654_get_of_property()
866 &sdhci_am654->clkbuf_sel); in sdhci_am654_get_of_property()
868 if (device_property_read_bool(dev, "ti,fails-without-test-cd")) in sdhci_am654_get_of_property()
869 sdhci_am654->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST; in sdhci_am654_get_of_property()
872 if (!!of_parse_phandle(dev->of_node, "vmmc-supply", 0) == in sdhci_am654_get_of_property()
873 !!of_parse_phandle(dev->of_node, "vqmmc-supply", 0)) in sdhci_am654_get_of_property()
874 sdhci_am654->quirks |= SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA; in sdhci_am654_get_of_property()
883 .compatible = "ti,am654-sdhci-5.1",
887 .compatible = "ti,j721e-sdhci-8bit",
891 .compatible = "ti,j721e-sdhci-4bit",
895 .compatible = "ti,am64-sdhci-8bit",
899 .compatible = "ti,am64-sdhci-4bit",
903 .compatible = "ti,am62-sdhci",
919 struct device *dev = &pdev->dev; in sdhci_am654_probe()
923 match = of_match_node(sdhci_am654_of_match, pdev->dev.of_node); in sdhci_am654_probe()
924 drvdata = match->data; in sdhci_am654_probe()
928 if (soc && soc->data) in sdhci_am654_probe()
929 drvdata = soc->data; in sdhci_am654_probe()
931 host = sdhci_pltfm_init(pdev, drvdata->pdata, sizeof(*sdhci_am654)); in sdhci_am654_probe()
937 sdhci_am654->flags = drvdata->flags; in sdhci_am654_probe()
946 pltfm_host->clk = clk_xin; in sdhci_am654_probe()
954 sdhci_am654->base = devm_regmap_init_mmio(dev, base, in sdhci_am654_probe()
956 if (IS_ERR(sdhci_am654->base)) { in sdhci_am654_probe()
958 ret = PTR_ERR(sdhci_am654->base); in sdhci_am654_probe()
966 ret = mmc_of_parse(host->mmc); in sdhci_am654_probe()
972 host->mmc_host_ops.start_signal_voltage_switch = sdhci_am654_start_signal_voltage_switch; in sdhci_am654_probe()
973 host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; in sdhci_am654_probe()
980 ret = clk_prepare_enable(pltfm_host->clk); in sdhci_am654_probe()
996 clk_disable_unprepare(pltfm_host->clk); in sdhci_am654_probe()
1010 struct device *dev = &pdev->dev; in sdhci_am654_remove()
1018 clk_disable_unprepare(pltfm_host->clk); in sdhci_am654_remove()
1033 if (sdhci_am654->flags & DLL_CALIB) { in sdhci_am654_restore()
1034 regmap_read(sdhci_am654->base, PHY_STAT1, &val); in sdhci_am654_restore()
1037 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, in sdhci_am654_restore()
1039 ret = regmap_read_poll_timeout(sdhci_am654->base, in sdhci_am654_restore()
1049 if (sdhci_am654->flags & IOMUX_PRESENT) in sdhci_am654_restore()
1050 regmap_update_bits(sdhci_am654->base, PHY_CTRL1, in sdhci_am654_restore()
1054 if (host->mmc->caps & MMC_CAP_NONREMOVABLE) in sdhci_am654_restore()
1057 regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK, in sdhci_am654_restore()
1060 regmap_read(sdhci_am654->base, CTL_CFG_3, &val); in sdhci_am654_restore()
1063 regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK, in sdhci_am654_restore()
1075 if (host->tuning_mode != SDHCI_TUNING_MODE_3) in sdhci_am654_runtime_suspend()
1076 mmc_retune_needed(host->mmc); in sdhci_am654_runtime_suspend()
1078 ret = cqhci_suspend(host->mmc); in sdhci_am654_runtime_suspend()
1087 clk_disable_unprepare(pltfm_host->clk); in sdhci_am654_runtime_suspend()
1098 ret = clk_prepare_enable(pltfm_host->clk); in sdhci_am654_runtime_resume()
1110 ret = cqhci_resume(host->mmc); in sdhci_am654_runtime_resume()
1127 .name = "sdhci-am654",