1 /* 2 * (C) Copyright 2009 3 * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 4 * 5 * (C) Copyright 2007-2012 6 * Nobobuhiro Iwamatsu <iwamatsu@nigauri.org> 7 * 8 * (C) Copyright 2003 9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 10 * 11 * SPDX-License-Identifier: GPL-2.0+ 12 */ 13 14 #include <common.h> 15 #include <div64.h> 16 #include <asm/processor.h> 17 #include <asm/io.h> 18 #include <sh_tmu.h> 19 20 #define TCR_TPSC 0x07 21 22 static struct tmu_regs *tmu = (struct tmu_regs *)TMU_BASE; 23 24 static unsigned long last_tcnt; 25 static unsigned long long overflow_ticks; 26 27 unsigned long get_tbclk(void) 28 { 29 u16 tmu_bit = (ffs(CONFIG_SYS_TMU_CLK_DIV) >> 1) - 1; 30 return get_tmu0_clk_rate() >> ((tmu_bit + 1) * 2); 31 } 32 33 static inline unsigned long long tick_to_time(unsigned long long tick) 34 { 35 tick *= CONFIG_SYS_HZ; 36 do_div(tick, get_tbclk()); 37 38 return tick; 39 } 40 41 static inline unsigned long long usec_to_tick(unsigned long long usec) 42 { 43 usec *= get_tbclk(); 44 do_div(usec, 1000000); 45 46 return usec; 47 } 48 49 static void tmu_timer_start(unsigned int timer) 50 { 51 if (timer > 2) 52 return; 53 writeb(readb(&tmu->tstr) | (1 << timer), &tmu->tstr); 54 } 55 56 static void tmu_timer_stop(unsigned int timer) 57 { 58 if (timer > 2) 59 return; 60 writeb(readb(&tmu->tstr) & ~(1 << timer), &tmu->tstr); 61 } 62 63 int timer_init(void) 64 { 65 u16 tmu_bit = (ffs(CONFIG_SYS_TMU_CLK_DIV) >> 1) - 1; 66 writew((readw(&tmu->tcr0) & ~TCR_TPSC) | tmu_bit, &tmu->tcr0); 67 68 tmu_timer_stop(0); 69 tmu_timer_start(0); 70 71 last_tcnt = 0; 72 overflow_ticks = 0; 73 74 return 0; 75 } 76 77 unsigned long long get_ticks(void) 78 { 79 unsigned long tcnt = 0 - readl(&tmu->tcnt0); 80 81 if (last_tcnt > tcnt) /* overflow */ 82 overflow_ticks++; 83 last_tcnt = tcnt; 84 85 return (overflow_ticks << 32) | tcnt; 86 } 87 88 void __udelay(unsigned long usec) 89 { 90 unsigned long long tmp; 91 ulong tmo; 92 93 tmo = usec_to_tick(usec); 94 tmp = get_ticks() + tmo; /* get current timestamp */ 95 96 while (get_ticks() < tmp) /* loop till event */ 97 /*NOP*/; 98 } 99 100 unsigned long get_timer(unsigned long base) 101 { 102 /* return msec */ 103 return tick_to_time(get_ticks()) - base; 104 } 105 106 void set_timer(unsigned long t) 107 { 108 writel((0 - t), &tmu->tcnt0); 109 } 110 111 void reset_timer(void) 112 { 113 tmu_timer_stop(0); 114 set_timer(0); 115 tmu_timer_start(0); 116 } 117