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