Home | History | Annotate | Download | only in omap5
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2015
      4  * Texas Instruments Incorporated, <www.ti.com>
      5  *
      6  * Lokesh Vutla <lokeshvutla (at) ti.com>
      7  */
      8 
      9 #include <common.h>
     10 #include <asm/utils.h>
     11 #include <asm/arch/dra7xx_iodelay.h>
     12 #include <asm/arch/omap.h>
     13 #include <asm/arch/sys_proto.h>
     14 #include <asm/arch/clock.h>
     15 #include <asm/arch/mux_dra7xx.h>
     16 #include <asm/omap_common.h>
     17 
     18 static int isolate_io(u32 isolate)
     19 {
     20 	if (isolate) {
     21 		clrsetbits_le32((*ctrl)->control_pbias, SDCARD_PWRDNZ,
     22 				SDCARD_PWRDNZ);
     23 		clrsetbits_le32((*ctrl)->control_pbias, SDCARD_BIAS_PWRDNZ,
     24 				SDCARD_BIAS_PWRDNZ);
     25 	}
     26 
     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;
     33 
     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);
     39 
     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;
     47 
     48 	return 0;
     49 }
     50 
     51 static int calibrate_iodelay(u32 base)
     52 {
     53 	u32 reg;
     54 
     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);
     60 
     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;
     67 
     68 	return 0;
     69 }
     70 
     71 static int update_delay_mechanism(u32 base)
     72 {
     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;
     79 
     80 	return 0;
     81 }
     82 
     83 static u32 calculate_delay(u32 base, u16 offset, u16 den)
     84 {
     85 	u16 refclk_period, dly_cnt, ref_cnt;
     86 	u32 reg, q, r;
     87 
     88 	refclk_period = readl(base + CFG_REG_2_OFFSET) &
     89 			      CFG_REG_REFCLK_PERIOD_MASK;
     90 
     91 	reg = readl(base + offset);
     92 	dly_cnt = (reg & CFG_REG_DLY_CNT_MASK) >> CFG_REG_DLY_CNT_SHIFT;
     93 	ref_cnt = (reg & CFG_REG_REF_CNT_MASK) >> CFG_REG_REF_CNT_SHIFT;
     94 
     95 	if (!dly_cnt || !den)
     96 		return 0;
     97 
     98 	/*
     99 	 * To avoid overflow and integer truncation, delay value
    100 	 * is calculated as quotient + remainder.
    101 	 */
    102 	q = 5 * ((ref_cnt * refclk_period) / (dly_cnt * den));
    103 	r = (10 * ((ref_cnt * refclk_period) % (dly_cnt * den))) /
    104 		(2 * dly_cnt * den);
    105 
    106 	return q + r;
    107 }
    108 
    109 static u32 get_cfg_reg(u16 a_delay, u16 g_delay, u32 cpde, u32 fpde)
    110 {
    111 	u32 g_delay_coarse, g_delay_fine;
    112 	u32 a_delay_coarse, a_delay_fine;
    113 	u32 c_elements, f_elements;
    114 	u32 total_delay, reg = 0;
    115 
    116 	g_delay_coarse = g_delay / 920;
    117 	g_delay_fine = ((g_delay % 920) * 10) / 60;
    118 
    119 	a_delay_coarse = a_delay / cpde;
    120 	a_delay_fine = ((a_delay % cpde) * 10) / fpde;
    121 
    122 	c_elements = g_delay_coarse + a_delay_coarse;
    123 	f_elements = (g_delay_fine + a_delay_fine) / 10;
    124 
    125 	if (f_elements > 22) {
    126 		total_delay = c_elements * cpde + f_elements * fpde;
    127 
    128 		c_elements = total_delay / cpde;
    129 		f_elements = (total_delay % cpde) / fpde;
    130 	}
    131 
    132 	reg = (c_elements << CFG_X_COARSE_DLY_SHIFT) & CFG_X_COARSE_DLY_MASK;
    133 	reg |= (f_elements << CFG_X_FINE_DLY_SHIFT) & CFG_X_FINE_DLY_MASK;
    134 	reg |= CFG_X_SIGNATURE << CFG_X_SIGNATURE_SHIFT;
    135 	reg |= CFG_X_LOCK << CFG_X_LOCK_SHIFT;
    136 
    137 	return reg;
    138 }
    139 
    140 int do_set_iodelay(u32 base, struct iodelay_cfg_entry const *array,
    141 		   int niodelays)
    142 {
    143 	struct iodelay_cfg_entry *iodelay = (struct iodelay_cfg_entry *)array;
    144 	u32 reg, cpde, fpde, i;
    145 
    146 	if (!niodelays)
    147 		return 0;
    148 
    149 	cpde = calculate_delay((*ctrl)->iodelay_config_base, CFG_REG_3_OFFSET,
    150 			       88);
    151 	if (!cpde)
    152 		return ERR_CPDE;
    153 
    154 	fpde = calculate_delay((*ctrl)->iodelay_config_base, CFG_REG_4_OFFSET,
    155 			       264);
    156 	if (!fpde)
    157 		return ERR_FPDE;
    158 
    159 	for (i = 0; i < niodelays; i++, iodelay++) {
    160 		reg = get_cfg_reg(iodelay->a_delay, iodelay->g_delay, cpde,
    161 				  fpde);
    162 		writel(reg, base + iodelay->offset);
    163 	}
    164 
    165 	return 0;
    166 }
    167 
    168 int __recalibrate_iodelay_start(void)
    169 {
    170 	int ret = 0;
    171 
    172 	/* IO recalibration should be done only from SRAM */
    173 	if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) {
    174 		puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n");
    175 		return -1;
    176 	}
    177 
    178 	/* unlock IODELAY CONFIG registers */
    179 	writel(CFG_IODELAY_UNLOCK_KEY, (*ctrl)->iodelay_config_base +
    180 	       CFG_REG_8_OFFSET);
    181 
    182 	ret = calibrate_iodelay((*ctrl)->iodelay_config_base);
    183 	if (ret)
    184 		goto err;
    185 
    186 	ret = isolate_io(ISOLATE_IO);
    187 	if (ret)
    188 		goto err;
    189 
    190 	ret = update_delay_mechanism((*ctrl)->iodelay_config_base);
    191 
    192 err:
    193 	return ret;
    194 }
    195 
    196 void __recalibrate_iodelay_end(int ret)
    197 {
    198 
    199 	/* IO recalibration should be done only from SRAM */
    200 	if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) {
    201 		puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n");
    202 		return;
    203 	}
    204 
    205 	if (!ret)
    206 		ret = isolate_io(DEISOLATE_IO);
    207 
    208 	/* lock IODELAY CONFIG registers */
    209 	writel(CFG_IODELAY_LOCK_KEY, (*ctrl)->iodelay_config_base +
    210 	       CFG_REG_8_OFFSET);
    211 
    212 	/*
    213 	 * UART cannot be used during IO recalibration sequence as IOs are in
    214 	 * isolation. So error handling and debug prints are done after
    215 	 * complete IO delay recalibration sequence
    216 	 */
    217 	switch (ret) {
    218 	case ERR_CALIBRATE_IODELAY:
    219 		puts("IODELAY: IO delay calibration sequence failed\n");
    220 		break;
    221 	case ERR_ISOLATE_IO:
    222 		puts("IODELAY: Isolation of Device IOs failed\n");
    223 		break;
    224 	case ERR_UPDATE_DELAY:
    225 		puts("IODELAY: Delay mechanism update with new calibrated values failed\n");
    226 		break;
    227 	case ERR_DEISOLATE_IO:
    228 		puts("IODELAY: De-isolation of Device IOs failed\n");
    229 		break;
    230 	case ERR_CPDE:
    231 		puts("IODELAY: CPDE calculation failed\n");
    232 		break;
    233 	case ERR_FPDE:
    234 		puts("IODELAY: FPDE calculation failed\n");
    235 		break;
    236 	case -1:
    237 		puts("IODELAY: Wrong Context call?\n");
    238 		break;
    239 	default:
    240 		debug("IODELAY: IO delay recalibration successfully completed\n");
    241 	}
    242 
    243 	return;
    244 }
    245 
    246 void __recalibrate_iodelay(struct pad_conf_entry const *pad, int npads,
    247 			   struct iodelay_cfg_entry const *iodelay,
    248 			   int niodelays)
    249 {
    250 	int ret = 0;
    251 
    252 	/* IO recalibration should be done only from SRAM */
    253 	if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) {
    254 		puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n");
    255 		return;
    256 	}
    257 
    258 	ret = __recalibrate_iodelay_start();
    259 	if (ret)
    260 		goto err;
    261 
    262 	/* Configure Mux settings */
    263 	do_set_mux32((*ctrl)->control_padconf_core_base, pad, npads);
    264 
    265 	/* Configure Manual IO timing modes */
    266 	ret = do_set_iodelay((*ctrl)->iodelay_config_base, iodelay, niodelays);
    267 	if (ret)
    268 		goto err;
    269 
    270 err:
    271 	__recalibrate_iodelay_end(ret);
    272 
    273 }
    274 
    275 void late_recalibrate_iodelay(struct pad_conf_entry const *pad, int npads,
    276 			      struct iodelay_cfg_entry const *iodelay,
    277 			      int niodelays)
    278 {
    279 	int ret = 0;
    280 
    281 	/* unlock IODELAY CONFIG registers */
    282 	writel(CFG_IODELAY_UNLOCK_KEY, (*ctrl)->iodelay_config_base +
    283 	       CFG_REG_8_OFFSET);
    284 
    285 	ret = calibrate_iodelay((*ctrl)->iodelay_config_base);
    286 	if (ret)
    287 		goto err;
    288 
    289 	ret = update_delay_mechanism((*ctrl)->iodelay_config_base);
    290 
    291 	/* Configure Mux settings */
    292 	do_set_mux32((*ctrl)->control_padconf_core_base, pad, npads);
    293 
    294 	/* Configure Manual IO timing modes */
    295 	ret = do_set_iodelay((*ctrl)->iodelay_config_base, iodelay, niodelays);
    296 	if (ret)
    297 		goto err;
    298 
    299 err:
    300 	/* lock IODELAY CONFIG registers */
    301 	writel(CFG_IODELAY_LOCK_KEY, (*ctrl)->iodelay_config_base +
    302 	       CFG_REG_8_OFFSET);
    303 }
    304