⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 4xx_ibm_ddr2_autocalib.c

📁 最新版的u-boot,2008-10-18发布
💻 C
📖 第 1 页 / 共 3 页
字号:
	int bxcr_num;	int rffd_average;	int pass;	u32 passed = 0;	int in_window;	struct autocal_regs curr_win_min;	struct autocal_regs curr_win_max;	struct autocal_regs best_win_min;	struct autocal_regs best_win_max;	struct autocal_regs loop_win_min;	struct autocal_regs loop_win_max;#ifdef DEBUG	ulong temp;#endif	ulong rdcc;	char slash[] = "\\|/-\\|/-";	int loopi = 0;	/* start */	in_window = 0;	memset(&curr_win_min, 0, sizeof(curr_win_min));	memset(&curr_win_max, 0, sizeof(curr_win_max));	memset(&best_win_min, 0, sizeof(best_win_min));	memset(&best_win_max, 0, sizeof(best_win_max));	memset(&loop_win_min, 0, sizeof(loop_win_min));	memset(&loop_win_max, 0, sizeof(loop_win_max));	rdcc = 0;	/*	 * Program RDCC register	 * Read sample cycle auto-update enable	 */	mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T1 | SDRAM_RDCC_RSAE_ENABLE);#ifdef DEBUG	mfsdram(SDRAM_RDCC, temp);	debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp);	mfsdram(SDRAM_RTSR, temp);	debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp);	mfsdram(SDRAM_FCSR, temp);	debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp);#endif	/*	 * Program RQDC register	 * Internal DQS delay mechanism enable	 */	mtsdram(SDRAM_RQDC,		SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00));#ifdef DEBUG	mfsdram(SDRAM_RQDC, temp);	debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp);#endif	/*	 * Program RFDC register	 * Set Feedback Fractional Oversample	 * Auto-detect read sample cycle enable	 */	mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |		SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0));#ifdef DEBUG	mfsdram(SDRAM_RFDC, temp);	debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp);#endif	putc(' ');	for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {		mfsdram(SDRAM_RQDC, rqdc_reg);		rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);		mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));		putc('\b');		putc(slash[loopi++ % 8]);		curr_win_min.rffd = 0;		curr_win_max.rffd = 0;		in_window = 0;		for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {			mfsdram(SDRAM_RFDC, rfdc_reg);			rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);			mtsdram(SDRAM_RFDC,				    rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));			for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {				mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);				/* Banks enabled */				if (bxcf & SDRAM_BXCF_M_BE_MASK) {					/* Bank is enabled */					membase = get_membase(bxcr_num);					pass = short_mem_test(membase);				} /* if bank enabled */			} /* for bxcr_num */			/* If this value passed update RFFD windows */			if (pass && !in_window) { /* at the start of window */				in_window = 1;				curr_win_min.rffd = curr_win_max.rffd = rffd;				curr_win_min.rqfd = curr_win_max.rqfd = rqfd;				mfsdram(SDRAM_RDCC, rdcc); /*record this value*/			} else if (!pass && in_window) { /* at end of window */				in_window = 0;			} else if (pass && in_window) { /* within the window */				curr_win_max.rffd = rffd;				curr_win_max.rqfd = rqfd;			}			/* else if (!pass && !in_window)				skip - no pass, not currently in a window */			if (in_window) {				if ((curr_win_max.rffd - curr_win_min.rffd) >				    (best_win_max.rffd - best_win_min.rffd)) {					best_win_min.rffd = curr_win_min.rffd;					best_win_max.rffd = curr_win_max.rffd;					best_win_min.rqfd = curr_win_min.rqfd;					best_win_max.rqfd = curr_win_max.rqfd;					cal->rdcc	  = rdcc;				}				passed = 1;			}		} /* RFDC.RFFD */		/*		 * save-off the best window results of the RFDC.RFFD		 * for this RQDC.RQFD setting		 */		/*		 * if (just ended RFDC.RFDC loop pass window) >		 *	(prior RFDC.RFFD loop pass window)		 */		if ((best_win_max.rffd - best_win_min.rffd) >		    (loop_win_max.rffd - loop_win_min.rffd)) {			loop_win_min.rffd = best_win_min.rffd;			loop_win_max.rffd = best_win_max.rffd;			loop_win_min.rqfd = rqfd;			loop_win_max.rqfd = rqfd;			debug("RQFD.min 0x%08x, RQFD.max 0x%08x, "			      "RFFD.min 0x%08x, RFFD.max 0x%08x\n",					loop_win_min.rqfd, loop_win_max.rqfd,					loop_win_min.rffd, loop_win_max.rffd);		}	} /* RQDC.RQFD */	putc('\b');	debug("\n");	if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) &&	    (best_win_min.rffd == 0) && (best_win_max.rffd == 0) &&	    (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) {		passed = 0;	}	/*	 * Need to program RQDC before RFDC.	 */	debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd);	debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd);	rqfd_average = loop_win_max.rqfd;	if (rqfd_average < 0)		rqfd_average = 0;	if (rqfd_average > SDRAM_RQDC_RQFD_MAX)		rqfd_average = SDRAM_RQDC_RQFD_MAX;	debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average);	mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |				SDRAM_RQDC_RQFD_ENCODE(rqfd_average));	debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd);	debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd);	rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2);	if (rffd_average < 0)		rffd_average = 0;	if (rffd_average > SDRAM_RFDC_RFFD_MAX)		rffd_average = SDRAM_RFDC_RFFD_MAX;	debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average);	mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));	/* if something passed, then return the size of the largest window */	if (passed != 0) {		passed		= loop_win_max.rffd - loop_win_min.rffd;		cal->rqfd	= rqfd_average;		cal->rffd	= rffd_average;		cal->rffd_min	= loop_win_min.rffd;		cal->rffd_max	= loop_win_max.rffd;	}	return (u32)passed;}#else	/* !defined(CONFIG_PPC4xx_DDR_METHOD_A) *//*-----------------------------------------------------------------------------+| program_DQS_calibration_methodB.+-----------------------------------------------------------------------------*/static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal){	u32 pass_result = 0;#ifdef DEBUG	ulong temp;#endif	/*	 * Program RDCC register	 * Read sample cycle auto-update enable	 */	mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T2 | SDRAM_RDCC_RSAE_ENABLE);#ifdef DEBUG	mfsdram(SDRAM_RDCC, temp);	debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);#endif	/*	 * Program RQDC register	 * Internal DQS delay mechanism enable	 */	mtsdram(SDRAM_RQDC,#if defined(CONFIG_DDR_RQDC_START_VAL)			SDRAM_RQDC_RQDE_ENABLE |			    SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL));#else			SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38));#endif#ifdef DEBUG	mfsdram(SDRAM_RQDC, temp);	debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp);#endif	/*	 * Program RFDC register	 * Set Feedback Fractional Oversample	 * Auto-detect read sample cycle enable	 */	mtsdram(SDRAM_RFDC,	SDRAM_RFDC_ARSE_ENABLE |				SDRAM_RFDC_RFOS_ENCODE(0) |				SDRAM_RFDC_RFFD_ENCODE(0));#ifdef DEBUG	mfsdram(SDRAM_RFDC, temp);	debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp);#endif	pass_result = DQS_calibration_methodB(ddrcal);	return pass_result;}/* * DQS_calibration_methodB() * * Autocalibration Method B * * ARRAY [Entire DQS Range] DQS_Valid_Window ;       initialized to all zeros * ARRAY [Entire Feedback Range] FDBK_Valid_Window;  initialized to all zeros * MEMWRITE(addr, expected_data); * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38). * *  for (j = 0; j < Entire Feedback Range; j++) { *      MEMREAD(addr, actual_data); *       if (actual_data == expected_data) { *           FDBK_Valid_Window[j] = 1; *       } * } * * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window. * * for (i = 0; i < Entire DQS Range; i++) { *     MEMREAD(addr, actual_data); *     if (actual_data == expected_data) { *         DQS_Valid_Window[i] = 1; *      } * } * * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window. *//*-----------------------------------------------------------------------------+| DQS_calibration_methodB.+-----------------------------------------------------------------------------*/static u32 DQS_calibration_methodB(struct ddrautocal *cal){	ulong rfdc_reg;	ulong rffd;	ulong rqdc_reg;	ulong rqfd;	ulong rdcc;	u32 *membase;	ulong bxcf;	int rqfd_average;	int bxcr_num;	int rffd_average;	int pass;	uint passed = 0;	int in_window;	u32 curr_win_min, curr_win_max;	u32 best_win_min, best_win_max;	u32 size = 0;	/*------------------------------------------------------------------	 | Test to determine the best read clock delay tuning bits.	 |	 | Before the DDR controller can be used, the read clock delay needs to	 | be set.  This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].	 | This value cannot be hardcoded into the program because it changes	 | depending on the board's setup and environment.	 | To do this, all delay values are tested to see if they	 | work or not.  By doing this, you get groups of fails with groups of	 | passing values.  The idea is to find the start and end of a passing	 | window and take the center of it to use as the read clock delay.	 |	 | A failure has to be seen first so that when we hit a pass, we know	 | that it is truely the start of the window.  If we get passing values	 | to start off with, we don't know if we are at the start of the window	 |	 | The code assumes that a failure will always be found.	 | If a failure is not found, there is no easy way to get the middle	 | of the passing window.  I guess we can pretty much pick any value	 | but some values will be better than others.  Since the lowest speed	 | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),	 | from experimentation it is safe to say you will always have a failure	 +-----------------------------------------------------------------*/	debug("\n\n");	in_window = 0;	rdcc = 0;	curr_win_min = curr_win_max = 0;	best_win_min = best_win_max = 0;	for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {		mfsdram(SDRAM_RFDC, rfdc_reg);		rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);		mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));		pass = 1;		for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {			mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);			/* Banks enabled */			if (bxcf & SDRAM_BXCF_M_BE_MASK) {				/* Bank is enabled */				membase = get_membase(bxcr_num);				pass &= short_mem_test(membase);			} /* if bank enabled */		} /* for bxcf_num */		/* If this value passed */		if (pass && !in_window) {	/* start of passing window */			in_window = 1;			curr_win_min = curr_win_max = rffd;			mfsdram(SDRAM_RDCC, rdcc);	/* record this value */		} else if (!pass && in_window) {	/* end passing window */			in_window = 0;		} else if (pass && in_window) {	/* within the passing window */			curr_win_max = rffd;		}		if (in_window) {			if ((curr_win_max - curr_win_min) >			    (best_win_max - best_win_min)) {				best_win_min = curr_win_min;				best_win_max = curr_win_max;				cal->rdcc    = rdcc;			}			passed = 1;		}	} /* for rffd */	if ((best_win_min == 0) && (best_win_max == 0))		passed = 0;	else		size = best_win_max - best_win_min;	debug("RFFD Min: 0x%x\n", best_win_min);	debug("RFFD Max: 0x%x\n", best_win_max);	rffd_average = ((best_win_min + best_win_max) / 2);	cal->rffd_min = best_win_min;	cal->rffd_max = best_win_max;	if (rffd_average < 0)		rffd_average = 0;	if (rffd_average > SDRAM_RFDC_RFFD_MAX)		rffd_average = SDRAM_RFDC_RFFD_MAX;	mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));	rffd = rffd_average;	in_window = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -