1/* 2 * TNETV107X: Timer implementation 3 * 4 * See file CREDITS for list of people who contributed to this 5 * project. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22#include <common.h> 23#include <asm/io.h> 24#include <asm/arch/clock.h> 25 26struct timer_regs { 27 u_int32_t pid12; 28 u_int32_t pad[3]; 29 u_int32_t tim12; 30 u_int32_t tim34; 31 u_int32_t prd12; 32 u_int32_t prd34; 33 u_int32_t tcr; 34 u_int32_t tgcr; 35 u_int32_t wdtcr; 36}; 37 38#define regs ((struct timer_regs *)CONFIG_SYS_TIMERBASE) 39 40#define TIMER_LOAD_VAL (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ) 41#define TIM_CLK_DIV 16 42 43static ulong timestamp; 44static ulong lastinc; 45 46int timer_init(void) 47{ 48 clk_enable(TNETV107X_LPSC_TIMER0); 49 50 lastinc = timestamp = 0; 51 52 /* We are using timer34 in unchained 32-bit mode, full speed */ 53 __raw_writel(0x0, ®s->tcr); 54 __raw_writel(0x0, ®s->tgcr); 55 __raw_writel(0x06 | ((TIM_CLK_DIV - 1) << 8), ®s->tgcr); 56 __raw_writel(0x0, ®s->tim34); 57 __raw_writel(TIMER_LOAD_VAL, ®s->prd34); 58 __raw_writel(2 << 22, ®s->tcr); 59 60 return 0; 61} 62 63static ulong get_timer_raw(void) 64{ 65 ulong now = __raw_readl(®s->tim34); 66 67 if (now >= lastinc) 68 timestamp += now - lastinc; 69 else 70 timestamp += now + TIMER_LOAD_VAL - lastinc; 71 72 lastinc = now; 73 74 return timestamp; 75} 76 77ulong get_timer(ulong base) 78{ 79 return (get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base; 80} 81 82unsigned long long get_ticks(void) 83{ 84 return get_timer(0); 85} 86 87void __udelay(unsigned long usec) 88{ 89 ulong tmo; 90 ulong endtime; 91 signed long diff; 92 93 tmo = CONFIG_SYS_HZ_CLOCK / 1000; 94 tmo *= usec; 95 tmo /= (1000 * TIM_CLK_DIV); 96 97 endtime = get_timer_raw() + tmo; 98 99 do { 100 ulong now = get_timer_raw(); 101 diff = endtime - now; 102 } while (diff >= 0); 103} 104 105ulong get_tbclk(void) 106{ 107 return CONFIG_SYS_HZ; 108} 109