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 <asm/omap_common.h>
  26#include <linux/delay.h>
  27
  28DECLARE_GLOBAL_DATA_PTR;
  29
  30static struct gptimer *timer_base = (struct gptimer *)CFG_SYS_TIMERBASE;
  31static ulong get_timer_masked(void);
  32
  33/*
  34 * Nothing really to do with interrupts, just starts up a counter.
  35 */
  36
  37#define TIMER_CLOCK             (V_SCLK / (2 << SYS_PTV))
  38#define TIMER_OVERFLOW_VAL      0xffffffff
  39#define TIMER_LOAD_VAL          0
  40
  41int timer_init(void)
  42{
  43        /* start the counter ticking up, reload value on overflow */
  44        writel(TIMER_LOAD_VAL, &timer_base->tldr);
  45        /* enable timer */
  46        writel((SYS_PTV << 2) | TCLR_PRE | TCLR_AR | TCLR_ST,
  47                &timer_base->tclr);
  48
  49        return 0;
  50}
  51
  52/*
  53 * timer without interrupts
  54 */
  55ulong get_timer(ulong base)
  56{
  57        return get_timer_masked() - base;
  58}
  59
  60/* delay x useconds */
  61void __udelay(unsigned long usec)
  62{
  63        long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
  64        unsigned long now, last = readl(&timer_base->tcrr);
  65
  66        while (tmo > 0) {
  67                now = readl(&timer_base->tcrr);
  68                if (last > now) /* count up timer overflow */
  69                        tmo -= TIMER_OVERFLOW_VAL - last + now + 1;
  70                else
  71                        tmo -= now - last;
  72                last = now;
  73        }
  74}
  75
  76static ulong get_timer_masked(void)
  77{
  78        /* current tick value */
  79        ulong now = readl(&timer_base->tcrr) / (TIMER_CLOCK / CONFIG_SYS_HZ);
  80
  81        if (now >= gd->arch.lastinc) {  /* normal mode (non roll) */
  82                /* move stamp fordward with absoulte diff ticks */
  83                gd->arch.tbl += (now - gd->arch.lastinc);
  84        } else {        /* we have rollover of incrementer */
  85                gd->arch.tbl += ((TIMER_OVERFLOW_VAL / (TIMER_CLOCK /
  86                                CONFIG_SYS_HZ)) - gd->arch.lastinc) + now;
  87        }
  88        gd->arch.lastinc = now;
  89        return gd->arch.tbl;
  90}
  91
  92/*
  93 * This function is derived from PowerPC code (read timebase as long long).
  94 * On ARM it just returns the timer value.
  95 */
  96unsigned long long get_ticks(void)
  97{
  98        return get_timer(0);
  99}
 100
 101/*
 102 * This function is derived from PowerPC code (timebase clock frequency).
 103 * On ARM it returns the number of timer ticks per second.
 104 */
 105ulong get_tbclk(void)
 106{
 107        return CONFIG_SYS_HZ;
 108}
 109