uboot/cpu/lh7a40x/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#include <lh7a40x.h>
  34
  35static ulong timer_load_val = 0;
  36
  37/* macro to read the 16 bit timer */
  38static inline ulong READ_TIMER(void)
  39{
  40        lh7a40x_timers_t* timers = LH7A40X_TIMERS_PTR;
  41        lh7a40x_timer_t* timer = &timers->timer1;
  42
  43        return (timer->value & 0x0000ffff);
  44}
  45
  46static ulong timestamp;
  47static ulong lastdec;
  48
  49int timer_init (void)
  50{
  51        lh7a40x_timers_t* timers = LH7A40X_TIMERS_PTR;
  52        lh7a40x_timer_t* timer = &timers->timer1;
  53
  54        /* a periodic timer using the 508kHz source */
  55        timer->control = (TIMER_PER | TIMER_CLK508K);
  56
  57        if (timer_load_val == 0) {
  58                /*
  59                 * 10ms period with 508.469kHz clock = 5084
  60                 */
  61                timer_load_val = CONFIG_SYS_HZ/100;
  62        }
  63
  64        /* load value for 10 ms timeout */
  65        lastdec = timer->load = timer_load_val;
  66
  67        /* auto load, start timer */
  68        timer->control = timer->control | TIMER_EN;
  69        timestamp = 0;
  70
  71        return (0);
  72}
  73
  74/*
  75 * timer without interrupts
  76 */
  77
  78void reset_timer (void)
  79{
  80        reset_timer_masked ();
  81}
  82
  83ulong get_timer (ulong base)
  84{
  85        return (get_timer_masked() - base);
  86}
  87
  88void set_timer (ulong t)
  89{
  90        timestamp = t;
  91}
  92
  93void __udelay (unsigned long usec)
  94{
  95        ulong tmo,tmp;
  96
  97        /* normalize */
  98        if (usec >= 1000) {
  99                tmo = usec / 1000;
 100                tmo *= CONFIG_SYS_HZ;
 101                tmo /= 1000;
 102        }
 103        else {
 104                if (usec > 1) {
 105                        tmo = usec * CONFIG_SYS_HZ;
 106                        tmo /= (1000*1000);
 107                }
 108                else
 109                        tmo = 1;
 110        }
 111
 112        /* check for rollover during this delay */
 113        tmp = get_timer (0);
 114        if ((tmp + tmo) < tmp )
 115                reset_timer_masked();  /* timer would roll over */
 116        else
 117                tmo += tmp;
 118
 119        while (get_timer_masked () < tmo);
 120}
 121
 122void reset_timer_masked (void)
 123{
 124        /* reset time */
 125        lastdec = READ_TIMER();
 126        timestamp = 0;
 127}
 128
 129ulong get_timer_masked (void)
 130{
 131        ulong now = READ_TIMER();
 132
 133        if (lastdec >= now) {
 134                /* normal mode */
 135                timestamp += (lastdec - now);
 136        } else {
 137                /* we have an overflow ... */
 138                timestamp += ((lastdec + timer_load_val) - now);
 139        }
 140        lastdec = now;
 141
 142        return timestamp;
 143}
 144
 145void udelay_masked (unsigned long usec)
 146{
 147        ulong tmo;
 148        ulong endtime;
 149        signed long diff;
 150
 151        /* normalize */
 152        if (usec >= 1000) {
 153                tmo = usec / 1000;
 154                tmo *= CONFIG_SYS_HZ;
 155                tmo /= 1000;
 156        } else {
 157                if (usec > 1) {
 158                        tmo = usec * CONFIG_SYS_HZ;
 159                        tmo /= (1000*1000);
 160                } else {
 161                        tmo = 1;
 162                }
 163        }
 164
 165        endtime = get_timer_masked () + tmo;
 166
 167        do {
 168                ulong now = get_timer_masked ();
 169                diff = endtime - now;
 170        } while (diff >= 0);
 171}
 172
 173/*
 174 * This function is derived from PowerPC code (read timebase as long long).
 175 * On ARM it just returns the timer value.
 176 */
 177unsigned long long get_ticks(void)
 178{
 179        return get_timer(0);
 180}
 181
 182/*
 183 * This function is derived from PowerPC code (timebase clock frequency).
 184 * On ARM it returns the number of timer ticks per second.
 185 */
 186ulong get_tbclk (void)
 187{
 188        ulong tbclk;
 189
 190        tbclk = timer_load_val * 100;
 191
 192        return tbclk;
 193}
 194