uboot/arch/arm/cpu/arm926ejs/spear/timer.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2009
   3 * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <asm/io.h>
  10#include <asm/arch/hardware.h>
  11#include <asm/arch/spr_gpt.h>
  12#include <asm/arch/spr_misc.h>
  13
  14#define GPT_RESOLUTION  (CONFIG_SPEAR_HZ_CLOCK / CONFIG_SPEAR_HZ)
  15#define READ_TIMER()    (readl(&gpt_regs_p->count) & GPT_FREE_RUNNING)
  16
  17static struct gpt_regs *const gpt_regs_p =
  18    (struct gpt_regs *)CONFIG_SPEAR_TIMERBASE;
  19
  20static struct misc_regs *const misc_regs_p =
  21    (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
  22
  23DECLARE_GLOBAL_DATA_PTR;
  24
  25#define timestamp gd->arch.tbl
  26#define lastdec gd->arch.lastinc
  27
  28int timer_init(void)
  29{
  30        u32 synth;
  31
  32        /* Prescaler setting */
  33#if defined(CONFIG_SPEAR3XX)
  34        writel(MISC_PRSC_CFG, &misc_regs_p->prsc2_clk_cfg);
  35        synth = MISC_GPT4SYNTH;
  36#elif defined(CONFIG_SPEAR600)
  37        writel(MISC_PRSC_CFG, &misc_regs_p->prsc1_clk_cfg);
  38        synth = MISC_GPT3SYNTH;
  39#else
  40# error Incorrect config. Can only be SPEAR{600|300|310|320}
  41#endif
  42
  43        writel(readl(&misc_regs_p->periph_clk_cfg) | synth,
  44               &misc_regs_p->periph_clk_cfg);
  45
  46        /* disable timers */
  47        writel(GPT_PRESCALER_1 | GPT_MODE_AUTO_RELOAD, &gpt_regs_p->control);
  48
  49        /* load value for free running */
  50        writel(GPT_FREE_RUNNING, &gpt_regs_p->compare);
  51
  52        /* auto reload, start timer */
  53        writel(readl(&gpt_regs_p->control) | GPT_ENABLE, &gpt_regs_p->control);
  54
  55        /* Reset the timer */
  56        lastdec = READ_TIMER();
  57        timestamp = 0;
  58
  59        return 0;
  60}
  61
  62/*
  63 * timer without interrupts
  64 */
  65ulong get_timer(ulong base)
  66{
  67        return (get_timer_masked() / GPT_RESOLUTION) - base;
  68}
  69
  70void __udelay(unsigned long usec)
  71{
  72        ulong tmo;
  73        ulong start = get_timer_masked();
  74        ulong tenudelcnt = CONFIG_SPEAR_HZ_CLOCK / (1000 * 100);
  75        ulong rndoff;
  76
  77        rndoff = (usec % 10) ? 1 : 0;
  78
  79        /* tenudelcnt timer tick gives 10 microsecconds delay */
  80        tmo = ((usec / 10) + rndoff) * tenudelcnt;
  81
  82        while ((ulong) (get_timer_masked() - start) < tmo)
  83                ;
  84}
  85
  86ulong get_timer_masked(void)
  87{
  88        ulong now = READ_TIMER();
  89
  90        if (now >= lastdec) {
  91                /* normal mode */
  92                timestamp += now - lastdec;
  93        } else {
  94                /* we have an overflow ... */
  95                timestamp += now + GPT_FREE_RUNNING - lastdec;
  96        }
  97        lastdec = now;
  98
  99        return timestamp;
 100}
 101
 102void udelay_masked(unsigned long usec)
 103{
 104        return udelay(usec);
 105}
 106
 107/*
 108 * This function is derived from PowerPC code (read timebase as long long).
 109 * On ARM it just returns the timer value.
 110 */
 111unsigned long long get_ticks(void)
 112{
 113        return get_timer(0);
 114}
 115
 116/*
 117 * This function is derived from PowerPC code (timebase clock frequency).
 118 * On ARM it returns the number of timer ticks per second.
 119 */
 120ulong get_tbclk(void)
 121{
 122        return CONFIG_SPEAR_HZ;
 123}
 124