1/* 2 * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> 3 * (C) Copyright 2011, Julius Baxter <julius@opencores.org> 4 * (C) Copyright 2003 5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10#include <common.h> 11#include <asm/system.h> 12#include <asm/openrisc_exc.h> 13 14static ulong timestamp; 15 16/* how many counter cycles in a jiffy */ 17#define TIMER_COUNTER_CYCLES (CONFIG_SYS_CLK_FREQ/CONFIG_SYS_OPENRISC_TMR_HZ) 18/* how many ms elapses between each timer interrupt */ 19#define TIMER_TIMESTAMP_INC (1000/CONFIG_SYS_OPENRISC_TMR_HZ) 20/* how many cycles per ms */ 21#define TIMER_CYCLES_MS (CONFIG_SYS_CLK_FREQ/1000) 22/* how many cycles per us */ 23#define TIMER_CYCLES_US (CONFIG_SYS_CLK_FREQ/1000000uL) 24 25void timer_isr(void) 26{ 27 timestamp += TIMER_TIMESTAMP_INC; 28 mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | 29 (TIMER_COUNTER_CYCLES & SPR_TTMR_TP)); 30} 31 32int timer_init(void) 33{ 34 /* Install timer exception handler */ 35 exception_install_handler(EXC_TIMER, timer_isr); 36 37 /* Set up the timer for the first expiration. */ 38 timestamp = 0; 39 40 mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | 41 (TIMER_COUNTER_CYCLES & SPR_TTMR_TP)); 42 43 /* Enable tick timer exception in supervisor register */ 44 mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_TEE); 45 46 return 0; 47} 48 49void reset_timer(void) 50{ 51 timestamp = 0; 52 53 mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT | 54 (TIMER_COUNTER_CYCLES & SPR_TTMR_TP)); 55} 56 57/* 58 * The timer value in ms is calculated by taking the 59 * value accumulated by full timer revolutions plus the value 60 * accumulated in this period 61 */ 62ulong get_timer(ulong base) 63{ 64 return timestamp + mfspr(SPR_TTCR)/TIMER_CYCLES_MS - base; 65} 66 67void set_timer(ulong t) 68{ 69 reset_timer(); 70 timestamp = t; 71} 72 73unsigned long long get_ticks(void) 74{ 75 return get_timer(0); 76} 77 78ulong get_tbclk(void) 79{ 80 return CONFIG_SYS_HZ; 81} 82 83void __udelay(ulong usec) 84{ 85 ulong elapsed = 0; 86 ulong tick; 87 ulong last_tick; 88 89 last_tick = mfspr(SPR_TTCR); 90 while ((elapsed / TIMER_CYCLES_US) < usec) { 91 tick = mfspr(SPR_TTCR); 92 if (tick >= last_tick) 93 elapsed += (tick - last_tick); 94 else 95 elapsed += TIMER_COUNTER_CYCLES - (last_tick - tick); 96 last_tick = tick; 97 } 98} 99