uboot/lib/time.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2009
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <errno.h>
  11#include <timer.h>
  12#include <watchdog.h>
  13#include <div64.h>
  14#include <asm/io.h>
  15
  16#ifndef CONFIG_WD_PERIOD
  17# define CONFIG_WD_PERIOD       (10 * 1000 * 1000)      /* 10 seconds default */
  18#endif
  19
  20DECLARE_GLOBAL_DATA_PTR;
  21
  22#ifdef CONFIG_SYS_TIMER_RATE
  23/* Returns tick rate in ticks per second */
  24ulong notrace get_tbclk(void)
  25{
  26        return CONFIG_SYS_TIMER_RATE;
  27}
  28#endif
  29
  30#ifdef CONFIG_SYS_TIMER_COUNTER
  31unsigned long notrace timer_read_counter(void)
  32{
  33#ifdef CONFIG_SYS_TIMER_COUNTS_DOWN
  34        return ~readl(CONFIG_SYS_TIMER_COUNTER);
  35#else
  36        return readl(CONFIG_SYS_TIMER_COUNTER);
  37#endif
  38}
  39#else
  40extern unsigned long __weak timer_read_counter(void);
  41#endif
  42
  43#ifdef CONFIG_TIMER
  44ulong notrace get_tbclk(void)
  45{
  46        if (!gd->timer) {
  47#ifdef CONFIG_TIMER_EARLY
  48                return timer_early_get_rate();
  49#else
  50                int ret;
  51
  52                ret = dm_timer_init();
  53                if (ret)
  54                        return ret;
  55#endif
  56        }
  57
  58        return timer_get_rate(gd->timer);
  59}
  60
  61uint64_t notrace get_ticks(void)
  62{
  63        u64 count;
  64        int ret;
  65
  66        if (!gd->timer) {
  67#ifdef CONFIG_TIMER_EARLY
  68                return timer_early_get_count();
  69#else
  70                int ret;
  71
  72                ret = dm_timer_init();
  73                if (ret)
  74                        return ret;
  75#endif
  76        }
  77
  78        ret = timer_get_count(gd->timer, &count);
  79        if (ret)
  80                return ret;
  81
  82        return count;
  83}
  84
  85#else /* !CONFIG_TIMER */
  86
  87uint64_t __weak notrace get_ticks(void)
  88{
  89        unsigned long now = timer_read_counter();
  90
  91        /* increment tbu if tbl has rolled over */
  92        if (now < gd->timebase_l)
  93                gd->timebase_h++;
  94        gd->timebase_l = now;
  95        return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l;
  96}
  97
  98#endif /* CONFIG_TIMER */
  99
 100/* Returns time in milliseconds */
 101static uint64_t notrace tick_to_time(uint64_t tick)
 102{
 103        ulong div = get_tbclk();
 104
 105        tick *= CONFIG_SYS_HZ;
 106        do_div(tick, div);
 107        return tick;
 108}
 109
 110int __weak timer_init(void)
 111{
 112        return 0;
 113}
 114
 115/* Returns time in milliseconds */
 116ulong __weak get_timer(ulong base)
 117{
 118        return tick_to_time(get_ticks()) - base;
 119}
 120
 121unsigned long __weak notrace timer_get_us(void)
 122{
 123        return tick_to_time(get_ticks() * 1000);
 124}
 125
 126static uint64_t usec_to_tick(unsigned long usec)
 127{
 128        uint64_t tick = usec;
 129        tick *= get_tbclk();
 130        do_div(tick, 1000000);
 131        return tick;
 132}
 133
 134void __weak __udelay(unsigned long usec)
 135{
 136        uint64_t tmp;
 137
 138        tmp = get_ticks() + usec_to_tick(usec); /* get current timestamp */
 139
 140        while (get_ticks() < tmp+1)     /* loop till event */
 141                 /*NOP*/;
 142}
 143
 144/* ------------------------------------------------------------------------- */
 145
 146void udelay(unsigned long usec)
 147{
 148        ulong kv;
 149
 150        do {
 151                WATCHDOG_RESET();
 152                kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec;
 153                __udelay (kv);
 154                usec -= kv;
 155        } while(usec);
 156}
 157
 158void mdelay(unsigned long msec)
 159{
 160        while (msec--)
 161                udelay(1000);
 162}
 163