The s3c24x0 timer has been updated to avoid using static variables prior
to BSS being made available.
Restructured code based on other timer.c files.
Updated comments and several parameters.

Signed-off-by: Mark Norman <mpnor...@gmail.com>
---
Changes for v2:
   - Fixed multi-line comment format
   - Formatting updates to separate declarations from code
   - Removed unrelated changes accidentally included in original patch
Changes for v3:
   - Added bitfield declarations to avoid using magic numbers.
   - Change to use existing global_data variables instead of creating new
     ones.

 arch/arm/cpu/arm920t/s3c24x0/timer.c |  180 ++++++++++++++++------------------
 1 files changed, 85 insertions(+), 95 deletions(-)

diff --git a/arch/arm/cpu/arm920t/s3c24x0/timer.c 
b/arch/arm/cpu/arm920t/s3c24x0/timer.c
index 9571870..8e1b935 100644
--- a/arch/arm/cpu/arm920t/s3c24x0/timer.c
+++ b/arch/arm/cpu/arm920t/s3c24x0/timer.c
@@ -35,116 +35,93 @@
 #include <asm/io.h>
 #include <asm/arch/s3c24x0_cpu.h>
 
-int timer_load_val = 0;
-static ulong timer_clk;
+/* Timer Control Register (TCON) bitfields */
+#define TCON_TMR4_AUTO_RELOAD (1<<22)
+#define TCON_TMR4_MAN_UPDATE  (1<<21)
+#define TCON_TMR4_START       (1<<20)
+#define TCON_TMR4_MASK        (TCON_TMR4_AUTO_RELOAD | TCON_TMR4_MAN_UPDATE | \
+                               TCON_TMR4_START)
 
-/* macro to read the 16 bit timer */
-static inline ulong READ_TIMER(void)
+/* Timer Configuration Register 0 (TCFG0) bitfields */
+#define TCFG0_PRESCALER1(x)   (((x) & 0xff) << 8)
+
+/* Watchdog Timer Control Register (WTCON) bitfields */
+#define WTCON_TIMER_EN        (1<<5)
+#define WTCON_RESET_EN        (1<<0)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp          (gd->tbl)
+#define lastdec            (gd->lastinc)
+#define timer_rate_hz      (gd->timer_rate_hz)
+#define timer_reset_value  (gd->timer_reset_value)
+
+/* 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;
+       const ulong divider = 2;
        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 */
-       tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000;
-       writel(tmr, &timers->tcon);
-       /* auto load, start timer 4 */
-       tmr = (tmr & ~0x0700000) | 0x0500000;
-       writel(tmr, &timers->tcon);
-       timestamp = 0;
-
-       return (0);
-}
-
-/*
- * timer without interrupts
- */
-ulong get_timer(ulong base)
-{
-       return get_timer_masked() - base;
-}
-
-void __udelay (unsigned long usec)
-{
-       ulong tmo;
-       ulong start = get_ticks();
+       /* Set prescaler for Timer 4 */
+       writel(TCFG0_PRESCALER1(prescaler-1), &timers->tcfg0);
 
-       tmo = usec / 1000;
-       tmo *= (timer_load_val * 100);
-       tmo /= 1000;
+       /* Calculate timer freq, approx 100kHz @ PCLK=50MHz. */
+       timer_rate_hz = get_PCLK() / (divider * prescaler);
 
-       while ((ulong) (get_ticks() - start) < tmo)
-               /*NOP*/;
-}
-
-ulong get_timer_masked(void)
-{
-       ulong tmr = get_ticks();
+       /* Set timer for 0.5s timeout (50000 ticks @ 10us ticks). */
+       timer_reset_value = 50000;
+       writel(timer_reset_value, &timers->tcntb4);
+       lastdec = timer_reset_value;
 
-       return tmr / (timer_clk / CONFIG_SYS_HZ);
-}
+       /* Load the initial timer 4 count value using the manual update bit. */
+       tmr = readl(&timers->tcon);
+       tmr &= ~TCON_TMR4_MASK;
+       tmr |= (TCON_TMR4_AUTO_RELOAD | TCON_TMR4_MAN_UPDATE);
+       writel(tmr, &timers->tcon);
 
-void udelay_masked(unsigned long usec)
-{
-       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);
-       }
+       /* Configure timer 4 for auto reload and start it. */
+       tmr &= ~TCON_TMR4_MASK;
+       tmr |= (TCON_TMR4_AUTO_RELOAD | TCON_TMR4_START);
+       writel(tmr, &timers->tcon);
 
-       endtime = get_ticks() + tmo;
+       timestamp = 0;
 
-       do {
-               ulong now = get_ticks();
-               diff = endtime - now;
-       } while (diff >= 0);
+       return 0;
 }
 
 /*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
+ * Get the number of ticks (in CONFIG_SYS_HZ resolution)
  */
 unsigned long long get_ticks(void)
 {
-       ulong now = READ_TIMER();
+       return get_timer(0);
+}
+
+unsigned long get_timer_raw(void)
+{
+       ulong now = read_timer();
 
        if (lastdec >= now) {
                /* normal mode */
                timestamp += lastdec - now;
        } else {
                /* we have an overflow ... */
-               timestamp += lastdec + timer_load_val - now;
+               timestamp += lastdec + timer_reset_value - now;
        }
        lastdec = now;
 
@@ -157,20 +134,33 @@ unsigned long long get_ticks(void)
  */
 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;
+       return CONFIG_SYS_HZ;
+}
+
+ulong get_timer_masked(void)
+{
+       unsigned long tmr = get_timer_raw();
+
+       return (tmr * CONFIG_SYS_HZ) / timer_rate_hz;
+}
+
+ulong get_timer(ulong base)
+{
+       return get_timer_masked() - base;
+}
+
+void __udelay(unsigned long usec)
+{
+       unsigned long tmp;
+       unsigned long tmo;
+
+       /* convert usec to ticks. */
+       tmo = ((timer_rate_hz / 1000) * usec) / 1000;
+
+       tmp = get_timer_raw() + tmo;    /* get current timestamp */
+
+       while (get_timer_raw() < tmp)   /* loop till event */
+               /*NOP*/;
 }
 
 /*
@@ -189,7 +179,7 @@ void reset_cpu(ulong ignored)
        writel(0x0001, &watchdog->wtcnt);
 
        /* Enable watchdog timer; assert reset at timer timeout */
-       writel(0x0021, &watchdog->wtcon);
+       writel(WTCON_TIMER_EN | WTCON_RESET_EN, &watchdog->wtcon);
 
        while (1)
                /* loop forever and wait for reset to happen */;
-- 
1.7.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to