Dear Wolfgang Denk,

Thank you for your response.

>>  Since the .rel.text section is required by the relocation code, I
>> assume that .bss global variables cannot be used until after
>> relocation?
>
> Why do you have to make such assumptions?  That's documented
> behaviour.  Didn't you RTFM?
>

I thought I had done a thorough search previously but after receiving
your response I managed to find some of the details outlined in the
README file.

I have attached an updated patch below which hopefully addresses the
other issues you highlighted.

Kind Regards,

Mark Norman



The s3c24x0 timer has been updated to use the global_data struct.
Restructured code based on other timer.c files.
Updated comments and several parameters.

Signed-off-by: Mark Norman <mpnor...@gmail.com>
---
 arch/arm/cpu/arm920t/s3c24x0/timer.c |  155 +++++++++++++--------------------
 arch/arm/include/asm/global_data.h   |    4 +
 2 files changed, 65 insertions(+), 94 deletions(-)

diff --git a/arch/arm/cpu/arm920t/s3c24x0/timer.c
b/arch/arm/cpu/arm920t/s3c24x0/timer.c
index 9571870..5695c62 100644
--- a/arch/arm/cpu/arm920t/s3c24x0/timer.c
+++ b/arch/arm/cpu/arm920t/s3c24x0/timer.c
@@ -35,142 +35,109 @@
 #include <asm/io.h>
 #include <asm/arch/s3c24x0_cpu.h>

-int timer_load_val = 0;
-static ulong timer_clk;
+DECLARE_GLOBAL_DATA_PTR;

-/* macro to read the 16 bit timer */
-static inline ulong READ_TIMER(void)
+/* Read the 16 bit timer */
+static inline ulong read_timer(void)
 {
        struct s3c24x0_timers *timers = s3c24x0_get_base_timers();

        return readl(&timers->tcnto4) & 0xffff;
 }

-static ulong timestamp;
-static ulong lastdec;
-
 int timer_init(void)
 {
+       /*
+        * PWM Timer 4 is used because it has no output.
+        * Prescaler is hard fixed at 250, divider at 2.
+        * This generates a Timer clock frequency of 100kHz (@PCLK=50MHz) and
+        * therefore 10us timer ticks.
+        */
+       const ulong prescaler = 250;
        struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
        ulong tmr;

-       /* use PWM Timer 4 because it has no output */
-       /* prescaler for Timer 4 is 16 */
-       writel(0x0f00, &timers->tcfg0);
-       if (timer_load_val == 0) {
-               /*
-                * for 10 ms clock period @ PCLK with 4 bit divider = 1/2
-                * (default) and prescaler = 16. Should be 10390
-                * @33.25MHz and 15625 @ 50 MHz
-                */
-               timer_load_val = get_PCLK() / (2 * 16 * 100);
-               timer_clk = get_PCLK() / (2 * 16);
-       }
-       /* load value for 10 ms timeout */
-       lastdec = timer_load_val;
-       writel(timer_load_val, &timers->tcntb4);
-       /* auto load, manual update of timer 4 */
+       /* Set prescaler for Timer 4 */
+       writel((prescaler-1) << 8, &timers->tcfg0);
+
+       /* Calculate timer freq, approx 100kHz @ PCLK=50MHz. */
+       gd->timer_rate_hz = get_PCLK() / (2 * prescaler);
+
+       /* Set timer for 0.5s timeout (50000 ticks @ 10us ticks). */
+       gd->timer_reset_value = 50000;
+       writel(gd->timer_reset_value, &timers->tcntb4);
+       gd->lastdec = gd->timer_reset_value;
+
+       /* Load the initial timer 4 count value using the manual update bit. */
        tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000;
        writel(tmr, &timers->tcon);
-       /* auto load, start timer 4 */
+
+       /* Configure timer 4 for auto reload and start it. */
        tmr = (tmr & ~0x0700000) | 0x0500000;
        writel(tmr, &timers->tcon);
-       timestamp = 0;
+
+       gd->timestamp = 0;

        return (0);
 }

 /*
- * timer without interrupts
+ * Get the number of ticks (in CONFIG_SYS_HZ resolution)
  */
