uboot/arch/arm/cpu/armv7/highbank/timer.c
<<
>>
Prefs
   1/*
   2 * Copyright 2010-2011 Calxeda, Inc.
   3 *
   4 * Based on arm926ejs/mx27/timer.c
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <div64.h>
  11#include <linux/types.h>        /* for size_t */
  12#include <linux/stddef.h>       /* for NULL */
  13#include <asm/io.h>
  14#include <asm/arch-armv7/systimer.h>
  15
  16#undef SYSTIMER_BASE
  17#define SYSTIMER_BASE           0xFFF34000      /* Timer 0 and 1 base   */
  18#define SYSTIMER_RATE           (150000000 / 256)
  19
  20static ulong timestamp;
  21static ulong lastinc;
  22static struct systimer *systimer_base = (struct systimer *)SYSTIMER_BASE;
  23
  24/*
  25 * Start the timer
  26 */
  27int timer_init(void)
  28{
  29        /*
  30         * Setup timer0
  31         */
  32        writel(0, &systimer_base->timer0control);
  33        writel(SYSTIMER_RELOAD, &systimer_base->timer0load);
  34        writel(SYSTIMER_RELOAD, &systimer_base->timer0value);
  35        writel(SYSTIMER_EN | SYSTIMER_32BIT | SYSTIMER_PRESC_256,
  36                &systimer_base->timer0control);
  37
  38        return 0;
  39
  40}
  41
  42#define TICK_PER_TIME   ((SYSTIMER_RATE + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ)
  43#define NS_PER_TICK     (1000000000 / SYSTIMER_RATE)
  44
  45static inline unsigned long long tick_to_time(unsigned long long tick)
  46{
  47        do_div(tick, TICK_PER_TIME);
  48        return tick;
  49}
  50
  51static inline unsigned long long time_to_tick(unsigned long long time)
  52{
  53        return time * TICK_PER_TIME;
  54}
  55
  56static inline unsigned long long us_to_tick(unsigned long long us)
  57{
  58        unsigned long long tick = us * 1000;
  59        tick += NS_PER_TICK - 1;
  60        do_div(tick, NS_PER_TICK);
  61        return tick;
  62}
  63
  64unsigned long long get_ticks(void)
  65{
  66        ulong now = ~readl(&systimer_base->timer0value);
  67
  68        if (now >= lastinc)     /* normal mode (non roll) */
  69                /* move stamp forward with absolut diff ticks */
  70                timestamp += (now - lastinc);
  71        else                    /* we have rollover of incrementer */
  72                timestamp += (0xFFFFFFFF - lastinc) + now;
  73        lastinc = now;
  74        return timestamp;
  75}
  76
  77/*
  78 * Delay x useconds AND preserve advance timstamp value
  79 *     assumes timer is ticking at 1 msec
  80 */
  81void __udelay(ulong usec)
  82{
  83        unsigned long long tmp;
  84        ulong tmo;
  85
  86        tmo = us_to_tick(usec);
  87        tmp = get_ticks() + tmo;        /* get current timestamp */
  88
  89        while (get_ticks() < tmp)       /* loop till event */
  90                 /*NOP*/;
  91}
  92
  93ulong get_timer(ulong base)
  94{
  95        return get_timer_masked() - base;
  96}
  97
  98void reset_timer_masked(void)
  99{
 100        lastinc = ~readl(&systimer_base->timer0value);
 101        timestamp = 0;
 102}
 103
 104void reset_timer(void)
 105{
 106        reset_timer_masked();
 107}
 108
 109ulong get_timer_masked(void)
 110{
 111        return tick_to_time(get_ticks());
 112}
 113
 114ulong get_tbclk(void)
 115{
 116        return SYSTIMER_RATE;
 117}
 118