uboot/arch/arm/mach-omap2/timer.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2008
   3 * Texas Instruments
   4 *
   5 * Richard Woodruff <r-woodruff2@ti.com>
   6 * Syed Moahmmed Khasim <khasim@ti.com>
   7 *
   8 * (C) Copyright 2002
   9 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  10 * Marius Groeger <mgroeger@sysgo.de>
  11 * Alex Zuepke <azu@sysgo.de>
  12 *
  13 * (C) Copyright 2002
  14 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
  15 *
  16 * SPDX-License-Identifier:     GPL-2.0+
  17 */
  18
  19#include <common.h>
  20#include <asm/io.h>
  21#include <asm/arch/cpu.h>
  22#include <asm/arch/clock.h>
  23
  24DECLARE_GLOBAL_DATA_PTR;
  25
  26static struct gptimer *timer_base = (struct gptimer *)CONFIG_SYS_TIMERBASE;
  27
  28/*
  29 * Nothing really to do with interrupts, just starts up a counter.
  30 */
  31
  32#define TIMER_CLOCK             (V_SCLK / (2 << CONFIG_SYS_PTV))
  33#define TIMER_OVERFLOW_VAL      0xffffffff
  34#define TIMER_LOAD_VAL          0
  35
  36int timer_init(void)
  37{
  38        /* start the counter ticking up, reload value on overflow */
  39        writel(TIMER_LOAD_VAL, &timer_base->tldr);
  40        /* enable timer */
  41        writel((CONFIG_SYS_PTV << 2) | TCLR_PRE | TCLR_AR | TCLR_ST,
  42                &timer_base->tclr);
  43
  44        return 0;
  45}
  46
  47/*
  48 * timer without interrupts
  49 */
  50ulong get_timer(ulong base)
  51{
  52        return get_timer_masked() - base;
  53}
  54
  55/* delay x useconds */
  56void __udelay(unsigned long usec)
  57{
  58        long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
  59        unsigned long now, last = readl(&timer_base->tcrr);
  60
  61        while (tmo > 0) {
  62                now = readl(&timer_base->tcrr);
  63                if (last > now) /* count up timer overflow */
  64                        tmo -= TIMER_OVERFLOW_VAL - last + now + 1;
  65                else
  66                        tmo -= now - last;
  67                last = now;
  68        }
  69}
  70
  71ulong get_timer_masked(void)
  72{
  73        /* current tick value */
  74        ulong now = readl(&timer_base->tcrr) / (TIMER_CLOCK / CONFIG_SYS_HZ);
  75
  76        if (now >= gd->arch.lastinc) {  /* normal mode (non roll) */
  77                /* move stamp fordward with absoulte diff ticks */
  78                gd->arch.tbl += (now - gd->arch.lastinc);
  79        } else {        /* we have rollover of incrementer */
  80                gd->arch.tbl += ((TIMER_OVERFLOW_VAL / (TIMER_CLOCK /
  81                                CONFIG_SYS_HZ)) - gd->arch.lastinc) + now;
  82        }
  83        gd->arch.lastinc = now;
  84        return gd->arch.tbl;
  85}
  86
  87/*
  88 * This function is derived from PowerPC code (read timebase as long long).
  89 * On ARM it just returns the timer value.
  90 */
  91unsigned long long get_ticks(void)
  92{
  93        return get_timer(0);
  94}
  95
  96/*
  97 * This function is derived from PowerPC code (timebase clock frequency).
  98 * On ARM it returns the number of timer ticks per second.
  99 */
 100ulong get_tbclk(void)
 101{
 102        return CONFIG_SYS_HZ;
 103}
 104