uboot/arch/arm/cpu/arm926ejs/orion5x/timer.c
<<
>>
Prefs
   1/*
   2  * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
   3 *
   4 * Based on original Kirkwood support which is
   5 * Copyright (C) Marvell International Ltd. and its affiliates
   6 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  24 * MA 02110-1301 USA
  25 */
  26
  27#include <common.h>
  28#include <asm/io.h>
  29
  30#define UBOOT_CNTR      0       /* counter to use for uboot timer */
  31
  32/* Timer reload and current value registers */
  33struct orion5x_tmr_val {
  34        u32 reload;     /* Timer reload reg */
  35        u32 val;        /* Timer value reg */
  36};
  37
  38/* Timer registers */
  39struct orion5x_tmr_registers {
  40        u32 ctrl;       /* Timer control reg */
  41        u32 pad[3];
  42        struct orion5x_tmr_val tmr[2];
  43        u32 wdt_reload;
  44        u32 wdt_val;
  45};
  46
  47struct orion5x_tmr_registers *orion5x_tmr_regs =
  48        (struct orion5x_tmr_registers *)ORION5X_TIMER_BASE;
  49
  50/*
  51 * ARM Timers Registers Map
  52 */
  53#define CNTMR_CTRL_REG                  (&orion5x_tmr_regs->ctrl)
  54#define CNTMR_RELOAD_REG(tmrnum)        (&orion5x_tmr_regs->tmr[tmrnum].reload)
  55#define CNTMR_VAL_REG(tmrnum)           (&orion5x_tmr_regs->tmr[tmrnum].val)
  56
  57/*
  58 * ARM Timers Control Register
  59 * CPU_TIMERS_CTRL_REG (CTCR)
  60 */
  61#define CTCR_ARM_TIMER_EN_OFFS(cntr)    (cntr * 2)
  62#define CTCR_ARM_TIMER_EN_MASK(cntr)    (1 << CTCR_ARM_TIMER_EN_OFFS)
  63#define CTCR_ARM_TIMER_EN(cntr)         (1 << CTCR_ARM_TIMER_EN_OFFS(cntr))
  64#define CTCR_ARM_TIMER_DIS(cntr)        (0 << CTCR_ARM_TIMER_EN_OFFS(cntr))
  65
  66#define CTCR_ARM_TIMER_AUTO_OFFS(cntr)  ((cntr * 2) + 1)
  67#define CTCR_ARM_TIMER_AUTO_MASK(cntr)  (1 << 1)
  68#define CTCR_ARM_TIMER_AUTO_EN(cntr)    (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
  69#define CTCR_ARM_TIMER_AUTO_DIS(cntr)   (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
  70
  71/*
  72 * ARM Timer\Watchdog Reload Register
  73 * CNTMR_RELOAD_REG (TRR)
  74 */
  75#define TRG_ARM_TIMER_REL_OFFS          0
  76#define TRG_ARM_TIMER_REL_MASK          0xffffffff
  77
  78/*
  79 * ARM Timer\Watchdog Register
  80 * CNTMR_VAL_REG (TVRG)
  81 */
  82#define TVR_ARM_TIMER_OFFS              0
  83#define TVR_ARM_TIMER_MASK              0xffffffff
  84#define TVR_ARM_TIMER_MAX               0xffffffff
  85#define TIMER_LOAD_VAL                  0xffffffff
  86
  87static inline ulong read_timer(void)
  88{
  89        return readl(CNTMR_VAL_REG(UBOOT_CNTR))
  90              / (CONFIG_SYS_TCLK / 1000);
  91}
  92
  93DECLARE_GLOBAL_DATA_PTR;
  94
  95#define timestamp gd->tbl
  96#define lastdec gd->lastinc
  97
  98ulong get_timer_masked(void)
  99{
 100        ulong now = read_timer();
 101
 102        if (lastdec >= now) {
 103                /* normal mode */
 104                timestamp += lastdec - now;
 105        } else {
 106                /* we have an overflow ... */
 107                timestamp += lastdec +
 108                        (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now;
 109        }
 110        lastdec = now;
 111
 112        return timestamp;
 113}
 114
 115ulong get_timer(ulong base)
 116{
 117        return get_timer_masked() - base;
 118}
 119
 120static inline ulong uboot_cntr_val(void)
 121{
 122        return readl(CNTMR_VAL_REG(UBOOT_CNTR));
 123}
 124
 125void __udelay(unsigned long usec)
 126{
 127        uint current;
 128        ulong delayticks;
 129
 130        current = uboot_cntr_val();
 131        delayticks = (usec * (CONFIG_SYS_TCLK / 1000000));
 132
 133        if (current < delayticks) {
 134                delayticks -= current;
 135                while (uboot_cntr_val() < current)
 136                        ;
 137                while ((TIMER_LOAD_VAL - delayticks) < uboot_cntr_val())
 138                        ;
 139        } else {
 140                while (uboot_cntr_val() > (current - delayticks))
 141                        ;
 142        }
 143}
 144
 145/*
 146 * init the counter
 147 */
 148int timer_init(void)
 149{
 150        unsigned int cntmrctrl;
 151
 152        /* load value into timer */
 153        writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR));
 154        writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR));
 155
 156        /* enable timer in auto reload mode */
 157        cntmrctrl = readl(CNTMR_CTRL_REG);
 158        cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR);
 159        cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR);
 160        writel(cntmrctrl, CNTMR_CTRL_REG);
 161        return 0;
 162}
 163
 164void timer_init_r(void)
 165{
 166        /* init the timestamp and lastdec value */
 167        lastdec = read_timer();
 168        timestamp = 0;
 169}
 170
 171/*
 172 * This function is derived from PowerPC code (read timebase as long long).
 173 * On ARM it just returns the timer value.
 174 */
 175unsigned long long get_ticks(void)
 176{
 177        return get_timer(0);
 178}
 179
 180/*
 181 * This function is derived from PowerPC code (timebase clock frequency).
 182 * On ARM it returns the number of timer ticks per second.
 183 */
 184ulong get_tbclk (void)
 185{
 186        return (ulong)CONFIG_SYS_HZ;
 187}
 188