Fix timer code for ARM systems: make sure that udelay() does not
authorwdenk <wdenk>
Mon, 4 Apr 2005 12:08:28 +0000 (12:08 +0000)
committerwdenk <wdenk>
Mon, 4 Apr 2005 12:08:28 +0000 (12:08 +0000)
reset timers so it's save to use udelay() in timeout code.

14 files changed:
CHANGELOG
cpu/arm1136/interrupts.c
cpu/arm720t/interrupts.c
cpu/arm920t/imx/interrupts.c
cpu/arm920t/s3c24x0/interrupts.c
cpu/arm925t/interrupts.c
cpu/arm926ejs/interrupts.c
cpu/at91rm9200/interrupts.c
cpu/at91rm9200/start.S
cpu/lh7a40x/interrupts.c
cpu/pxa/interrupts.c
cpu/s3c44b0/interrupts.c
cpu/sa1100/interrupts.c
include/configs/cmc_pu2.h

index 73fb943b7c93879d98659e0e79b6780917b6c9e6..ba250b67f9378f7e318d791c39724a480b03172a 100644 (file)
--- 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
 
index c80d9a5d0f90f511567f48383a07cecba9eeed57..23236dcb0ff770ad1ad6f1b66485ad98adaa4940 100644 (file)
@@ -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);
 }
 
 /*
index a7ea70a266fbc118d8a6d6a0c59fa55063de6852..ab28e602c55fc5710d135b50fecf3a7badacd3b4 100644 (file)
@@ -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)
index 12ae2faf28d6d34fb2c93d83305bcfb8a931eb01..2f2e7545699f99ee6951a46b7fa7fd522d70f8e6 100644 (file)
@@ -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)
index f581d6d6079275c117ad8eb4a8f2fa6cbec8edbf..868621fa5e91ddbacef46bb24ac4b2b26f7146d4 100644 (file)
@@ -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);
 }
 
 /*
index ea4aa3b3b04172bd84ae5c2d2fb1a78183511552..57bb4eab6f648b711d4939da2e9dd9014b26c7c5 100644 (file)
@@ -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
 }
 
index 062515e398ff60bc82d989f6174441e560baeb65..ae8082d5ce6d24aa3500f9c26ab4f5d63596356e 100644 (file)
@@ -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);
 }
 
 /*
index f15c5830bb62f2d27e248de57f93388ec4968e66..cccc4050a8619291c538953fb31d305acb47711c 100644 (file)
@@ -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);
 }
 
 /*
index e897e6b9c9091f5dd3ca47b76af25226982f6ec8..1881ab1990533edf63550b3161e0db970d635915 100644 (file)
@@ -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
index 3c2dc4fc49d08fc78d183042a54964851b503a82..23d8039931b47863a6e98d231d7007d3578297e4 100644 (file)
@@ -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);
 }
 
 /*
index b335a82a5e123deb5ae22e040f80c210156eb2ae..0479a1048b9ebbf34e7a4fb5eaeeebabb48701b8 100644 (file)
@@ -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);
 }
 
 /*
index dea8118dd7d327e6dcf54f8125b722041f77f38d..5d2c13d97f88ec51aa9a37f079e2219705a27887 100644 (file)
@@ -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);
 }
index 93a78d707eb338c8ea96e93d69acc57bb53a59ad..b393e0d435ea879cc261b191dd5de77ab7f84ce3 100644 (file)
@@ -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);
 }
 
 /*
index ef2d1b7246fc4f5c84d57309ea9a254ee277552b..96b7148cf145e1929bbdf278ce29a67d7674ceda 100644 (file)
@@ -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 */