uboot/arch/arm/mach-orion5x/timer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3  * Copyright (C) 2010 Albert ARIBAUD <albert.u.boot@aribaud.net>
   4 *
   5 * Based on original Kirkwood support which is
   6 * Copyright (C) Marvell International Ltd. and its affiliates
   7 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
   8 */
   9
  10#include <common.h>
  11#include <asm/io.h>
  12
  13#define UBOOT_CNTR      0       /* counter to use for uboot timer */
  14
  15/* Timer reload and current value registers */
  16struct orion5x_tmr_val {
  17        u32 reload;     /* Timer reload reg */
  18        u32 val;        /* Timer value reg */
  19};
  20
  21/* Timer registers */
  22struct orion5x_tmr_registers {
  23        u32 ctrl;       /* Timer control reg */
  24        u32 pad[3];
  25        struct orion5x_tmr_val tmr[2];
  26        u32 wdt_reload;
  27        u32 wdt_val;
  28};
  29
  30struct orion5x_tmr_registers *orion5x_tmr_regs =
  31        (struct orion5x_tmr_registers *)ORION5X_TIMER_BASE;
  32
  33/*
  34 * ARM Timers Registers Map
  35 */
  36#define CNTMR_CTRL_REG                  (&orion5x_tmr_regs->ctrl)
  37#define CNTMR_RELOAD_REG(tmrnum)        (&orion5x_tmr_regs->tmr[tmrnum].reload)
  38#define CNTMR_VAL_REG(tmrnum)           (&orion5x_tmr_regs->tmr[tmrnum].val)
  39
  40/*
  41 * ARM Timers Control Register
  42 * CPU_TIMERS_CTRL_REG (CTCR)
  43 */
  44#define CTCR_ARM_TIMER_EN_OFFS(cntr)    (cntr * 2)
  45#define CTCR_ARM_TIMER_EN_MASK(cntr)    (1 << CTCR_ARM_TIMER_EN_OFFS)
  46#define CTCR_ARM_TIMER_EN(cntr)         (1 << CTCR_ARM_TIMER_EN_OFFS(cntr))
  47#define CTCR_ARM_TIMER_DIS(cntr)        (0 << CTCR_ARM_TIMER_EN_OFFS(cntr))
  48
  49#define CTCR_ARM_TIMER_AUTO_OFFS(cntr)  ((cntr * 2) + 1)
  50#define CTCR_ARM_TIMER_AUTO_MASK(cntr)  (1 << 1)
  51#define CTCR_ARM_TIMER_AUTO_EN(cntr)    (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
  52#define CTCR_ARM_TIMER_AUTO_DIS(cntr)   (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
  53
  54/*
  55 * ARM Timer\Watchdog Reload Register
  56 * CNTMR_RELOAD_REG (TRR)
  57 */
  58#define TRG_ARM_TIMER_REL_OFFS          0
  59#define TRG_ARM_TIMER_REL_MASK          0xffffffff
  60
  61/*
  62 * ARM Timer\Watchdog Register
  63 * CNTMR_VAL_REG (TVRG)
  64 */
  65#define TVR_ARM_TIMER_OFFS              0
  66#define TVR_ARM_TIMER_MASK              0xffffffff
  67#define TVR_ARM_TIMER_MAX               0xffffffff
  68#define TIMER_LOAD_VAL                  0xffffffff
  69
  70static inline ulong read_timer(void)
  71{
  72        return readl(CNTMR_VAL_REG(UBOOT_CNTR))
  73              / (CONFIG_SYS_TCLK / 1000);
  74}
  75
  76DECLARE_GLOBAL_DATA_PTR;
  77
  78#define timestamp gd->arch.tbl
  79#define lastdec gd->arch.lastinc
  80
  81static ulong get_timer_masked(void)
  82{
  83        ulong now = read_timer();
  84
  85        if (lastdec >= now) {
  86                /* normal mode */
  87                timestamp += lastdec - now;
  88        } else {
  89                /* we have an overflow ... */
  90                timestamp += lastdec +
  91                        (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now;
  92        }
  93        lastdec = now;
  94
  95        return timestamp;
  96}
  97
  98ulong get_timer(ulong base)
  99{
 100        return get_timer_masked() - base;
 101}
 102
 103static inline ulong uboot_cntr_val(void)
 104{
 105        return readl(CNTMR_VAL_REG(UBOOT_CNTR));
 106}
 107
 108void __udelay(unsigned long usec)
 109{
 110        uint current;
 111        ulong delayticks;
 112
 113        current = uboot_cntr_val();
 114        delayticks = (usec * (CONFIG_SYS_TCLK / 1000000));
 115
 116        if (current < delayticks) {
 117                delayticks -= current;
 118                while (uboot_cntr_val() < current)
 119                        ;
 120                while ((TIMER_LOAD_VAL - delayticks) < uboot_cntr_val())
 121                        ;
 122        } else {
 123                while (uboot_cntr_val() > (current - delayticks))
 124                        ;
 125        }
 126}
 127
 128/*
 129 * init the counter
 130 */
 131int timer_init(void)
 132{
 133        unsigned int cntmrctrl;
 134
 135        /* load value into timer */
 136        writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR));
 137        writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR));
 138
 139        /* enable timer in auto reload mode */
 140        cntmrctrl = readl(CNTMR_CTRL_REG);
 141        cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR);
 142        cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR);
 143        writel(cntmrctrl, CNTMR_CTRL_REG);
 144        return 0;
 145}
 146
 147void timer_init_r(void)
 148{
 149        /* init the timestamp and lastdec value */
 150        lastdec = read_timer();
 151        timestamp = 0;
 152}
 153
 154/*
 155 * This function is derived from PowerPC code (read timebase as long long).
 156 * On ARM it just returns the timer value.
 157 */
 158unsigned long long get_ticks(void)
 159{
 160        return get_timer(0);
 161}
 162
 163/*
 164 * This function is derived from PowerPC code (timebase clock frequency).
 165 * On ARM it returns the number of timer ticks per second.
 166 */
 167ulong get_tbclk (void)
 168{
 169        return (ulong)CONFIG_SYS_HZ;
 170}
 171