瀏覽代碼

Fix timer code for ARM systems: make sure that udelay() does not
reset timers so it's save to use udelay() in timeout code.

wdenk 20 年之前
父節點
當前提交
101e8dfa2a

+ 3 - 0
CHANGELOG

@@ -2,6 +2,9 @@
 Changes for U-Boot 1.1.3:
 ======================================================================
 
+* Fix timer code for ARM systems: make sure that udelay() does not
+  reset timers so it's save to use udelay() in timeout code.
+
 * Patch by Mathias Küster, 23 Nov 2004:
   add udelay support for the mcf5282 cpu
 

+ 8 - 3
cpu/arm1136/interrupts.c

@@ -254,6 +254,8 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
+	ulong endtime;
+	signed long diff;
 
 	if (usec >= 1000) {			/* if "big" number, spread normalization to seconds */
 		tmo = usec / 1000;		/* start to normalize for usec to ticks per sec */
@@ -263,9 +265,12 @@ void udelay_masked (unsigned long usec)
 		tmo = usec * CFG_HZ;
 		tmo /= (1000*1000);
 	}
-	reset_timer_masked ();		/* set "advancing" timestamp to 0, set lastinc vaule */
-	while (get_timer_masked () < tmo) /* wait for time stamp to overtake tick number.*/
-		/* NOP */;
+	endtime = get_timer_masked () + tmo;
+
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 /*

+ 15 - 6
cpu/arm720t/interrupts.c

@@ -358,15 +358,24 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
+	ulong endtime;
+	signed long diff;
 
-	tmo = usec / 1000;
-	tmo *= CFG_HZ;
-	tmo /= 1000;
+	if (usec >= 1000) {
+		tmo = usec / 1000;
+		tmo *= CFG_HZ;
+		tmo /= 1000;
+	} else {
+		tmo = usec * CFG_HZ;
+		tmo /= (1000*1000);
+	}
 
-	reset_timer_masked ();
+	endtime = get_timer_masked () + tmo;
 
-	while (get_timer_masked () < tmo)
-		/*NOP*/;
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 #elif defined(CONFIG_S3C4510B)

+ 6 - 3
cpu/arm920t/imx/interrupts.c

@@ -81,10 +81,13 @@ ulong get_timer_masked (void)
 
 void udelay_masked (unsigned long usec)
 {
-	ulong start = get_timer_masked();
+	ulong endtime = get_timer_masked() + usec;
+	signed long diff;
 
-	while (get_timer_masked () - start < usec )
-		/*NOP*/;
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 void udelay (unsigned long usec)

+ 15 - 6
cpu/arm920t/s3c24x0/interrupts.c

@@ -137,15 +137,24 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
+	ulong endtime;
+	signed long diff;
 
-	tmo = usec / 1000;
-	tmo *= (timer_load_val * 100);
-	tmo /= 1000;
+	if (usec >= 1000) {
+		tmo = usec / 1000;
+		tmo *= (timer_load_val * 100);
+		tmo /= 1000;
+	} else {
+		tmo = usec * (timer_load_val * 100);
+		tmo /= (1000*1000);
+	}
 
-	reset_timer_masked ();
+	endtime = get_timer_masked () + tmo;
 
-	while (get_timer_masked () < tmo)
-		/*NOP*/;
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 /*

+ 9 - 5
cpu/arm925t/interrupts.c

@@ -275,20 +275,24 @@ void udelay_masked (unsigned long usec)
 #else
 
 	ulong tmo;
+	ulong endtime;
+	signed long diff;
 
-	if(usec >= 1000){		/* if "big" number, spread normalization to seconds */
+	if (usec >= 1000) {		/* if "big" number, spread normalization to seconds */
 		tmo = usec / 1000;	/* start to normalize for usec to ticks per sec */
 		tmo *= CFG_HZ;		/* find number of "ticks" to wait to achieve target */
 		tmo /= 1000;		/* finish normalize. */
-	}else{				/* else small number, don't kill it prior to HZ multiply */
+	} else {			/* else small number, don't kill it prior to HZ multiply */
 		tmo = usec * CFG_HZ;
 		tmo /= (1000*1000);
 	}
 
-	reset_timer_masked ();	/* set "advancing" timestamp to 0, set lastdec vaule */
+	endtime = get_timer_masked () + tmo;
 
-	while (get_timer_masked () < tmo) /* wait for time stamp to overtake tick number.*/
-		/*NOP*/;
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 #endif
 }
 

+ 26 - 22
cpu/arm926ejs/interrupts.c

@@ -26,7 +26,7 @@
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
@@ -116,15 +116,15 @@ void show_regs (struct pt_regs *regs)
 
 	flags = condition_codes (regs);
 
