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