From 101e8dfa2a8b045c6655bf2b3d6fba8d378453cd Mon Sep 17 00:00:00 2001 From: wdenk Date: Mon, 4 Apr 2005 12:08:28 +0000 Subject: [PATCH] Fix timer code for ARM systems: make sure that udelay() does not reset timers so it's save to use udelay() in timeout code. --- CHANGELOG | 3 +++ cpu/arm1136/interrupts.c | 11 ++++++--- cpu/arm720t/interrupts.c | 21 +++++++++++++----- cpu/arm920t/imx/interrupts.c | 9 +++++--- cpu/arm920t/s3c24x0/interrupts.c | 21 +++++++++++++----- cpu/arm925t/interrupts.c | 14 +++++++----- cpu/arm926ejs/interrupts.c | 48 ++++++++++++++++++++++------------------ cpu/at91rm9200/interrupts.c | 15 ++++++------- cpu/at91rm9200/start.S | 6 ++--- cpu/lh7a40x/interrupts.c | 16 +++++++++----- cpu/pxa/interrupts.c | 10 ++++++--- cpu/s3c44b0/interrupts.c | 23 ++++++++++++------- cpu/sa1100/interrupts.c | 27 ++++++++++++++-------- include/configs/cmc_pu2.h | 4 ++-- 14 files changed, 144 insertions(+), 84 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 73fb943..ba250b6 100644 --- a/CHANGELOG +++ b/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 diff --git a/cpu/arm1136/interrupts.c b/cpu/arm1136/interrupts.c index c80d9a5..23236dc 100644 --- a/cpu/arm1136/interrupts.c +++ b/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); } /* diff --git a/cpu/arm720t/interrupts.c b/cpu/arm720t/interrupts.c index a7ea70a..ab28e60 100644 --- a/cpu/arm720t/interrupts.c +++ b/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) diff --git a/cpu/arm920t/imx/interrupts.c b/cpu/arm920t/imx/interrupts.c index 12ae2fa..2f2e754 100644 --- a/cpu/arm920t/imx/interrupts.c +++ b/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) diff --git a/cpu/arm920t/s3c24x0/interrupts.c b/cpu/arm920t/s3c24x0/interrupts.c index f581d6d..868621f 100644 --- a/cpu/arm920t/s3c24x0/interrupts.c +++ b/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); } /* diff --git a/cpu/arm925t/interrupts.c b/cpu/arm925t/interrupts.c index ea4aa3b..57bb4ea 100644 --- a/cpu/arm925t/interrupts.c +++ b/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 } diff --git a/cpu/arm926ejs/interrupts.c b/cpu/arm926ejs/interrupts.c index 062515e..ae8082d 100644 --- a/cpu/arm926ejs/interrupts.c +++ b/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); } /* diff --git a/cpu/at91rm9200/interrupts.c b/cpu/at91rm9200/interrupts.c index f15c583..cccc405 100644 --- a/cpu/at91rm9200/interrupts.c +++ b/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); } /* diff --git a/cpu/at91rm9200/start.S b/cpu/at91rm9200/start.S index e897e6b..1881ab1 100644 --- a/cpu/at91rm9200/start.S +++ b/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 diff --git a/cpu/lh7a40x/interrupts.c b/cpu/lh7a40x/interrupts.c index 3c2dc4f..23d8039 100644 --- a/cpu/lh7a40x/interrupts.c +++ b/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); } /* diff --git a/cpu/pxa/interrupts.c b/cpu/pxa/interrupts.c index b335a82..0479a10 100644 --- a/cpu/pxa/interrupts.c +++ b/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); } /* diff --git a/cpu/s3c44b0/interrupts.c b/cpu/s3c44b0/interrupts.c index dea8118..5d2c13d 100644 --- a/cpu/s3c44b0/interrupts.c +++ b/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); } diff --git a/cpu/sa1100/interrupts.c b/cpu/sa1100/interrupts.c index 93a78d7..b393e0d 100644 --- a/cpu/sa1100/interrupts.c +++ b/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); } /* diff --git a/include/configs/cmc_pu2.h b/include/configs/cmc_pu2.h index ef2d1b7..96b7148 100644 --- a/include/configs/cmc_pu2.h +++ b/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 */