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 63void reset_timer(void) 64{ 65 lastinc = timestamp = 0; 66 67 __raw_writel(0, ®s->tcr); 68 __raw_writel(0, ®s->tim34); 69 __raw_writel(2 << 22, ®s->tcr); 70} 71 72static ulong get_timer_raw(void) 73{ 74 ulong now = __raw_readl(®s->tim34); 75 76 if (now >= lastinc) 77 timestamp += now - lastinc; 78 else 79 timestamp += now + TIMER_LOAD_VAL - lastinc; 80 81 lastinc = now; 82 83 return timestamp; 84} 85 86ulong get_timer(ulong base) 87{ 88 return (get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base; 89} 90 91void set_timer(ulong t) 92{ 93 timestamp = t; 94} 95 96unsigned long long get_ticks(void) 97{ 98 return get_timer(0); 99} 100 101void __udelay(unsigned long usec) 102{ 103 ulong tmo; 104 ulong endtime; 105 signed long diff; 106 107 tmo = CONFIG_SYS_HZ_CLOCK / 1000; 108 tmo *= usec; 109 tmo /= (1000 * TIM_CLK_DIV); 110 111 endtime = get_timer_raw() + tmo; 112 113 do { 114 ulong now = get_timer_raw(); 115 diff = endtime - now; 116 } while (diff >= 0); 117} 118 119ulong get_tbclk(void) 120{ 121 return CONFIG_SYS_HZ; 122} 123