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 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License as published by the Free
   8 * Software Foundation; either version 2 of the License, or (at your option)
   9 * any later version.
  10 *
  11 * This program is distributed in the hope it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14 * more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along with
  17 * this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include <common.h>
  21#include <div64.h>
  22#include <linux/types.h>        /* for size_t */
  23#include <linux/stddef.h>       /* for NULL */
  24#include <asm/io.h>
  25#include <asm/arch-armv7/systimer.h>
  26
  27#undef SYSTIMER_BASE
  28#define SYSTIMER_BASE           0xFFF34000      /* Timer 0 and 1 base   */
  29#define SYSTIMER_RATE           150000000
  30
  31static ulong timestamp;
  32static ulong lastinc;
  33static struct systimer *systimer_base = (struct systimer *)SYSTIMER_BASE;
  34
  35/*
  36 * Start the timer
  37 */
  38int timer_init(void)
  39{
  40        /*
  41         * Setup timer0
  42         */
  43        writel(SYSTIMER_RELOAD, &systimer_base->timer0load);
  44        writel(SYSTIMER_RELOAD, &systimer_base->timer0value);
  45        writel(SYSTIMER_EN | SYSTIMER_32BIT, &systimer_base->timer0control);
  46
  47        reset_timer_masked();
  48
  49        return 0;
  50
  51}
  52
  53#define TICK_PER_TIME   ((SYSTIMER_RATE + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ)
  54#define NS_PER_TICK     (1000000000 / SYSTIMER_RATE)
  55
  56static inline unsigned long long tick_to_time(unsigned long long tick)
  57{
  58        do_div(tick, TICK_PER_TIME);
  59        return tick;
  60}
  61
  62static inline unsigned long long time_to_tick(unsigned long long time)
  63{
  64        return time * TICK_PER_TIME;
  65}
  66
  67static inline unsigned long long us_to_tick(unsigned long long us)
  68{
  69        unsigned long long tick = us * 1000;
  70        tick += NS_PER_TICK - 1;
  71        do_div(tick, NS_PER_TICK);
  72        return tick;
  73}
  74
  75unsigned long long get_ticks(void)
  76{
  77        ulong now = ~readl(&systimer_base->timer0value);
  78
  79        if (now >= lastinc)     /* normal mode (non roll) */
  80                /* move stamp forward with absolut diff ticks */
  81                timestamp += (now - lastinc);
  82        else                    /* we have rollover of incrementer */
  83                timestamp += (0xFFFFFFFF - lastinc) + now;
  84        lastinc = now;
  85        return timestamp;
  86}
  87
  88/*
  89 * Delay x useconds AND preserve advance timstamp value
  90 *     assumes timer is ticking at 1 msec
  91 */
  92void __udelay(ulong usec)
  93{
  94        unsigned long long tmp;
  95        ulong tmo;
  96
  97        tmo = us_to_tick(usec);
  98        tmp = get_ticks() + tmo;        /* get current timestamp */
  99
 100        while (get_ticks() < tmp)       /* loop till event */
 101                 /*NOP*/;
 102}
 103
 104ulong get_timer(ulong base)
 105{
 106        return get_timer_masked() - base;
 107}
 108
 109void reset_timer_masked(void)
 110{
 111        lastinc = ~readl(&systimer_base->timer0value);
 112        timestamp = 0;
 113}
 114
 115void reset_timer(void)
 116{
 117        reset_timer_masked();
 118}
 119
 120ulong get_timer_masked(void)
 121{
 122        return tick_to_time(get_ticks());
 123}
 124
 125ulong get_tbclk(void)
 126{
 127        return CONFIG_SYS_HZ;
 128}
 129