uboot/arch/microblaze/cpu/timer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2007 Michal Simek
   4 *
   5 * Michal  SIMEK <monstr@monstr.eu>
   6 */
   7
   8#include <common.h>
   9#include <fdtdec.h>
  10#include <asm/microblaze_timer.h>
  11#include <asm/microblaze_intc.h>
  12
  13DECLARE_GLOBAL_DATA_PTR;
  14
  15volatile int timestamp = 0;
  16microblaze_timer_t *tmr;
  17
  18ulong get_timer (ulong base)
  19{
  20        if (tmr)
  21                return timestamp - base;
  22        return timestamp++ - base;
  23}
  24
  25void __udelay(unsigned long usec)
  26{
  27        u32 i;
  28
  29        if (tmr) {
  30                i = get_timer(0);
  31                while ((get_timer(0) - i) < (usec / 1000))
  32                        ;
  33        }
  34}
  35
  36#ifndef CONFIG_SPL_BUILD
  37static void timer_isr(void *arg)
  38{
  39        timestamp++;
  40        tmr->control = tmr->control | TIMER_INTERRUPT;
  41}
  42
  43int timer_init (void)
  44{
  45        int irq = -1;
  46        u32 preload = 0;
  47        u32 ret = 0;
  48        const void *blob = gd->fdt_blob;
  49        int node = 0;
  50        u32 cell[2];
  51
  52        debug("TIMER: Initialization\n");
  53
  54        /* Do not init before relocation */
  55        if (!(gd->flags & GD_FLG_RELOC))
  56                return 0;
  57
  58        node = fdt_node_offset_by_compatible(blob, node,
  59                                "xlnx,xps-timer-1.00.a");
  60        if (node != -1) {
  61                fdt_addr_t base = fdtdec_get_addr(blob, node, "reg");
  62                if (base == FDT_ADDR_T_NONE)
  63                        return -1;
  64
  65                debug("TIMER: Base addr %lx\n", base);
  66                tmr = (microblaze_timer_t *)base;
  67
  68                ret = fdtdec_get_int_array(blob, node, "interrupts",
  69                                            cell, ARRAY_SIZE(cell));
  70                if (ret)
  71                        return ret;
  72
  73                irq = cell[0];
  74                debug("TIMER: IRQ %x\n", irq);
  75
  76                preload = fdtdec_get_int(blob, node, "clock-frequency", 0);
  77                preload /= CONFIG_SYS_HZ;
  78        } else {
  79                return node;
  80        }
  81
  82        if (tmr && preload && irq >= 0) {
  83                tmr->loadreg = preload;
  84                tmr->control = TIMER_INTERRUPT | TIMER_RESET;
  85                tmr->control = TIMER_ENABLE | TIMER_ENABLE_INTR |\
  86                                        TIMER_RELOAD | TIMER_DOWN_COUNT;
  87                timestamp = 0;
  88                ret = install_interrupt_handler (irq, timer_isr, (void *)tmr);
  89                if (ret)
  90                        tmr = NULL;
  91        }
  92        /* No problem if timer is not found/initialized */
  93        return 0;
  94}
  95#else
  96int timer_init(void)
  97{
  98        return 0;
  99}
 100#endif
 101
 102/*
 103 * This function is derived from PowerPC code (read timebase as long long).
 104 * On Microblaze it just returns the timer value.
 105 */
 106unsigned long long get_ticks(void)
 107{
 108        return get_timer(0);
 109}
 110
 111/*
 112 * This function is derived from PowerPC code (timebase clock frequency).
 113 * On Microblaze it returns the number of timer ticks per second.
 114 */
 115ulong get_tbclk(void)
 116{
 117        return CONFIG_SYS_HZ;
 118}
 119