-ulong get_timer(ulong base)
+unsigned long long get_ticks(void)
 {
-       return get_timer_masked() - base;
+       return get_timer(0);
 }

-void __udelay (unsigned long usec)
+unsigned long get_timer_raw(void)
 {
-       ulong tmo;
-       ulong start = get_ticks();
+       ulong now = read_timer();

-       tmo = usec / 1000;
-       tmo *= (timer_load_val * 100);
-       tmo /= 1000;
+       if (gd->lastdec >= now) {
+               /* normal mode */
+               gd->timestamp += gd->lastdec - now;
+       } else {
+               /* we have an overflow ... */
+               gd->timestamp += gd->lastdec + gd->timer_reset_value - now;
+       }
+       gd->lastdec = now;

-       while ((ulong) (get_ticks() - start) < tmo)
-               /*NOP*/;
+       return gd->timestamp;
 }

-ulong get_timer_masked(void)
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
 {
-       ulong tmr = get_ticks();
-
-       return tmr / (timer_clk / CONFIG_SYS_HZ);
+       return CONFIG_SYS_HZ;
 }

-void udelay_masked(unsigned long usec)
+ulong get_timer_masked(void)
 {
-       ulong tmo;
-       ulong endtime;
-       signed long diff;
-
-       if (usec >= 1000) {
-               tmo = usec / 1000;
-               tmo *= (timer_load_val * 100);
-               tmo /= 1000;
-       } else {
-               tmo = usec * (timer_load_val * 100);
-               tmo /= (1000 * 1000);
-       }
+       unsigned long tmr = get_timer_raw();

-       endtime = get_ticks() + tmo;
+       return (tmr * CONFIG_SYS_HZ) / gd->timer_rate_hz;
+}

-       do {
-               ulong now = get_ticks();
-               diff = endtime - now;
-       } while (diff >= 0);
+ulong get_timer(ulong base)
+{
+       return get_timer_masked() - base;
 }

-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
- */
-unsigned long long get_ticks(void)
+void __udelay(unsigned long usec)
 {
-       ulong now = READ_TIMER();
+       unsigned long tmp;
+       unsigned long tmo;

-       if (lastdec >= now) {
-               /* normal mode */
-               timestamp += lastdec - now;
-       } else {
-               /* we have an overflow ... */
-               timestamp += lastdec + timer_load_val - now;
-       }
-       lastdec = now;
+       /* convert usec to ticks. */
+       tmo = ((gd->timer_rate_hz / 1000) * usec) / 1000;

-       return timestamp;
-}
+       tmp = get_timer_raw() + tmo;    /* get current timestamp */

-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
-{
-       ulong tbclk;
-
-#if defined(CONFIG_SMDK2400)
-       tbclk = timer_load_val * 100;
-#elif defined(CONFIG_SBC2410X) || \
-      defined(CONFIG_SMDK2410) || \
-       defined(CONFIG_S3C2440) || \
-      defined(CONFIG_VCMA9)
-       tbclk = CONFIG_SYS_HZ;
-#else
-#      error "tbclk not configured"
-#endif
-
-       return tbclk;
+       while (get_timer_raw() < tmp)   /* loop till event */
+               /*NOP*/;
 }

 /*
diff --git a/arch/arm/include/asm/global_data.h
b/arch/arm/include/asm/global_data.h
index fac98d5..b836915 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -67,6 +67,10 @@ typedef      struct  global_data {
 #ifdef CONFIG_IXP425
        unsigned long   timestamp;
 #endif
+#ifdef CONFIG_S3C24X0
+       unsigned long   lastdec;
+       unsigned long   timestamp;
+#endif
        unsigned long   relocaddr;      /* Start address of U-Boot in RAM */
        phys_size_t     ram_size;       /* RAM size */
        unsigned long   mon_len;        /* monitor len */
-- 
1.7.1
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to