-	printf ("pc : [<%08lx>]    lr : [<%08lx>]\n"
-		"sp : %08lx  ip : %08lx  fp : %08lx\n",
+	printf ("pc : [<%08lx>]	   lr : [<%08lx>]\n"
+		"sp : %08lx  ip : %08lx	 fp : %08lx\n",
 		instruction_pointer (regs),
 		regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
-	printf ("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+	printf ("r10: %08lx  r9 : %08lx	 r8 : %08lx\n",
 		regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
-	printf ("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+	printf ("r7 : %08lx  r6 : %08lx	 r5 : %08lx  r4 : %08lx\n",
 		regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
-	printf ("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+	printf ("r3 : %08lx  r2 : %08lx	 r1 : %08lx  r0 : %08lx\n",
 		regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
 	printf ("Flags: %c%c%c%c",
 		flags & CC_N_BIT ? 'N' : 'n',
@@ -242,17 +242,17 @@ void udelay (unsigned long usec)
 {
 	ulong tmo, tmp;
 
-	if(usec >= 1000){               /* if "big" number, spread normalization to seconds */
-		tmo = usec / 1000;      /* start to normalize for usec to ticks per sec */
-		tmo *= CFG_HZ;          /* find number of "ticks" to wait to achieve target */
-		tmo /= 1000;            /* finish normalize. */
-	}else{                          /* else small number, don't kill it prior to HZ multiply */
+	if(usec >= 1000){		/* if "big" number, spread normalization to seconds */
+		tmo = usec / 1000;	/* start to normalize for usec to ticks per sec */
+		tmo *= CFG_HZ;		/* find number of "ticks" to wait to achieve target */
+		tmo /= 1000;		/* finish normalize. */
+	}else{				/* else small number, don't kill it prior to HZ multiply */
 		tmo = usec * CFG_HZ;
 		tmo /= (1000*1000);
 	}
 
 	tmp = get_timer (0);		/* get current timestamp */
-	if( (tmo + tmp + 1) < tmp ) 	/* if setting this fordward will roll time stamp */
+	if( (tmo + tmp + 1) < tmp )	/* if setting this fordward will roll time stamp */
 		reset_timer_masked ();	/* reset "advancing" timestamp to 0, set lastdec value */
 	else
 		tmo += tmp;		/* else, set advancing stamp wake up time */
@@ -265,7 +265,7 @@ void reset_timer_masked (void)
 {
 	/* reset time */
 	lastdec = READ_TIMER;  /* capure current decrementer value time */
-	timestamp = 0;         /* start "advancing" time stamp from 0 */
+	timestamp = 0;	       /* start "advancing" time stamp from 0 */
 }
 
 ulong get_timer_masked (void)
@@ -292,20 +292,24 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
-
-	if(usec >= 1000){               /* if "big" number, spread normalization to seconds */
-		tmo = usec / 1000;      /* start to normalize for usec to ticks per sec */
-		tmo *= CFG_HZ;          /* find number of "ticks" to wait to achieve target */
-		tmo /= 1000;            /* finish normalize. */
-	}else{                          /* else small number, don't kill it prior to HZ multiply */
+	ulong endtime;
+	signed long diff;
+
+	if (usec >= 1000) {		/* if "big" number, spread normalization to seconds */
+		tmo = usec / 1000;	/* start to normalize for usec to ticks per sec */
+		tmo *= CFG_HZ;		/* find number of "ticks" to wait to achieve target */
+		tmo /= 1000;		/* finish normalize. */
+	} else {			/* else small number, don't kill it prior to HZ multiply */
 		tmo = usec * CFG_HZ;
 		tmo /= (1000*1000);
 	}
 
-	reset_timer_masked ();	/* set "advancing" timestamp to 0, set lastdec vaule */
+	endtime = get_timer_masked () + tmo;
 
-	while (get_timer_masked () < tmo) /* wait for time stamp to overtake tick number.*/
-		/*NOP*/;
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 /*

+ 7 - 8
cpu/at91rm9200/interrupts.c

@@ -231,20 +231,19 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
+	ulong endtime;
+	signed long diff;
 
-#if 0 /* doesn't work for usec < 1000 */
-	tmo = usec / 1000;
-	tmo *= CFG_HZ_CLOCK;
-#else
 	tmo = CFG_HZ_CLOCK / 1000;
 	tmo *= usec;
-#endif
 	tmo /= 1000;
 
-	reset_timer_masked ();
+	endtime = get_timer_raw () + tmo;
 
-	while (get_timer_raw () < tmo)
-		/*NOP*/;
+	do {
+		ulong now = get_timer_raw ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 /*

+ 3 - 3
cpu/at91rm9200/start.S

@@ -117,11 +117,11 @@ reset:
 
 #ifdef CONFIG_INIT_CRITICAL
 	/* scratch stack */
-	ldr 	r1, =0x00204000
+/****	ldr 	r1, =0x00204000		****/
 	/* Insure word alignment */
-	bic     r1, r1, #3
+/****	bic     r1, r1, #3		****/
 	/* Init stack SYS	 */
-	mov     sp, r1
+/****	mov     sp, r1			****/
 	/*
 	 * This does a lot more than just set up the memory, which
 	 * is why it's called lowlevelinit

+ 10 - 6
cpu/lh7a40x/interrupts.c

@@ -281,25 +281,29 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
+	ulong endtime;
+	signed long diff;
 
 	/* normalize */
 	if (usec >= 1000) {
 		tmo = usec / 1000;
 		tmo *= CFG_HZ;
 		tmo /= 1000;
-	}
-	else {
+	} else {
 		if (usec > 1) {
 			tmo = usec * CFG_HZ;
 			tmo /= (1000*1000);
-		}
-		else
+		} else {
 			tmo = 1;
+		}
 	}
 
-	reset_timer_masked ();
+	endtime = get_timer_masked () + tmo;
 
-	while (get_timer_masked () < tmo);
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 /*

+ 7 - 3
cpu/pxa/interrupts.c

@@ -190,6 +190,8 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
+	ulong endtime;
+	signed long diff;
 
 	if (usec >= 1000) {
 		tmo = usec / 1000;
@@ -200,10 +202,12 @@ void udelay_masked (unsigned long usec)
 		tmo /= (1000*1000);
 	}
 
-	reset_timer_masked ();
+	endtime = get_timer_masked () + tmo;
 
-	while (tmo >= get_timer_masked ())
-		/*NOP*/;
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 /*

+ 15 - 8
cpu/s3c44b0/interrupts.c

@@ -219,15 +219,22 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
+	ulong endtime;
+	signed long diff;
 
-	tmo = usec / 1000;
-	tmo *= CFG_HZ;
-	tmo /= 8;
-
-	tmo += get_timer (0);
+	if (usec >= 1000) {
+		tmo = usec / 1000;
+		tmo *= CFG_HZ;
+		tmo /= 8;
+	} else {
+		tmo = usec * CFG_HZ;
+		tmo /= (1000*8);
+	}
 
-	reset_timer_masked ();
+	endtime = get_timer(0) + tmo;
 
-	while (get_timer_masked () < tmo)
-		/*NOP*/;
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }

+ 18 - 9
cpu/sa1100/interrupts.c

@@ -206,15 +206,24 @@ ulong get_timer_masked (void)
 void udelay_masked (unsigned long usec)
 {
 	ulong tmo;
-
-	tmo = usec / 1000;
-	tmo *= CFG_HZ;
-	tmo /= 1000;
-
-	reset_timer_masked ();
-
-	while (tmo >= get_timer_masked ())
-		/*NOP*/;
+	ulong endtime;
+	signed long diff;
+
+	if (usec >= 1000) {
+		tmo = usec / 1000;
+		tmo *= CFG_HZ;
+		tmo /= 1000;
+	} else {
+		tmo = usec * CFG_HZ;
+		tmo /= (1000*1000);
+	}
+
+	endtime = get_timer_masked () + tmo;
+
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
 }
 
 /*

+ 2 - 2
include/configs/cmc_pu2.h

@@ -33,7 +33,7 @@
 
 /* ARM asynchronous clock */
 #define AT91C_MAIN_CLOCK	207360000	/* from 18.432 MHz crystal (18432000 / 4 * 45) */
-#define AT91C_MASTER_CLOCK	69120000	/* peripheral clock (AT91C_MASTER_CLOCK / 3) */
+#define AT91C_MASTER_CLOCK	(AT91C_MAIN_CLOCK/3)	/* peripheral clock */
 
 #define AT91_SLOW_CLOCK		32768	/* slow clock */
 
@@ -203,7 +203,7 @@ struct bd_info_ext {
 #endif	/* __ASSEMBLY__ */
 
 #define CFG_HZ 1000
-#define CFG_HZ_CLOCK AT91C_MASTER_CLOCK/2	/* AT91C_TC0_CMR is implicitly set to */
+#define CFG_HZ_CLOCK (AT91C_MASTER_CLOCK/2)	/* AT91C_TC0_CMR is implicitly set to */
 						/* AT91C_TC_TIMER_DIV1_CLOCK */
 
 #define CONFIG_STACKSIZE	(32*1024)	/* regular stack */