3 * Texas Instruments Incorporated, <www.ti.com>
5 * Lokesh Vutla <lokeshvutla@ti.com>
7 * SPDX-License-Identifier: GPL-2.0+
11 #include <asm/utils.h>
12 #include <asm/arch/dra7xx_iodelay.h>
13 #include <asm/arch/omap.h>
14 #include <asm/arch/sys_proto.h>
15 #include <asm/arch/clock.h>
16 #include <asm/omap_common.h>
18 static int isolate_io(u32 isolate)
21 clrsetbits_le32((*ctrl)->control_pbias, SDCARD_PWRDNZ,
23 clrsetbits_le32((*ctrl)->control_pbias, SDCARD_BIAS_PWRDNZ,
27 /* Override control on ISOCLKIN signal to IO pad ring. */
28 clrsetbits_le32((*prcm)->prm_io_pmctrl, PMCTRL_ISOCLK_OVERRIDE_MASK,
29 PMCTRL_ISOCLK_OVERRIDE_CTRL);
30 if (!wait_on_value(PMCTRL_ISOCLK_STATUS_MASK, PMCTRL_ISOCLK_STATUS_MASK,
31 (u32 *)(*prcm)->prm_io_pmctrl, LDELAY))
32 return ERR_DEISOLATE_IO << isolate;
34 /* Isolate/Deisolate IO */
35 clrsetbits_le32((*ctrl)->ctrl_core_sma_sw_0, CTRL_ISOLATE_MASK,
36 isolate << CTRL_ISOLATE_SHIFT);
37 /* Dummy read to add delay t > 10ns */
38 readl((*ctrl)->ctrl_core_sma_sw_0);
40 /* Return control on ISOCLKIN to hardware */
41 clrsetbits_le32((*prcm)->prm_io_pmctrl, PMCTRL_ISOCLK_OVERRIDE_MASK,
42 PMCTRL_ISOCLK_NOT_OVERRIDE_CTRL);
43 if (!wait_on_value(PMCTRL_ISOCLK_STATUS_MASK,
44 0 << PMCTRL_ISOCLK_STATUS_SHIFT,
45 (u32 *)(*prcm)->prm_io_pmctrl, LDELAY))
46 return ERR_DEISOLATE_IO << isolate;
51 static int calibrate_iodelay(u32 base)
55 /* Configure REFCLK period */
56 reg = readl(base + CFG_REG_2_OFFSET);
57 reg &= ~CFG_REG_REFCLK_PERIOD_MASK;
58 reg |= CFG_REG_REFCLK_PERIOD;
59 writel(reg, base + CFG_REG_2_OFFSET);
61 /* Initiate Calibration */
62 clrsetbits_le32(base + CFG_REG_0_OFFSET, CFG_REG_CALIB_STRT_MASK,
63 CFG_REG_CALIB_STRT << CFG_REG_CALIB_STRT_SHIFT);
64 if (!wait_on_value(CFG_REG_CALIB_STRT_MASK, CFG_REG_CALIB_END,
65 (u32 *)(base + CFG_REG_0_OFFSET), LDELAY))
66 return ERR_CALIBRATE_IODELAY;
71 static int update_delay_mechanism(u32 base)
73 /* Initiate the reload of calibrated values. */
74 clrsetbits_le32(base + CFG_REG_0_OFFSET, CFG_REG_ROM_READ_MASK,
75 CFG_REG_ROM_READ_START);
76 if (!wait_on_value(CFG_REG_ROM_READ_MASK, CFG_REG_ROM_READ_END,
77 (u32 *)(base + CFG_REG_0_OFFSET), LDELAY))
78 return ERR_UPDATE_DELAY;
83 void __recalibrate_iodelay(struct pad_conf_entry const *pad, int npads)
87 /* IO recalibration should be done only from SRAM */
88 if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) {
89 puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n");
93 /* unlock IODELAY CONFIG registers */
94 writel(CFG_IODELAY_UNLOCK_KEY, (*ctrl)->iodelay_config_base +
97 ret = calibrate_iodelay((*ctrl)->iodelay_config_base);
101 ret = isolate_io(ISOLATE_IO);
105 ret = update_delay_mechanism((*ctrl)->iodelay_config_base);
109 /* Configure Mux settings */
110 do_set_mux32((*ctrl)->control_padconf_core_base, pad, npads);
112 ret = isolate_io(DEISOLATE_IO);
115 /* lock IODELAY CONFIG registers */
116 writel(CFG_IODELAY_LOCK_KEY, (*ctrl)->iodelay_config_base +
119 * UART cannot be used during IO recalibration sequence as IOs are in
120 * isolation. So error handling and debug prints are done after
121 * complete IO delay recalibration sequence
124 case ERR_CALIBRATE_IODELAY:
125 puts("IODELAY: IO delay calibration sequence failed\n");
128 puts("IODELAY: Isolation of Device IOs failed\n");
130 case ERR_UPDATE_DELAY:
131 puts("IODELAY: Delay mechanism update with new calibrated values failed\n");
133 case ERR_DEISOLATE_IO:
134 puts("IODELAY: De-isolation of Device IOs failed\n");
137 debug("IODELAY: IO delay recalibration successfully completed\n");