uboot/arch/arm/cpu/arm920t/s3c24x0/timer.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   4 * Marius Groeger <mgroeger@sysgo.de>
   5 *
   6 * (C) Copyright 2002
   7 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   8 * Alex Zuepke <azu@sysgo.de>
   9 *
  10 * (C) Copyright 2002
  11 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
  12 *
  13 * See file CREDITS for list of people who contributed to this
  14 * project.
  15 *
  16 * This program is free software; you can redistribute it and/or
  17 * modify it under the terms of the GNU General Public License as
  18 * published by the Free Software Foundation; either version 2 of
  19 * the License, or (at your option) any later version.
  20 *
  21 * This program is distributed in the hope that it will be useful,
  22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24 * GNU General Public License for more details.
  25 *
  26 * You should have received a copy of the GNU General Public License
  27 * along with this program; if not, write to the Free Software
  28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  29 * MA 02111-1307 USA
  30 */
  31
  32#include <common.h>
  33#ifdef CONFIG_S3C24X0
  34
  35#include <asm/io.h>
  36#include <asm/arch/s3c24x0_cpu.h>
  37
  38int timer_load_val = 0;
  39static ulong timer_clk;
  40
  41/* macro to read the 16 bit timer */
  42static inline ulong READ_TIMER(void)
  43{
  44        struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
  45
  46        return readl(&timers->TCNTO4) & 0xffff;
  47}
  48
  49static ulong timestamp;
  50static ulong lastdec;
  51
  52int timer_init(void)
  53{
  54        struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
  55        ulong tmr;
  56
  57        /* use PWM Timer 4 because it has no output */
  58        /* prescaler for Timer 4 is 16 */
  59        writel(0x0f00, &timers->TCFG0);
  60        if (timer_load_val == 0) {
  61                /*
  62                 * for 10 ms clock period @ PCLK with 4 bit divider = 1/2
  63                 * (default) and prescaler = 16. Should be 10390
  64                 * @33.25MHz and 15625 @ 50 MHz
  65                 */
  66                timer_load_val = get_PCLK() / (2 * 16 * 100);
  67                timer_clk = get_PCLK() / (2 * 16);
  68        }
  69        /* load value for 10 ms timeout */
  70        lastdec = timer_load_val;
  71        writel(timer_load_val, &timers->TCNTB4);
  72        /* auto load, manual update of Timer 4 */
  73        tmr = (readl(&timers->TCON) & ~0x0700000) | 0x0600000;
  74        writel(tmr, &timers->TCON);
  75        /* auto load, start Timer 4 */
  76        tmr = (tmr & ~0x0700000) | 0x0500000;
  77        writel(tmr, &timers->TCON);
  78        timestamp = 0;
  79
  80        return (0);
  81}
  82
  83/*
  84 * timer without interrupts
  85 */
  86
  87void reset_timer(void)
  88{
  89        reset_timer_masked();
  90}
  91
  92ulong get_timer(ulong base)
  93{
  94        return get_timer_masked() - base;
  95}
  96
  97void set_timer(ulong t)
  98{
  99        timestamp = t;
 100}
 101
 102void __udelay (unsigned long usec)
 103{
 104        ulong tmo;
 105        ulong start = get_ticks();
 106
 107        tmo = usec / 1000;
 108        tmo *= (timer_load_val * 100);
 109        tmo /= 1000;
 110
 111        while ((ulong) (get_ticks() - start) < tmo)
 112                /*NOP*/;
 113}
 114
 115void reset_timer_masked(void)
 116{
 117        /* reset time */
 118        lastdec = READ_TIMER();
 119        timestamp = 0;
 120}
 121
 122ulong get_timer_masked(void)
 123{
 124        ulong tmr = get_ticks();
 125
 126        return tmr / (timer_clk / CONFIG_SYS_HZ);
 127}
 128
 129void udelay_masked(unsigned long usec)
 130{
 131        ulong tmo;
 132        ulong endtime;
 133        signed long diff;
 134
 135        if (usec >= 1000) {
 136                tmo = usec / 1000;
 137                tmo *= (timer_load_val * 100);
 138                tmo /= 1000;
 139        } else {
 140                tmo = usec * (timer_load_val * 100);
 141                tmo /= (1000 * 1000);
 142        }
 143
 144        endtime = get_ticks() + tmo;
 145
 146        do {
 147                ulong now = get_ticks();
 148                diff = endtime - now;
 149        } while (diff >= 0);
 150}
 151
 152/*
 153 * This function is derived from PowerPC code (read timebase as long long).
 154 * On ARM it just returns the timer value.
 155 */
 156unsigned long long get_ticks(void)
 157{
 158        ulong now = READ_TIMER();
 159
 160        if (lastdec >= now) {
 161                /* normal mode */
 162                timestamp += lastdec - now;
 163        } else {
 164                /* we have an overflow ... */
 165                timestamp += lastdec + timer_load_val - now;
 166        }
 167        lastdec = now;
 168
 169        return timestamp;
 170}
 171
 172/*
 173 * This function is derived from PowerPC code (timebase clock frequency).
 174 * On ARM it returns the number of timer ticks per second.
 175 */
 176ulong get_tbclk(void)
 177{
 178        ulong tbclk;
 179
 180#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
 181        tbclk = timer_load_val * 100;
 182#elif defined(CONFIG_SBC2410X) || \
 183      defined(CONFIG_SMDK2410) || \
 184      defined(CONFIG_VCMA9)
 185        tbclk = CONFIG_SYS_HZ;
 186#else
 187#       error "tbclk not configured"
 188#endif
 189
 190        return tbclk;
 191}
 192
 193/*
 194 * reset the cpu by setting up the watchdog timer and let him time out
 195 */
 196void reset_cpu(ulong ignored)
 197{
 198        struct s3c24x0_watchdog *watchdog;
 199
 200#ifdef CONFIG_TRAB
 201        extern void disable_vfd(void);
 202
 203        disable_vfd();
 204#endif
 205
 206        watchdog = s3c24x0_get_base_watchdog();
 207
 208        /* Disable watchdog */
 209        writel(0x0000, &watchdog->WTCON);
 210
 211        /* Initialize watchdog timer count register */
 212        writel(0x0001, &watchdog->WTCNT);
 213
 214        /* Enable watchdog timer; assert reset at timer timeout */
 215        writel(0x0021, &watchdog->WTCON);
 216
 217        while (1)
 218                /* loop forever and wait for reset to happen */;
 219
 220        /*NOTREACHED*/
 221}
 222
 223#endif /* CONFIG_S3C24X0 */
 224