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