1 /* 2 * (C) Copyright 2015 3 * Texas Instruments Incorporated, <www.ti.com> 4 * 5 * Lokesh Vutla <lokeshvutla@ti.com> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 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/arch/mux_dra7xx.h> 17 #include <asm/omap_common.h> 18 19 static int isolate_io(u32 isolate) 20 { 21 if (isolate) { 22 clrsetbits_le32((*ctrl)->control_pbias, SDCARD_PWRDNZ, 23 SDCARD_PWRDNZ); 24 clrsetbits_le32((*ctrl)->control_pbias, SDCARD_BIAS_PWRDNZ, 25 SDCARD_BIAS_PWRDNZ); 26 } 27 28 /* Override control on ISOCLKIN signal to IO pad ring. */ 29 clrsetbits_le32((*prcm)->prm_io_pmctrl, PMCTRL_ISOCLK_OVERRIDE_MASK, 30 PMCTRL_ISOCLK_OVERRIDE_CTRL); 31 if (!wait_on_value(PMCTRL_ISOCLK_STATUS_MASK, PMCTRL_ISOCLK_STATUS_MASK, 32 (u32 *)(*prcm)->prm_io_pmctrl, LDELAY)) 33 return ERR_DEISOLATE_IO << isolate; 34 35 /* Isolate/Deisolate IO */ 36 clrsetbits_le32((*ctrl)->ctrl_core_sma_sw_0, CTRL_ISOLATE_MASK, 37 isolate << CTRL_ISOLATE_SHIFT); 38 /* Dummy read to add delay t > 10ns */ 39 readl((*ctrl)->ctrl_core_sma_sw_0); 40 41 /* Return control on ISOCLKIN to hardware */ 42 clrsetbits_le32((*prcm)->prm_io_pmctrl, PMCTRL_ISOCLK_OVERRIDE_MASK, 43 PMCTRL_ISOCLK_NOT_OVERRIDE_CTRL); 44 if (!wait_on_value(PMCTRL_ISOCLK_STATUS_MASK, 45 0 << PMCTRL_ISOCLK_STATUS_SHIFT, 46 (u32 *)(*prcm)->prm_io_pmctrl, LDELAY)) 47 return ERR_DEISOLATE_IO << isolate; 48 49 return 0; 50 } 51 52 static int calibrate_iodelay(u32 base) 53 { 54 u32 reg; 55 56 /* Configure REFCLK period */ 57 reg = readl(base + CFG_REG_2_OFFSET); 58 reg &= ~CFG_REG_REFCLK_PERIOD_MASK; 59 reg |= CFG_REG_REFCLK_PERIOD; 60 writel(reg, base + CFG_REG_2_OFFSET); 61 62 /* Initiate Calibration */ 63 clrsetbits_le32(base + CFG_REG_0_OFFSET, CFG_REG_CALIB_STRT_MASK, 64 CFG_REG_CALIB_STRT << CFG_REG_CALIB_STRT_SHIFT); 65 if (!wait_on_value(CFG_REG_CALIB_STRT_MASK, CFG_REG_CALIB_END, 66 (u32 *)(base + CFG_REG_0_OFFSET), LDELAY)) 67 return ERR_CALIBRATE_IODELAY; 68 69 return 0; 70 } 71 72 static int update_delay_mechanism(u32 base) 73 { 74 /* Initiate the reload of calibrated values. */ 75 clrsetbits_le32(base + CFG_REG_0_OFFSET, CFG_REG_ROM_READ_MASK, 76 CFG_REG_ROM_READ_START); 77 if (!wait_on_value(CFG_REG_ROM_READ_MASK, CFG_REG_ROM_READ_END, 78 (u32 *)(base + CFG_REG_0_OFFSET), LDELAY)) 79 return ERR_UPDATE_DELAY; 80 81 return 0; 82 } 83 84 static u32 calculate_delay(u32 base, u16 offset, u16 den) 85 { 86 u16 refclk_period, dly_cnt, ref_cnt; 87 u32 reg, q, r; 88 89 refclk_period = readl(base + CFG_REG_2_OFFSET) & 90 CFG_REG_REFCLK_PERIOD_MASK; 91 92 reg = readl(base + offset); 93 dly_cnt = (reg & CFG_REG_DLY_CNT_MASK) >> CFG_REG_DLY_CNT_SHIFT; 94 ref_cnt = (reg & CFG_REG_REF_CNT_MASK) >> CFG_REG_REF_CNT_SHIFT; 95 96 if (!dly_cnt || !den) 97 return 0; 98 99 /* 100 * To avoid overflow and integer truncation, delay value 101 * is calculated as quotient + remainder. 102 */ 103 q = 5 * ((ref_cnt * refclk_period) / (dly_cnt * den)); 104 r = (10 * ((ref_cnt * refclk_period) % (dly_cnt * den))) / 105 (2 * dly_cnt * den); 106 107 return q + r; 108 } 109 110 static u32 get_cfg_reg(u16 a_delay, u16 g_delay, u32 cpde, u32 fpde) 111 { 112 u32 g_delay_coarse, g_delay_fine; 113 u32 a_delay_coarse, a_delay_fine; 114 u32 c_elements, f_elements; 115 u32 total_delay, reg = 0; 116 117 g_delay_coarse = g_delay / 920; 118 g_delay_fine = ((g_delay % 920) * 10) / 60; 119 120 a_delay_coarse = a_delay / cpde; 121 a_delay_fine = ((a_delay % cpde) * 10) / fpde; 122 123 c_elements = g_delay_coarse + a_delay_coarse; 124 f_elements = (g_delay_fine + a_delay_fine) / 10; 125 126 if (f_elements > 22) { 127 total_delay = c_elements * cpde + f_elements * fpde; 128 129 c_elements = total_delay / cpde; 130 f_elements = (total_delay % cpde) / fpde; 131 } 132 133 reg = (c_elements << CFG_X_COARSE_DLY_SHIFT) & CFG_X_COARSE_DLY_MASK; 134 reg |= (f_elements << CFG_X_FINE_DLY_SHIFT) & CFG_X_FINE_DLY_MASK; 135 reg |= CFG_X_SIGNATURE << CFG_X_SIGNATURE_SHIFT; 136 reg |= CFG_X_LOCK << CFG_X_LOCK_SHIFT; 137 138 return reg; 139 } 140 141 int do_set_iodelay(u32 base, struct iodelay_cfg_entry const *array, 142 int niodelays) 143 { 144 struct iodelay_cfg_entry *iodelay = (struct iodelay_cfg_entry *)array; 145 u32 reg, cpde, fpde, i; 146 147 if (!niodelays) 148 return 0; 149 150 cpde = calculate_delay((*ctrl)->iodelay_config_base, CFG_REG_3_OFFSET, 151 88); 152 if (!cpde) 153 return ERR_CPDE; 154 155 fpde = calculate_delay((*ctrl)->iodelay_config_base, CFG_REG_4_OFFSET, 156 264); 157 if (!fpde) 158 return ERR_FPDE; 159 160 for (i = 0; i < niodelays; i++, iodelay++) { 161 reg = get_cfg_reg(iodelay->a_delay, iodelay->g_delay, cpde, 162 fpde); 163 writel(reg, base + iodelay->offset); 164 } 165 166 return 0; 167 } 168 169 int __recalibrate_iodelay_start(void) 170 { 171 int ret = 0; 172 173 /* IO recalibration should be done only from SRAM */ 174 if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) { 175 puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n"); 176 return -1; 177 } 178 179 /* unlock IODELAY CONFIG registers */ 180 writel(CFG_IODELAY_UNLOCK_KEY, (*ctrl)->iodelay_config_base + 181 CFG_REG_8_OFFSET); 182 183 ret = calibrate_iodelay((*ctrl)->iodelay_config_base); 184 if (ret) 185 goto err; 186 187 ret = isolate_io(ISOLATE_IO); 188 if (ret) 189 goto err; 190 191 ret = update_delay_mechanism((*ctrl)->iodelay_config_base); 192 193 err: 194 return ret; 195 } 196 197 void __recalibrate_iodelay_end(int ret) 198 { 199 200 /* IO recalibration should be done only from SRAM */ 201 if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) { 202 puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n"); 203 return; 204 } 205 206 if (!ret) 207 ret = isolate_io(DEISOLATE_IO); 208 209 /* lock IODELAY CONFIG registers */ 210 writel(CFG_IODELAY_LOCK_KEY, (*ctrl)->iodelay_config_base + 211 CFG_REG_8_OFFSET); 212 213 /* 214 * UART cannot be used during IO recalibration sequence as IOs are in 215 * isolation. So error handling and debug prints are done after 216 * complete IO delay recalibration sequence 217 */ 218 switch (ret) { 219 case ERR_CALIBRATE_IODELAY: 220 puts("IODELAY: IO delay calibration sequence failed\n"); 221 break; 222 case ERR_ISOLATE_IO: 223 puts("IODELAY: Isolation of Device IOs failed\n"); 224 break; 225 case ERR_UPDATE_DELAY: 226 puts("IODELAY: Delay mechanism update with new calibrated values failed\n"); 227 break; 228 case ERR_DEISOLATE_IO: 229 puts("IODELAY: De-isolation of Device IOs failed\n"); 230 break; 231 case ERR_CPDE: 232 puts("IODELAY: CPDE calculation failed\n"); 233 break; 234 case ERR_FPDE: 235 puts("IODELAY: FPDE calculation failed\n"); 236 break; 237 case -1: 238 puts("IODELAY: Wrong Context call?\n"); 239 break; 240 default: 241 debug("IODELAY: IO delay recalibration successfully completed\n"); 242 } 243 244 return; 245 } 246 247 void __recalibrate_iodelay(struct pad_conf_entry const *pad, int npads, 248 struct iodelay_cfg_entry const *iodelay, 249 int niodelays) 250 { 251 int ret = 0; 252 253 /* IO recalibration should be done only from SRAM */ 254 if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) { 255 puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n"); 256 return; 257 } 258 259 ret = __recalibrate_iodelay_start(); 260 if (ret) 261 goto err; 262 263 /* Configure Mux settings */ 264 do_set_mux32((*ctrl)->control_padconf_core_base, pad, npads); 265 266 /* Configure Manual IO timing modes */ 267 ret = do_set_iodelay((*ctrl)->iodelay_config_base, iodelay, niodelays); 268 if (ret) 269 goto err; 270 271 err: 272 __recalibrate_iodelay_end(ret); 273 274 } 275