1ea0364f1SPeter Tyser /* 2ea0364f1SPeter Tyser * (C) Copyright 2009 3ea0364f1SPeter Tyser * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 4ea0364f1SPeter Tyser * 561973afcSNobuhiro Iwamatsu * (C) Copyright 2007-2010 6ea0364f1SPeter Tyser * Nobobuhiro Iwamatsu <iwamatsu@nigauri.org> 7ea0364f1SPeter Tyser * 8ea0364f1SPeter Tyser * (C) Copyright 2003 9ea0364f1SPeter Tyser * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 10ea0364f1SPeter Tyser * 11ea0364f1SPeter Tyser * See file CREDITS for list of people who contributed to this 12ea0364f1SPeter Tyser * project. 13ea0364f1SPeter Tyser * 14ea0364f1SPeter Tyser * This program is free software; you can redistribute it and/or 15ea0364f1SPeter Tyser * modify it under the terms of the GNU General Public License as 16ea0364f1SPeter Tyser * published by the Free Software Foundation; either version 2 of 17ea0364f1SPeter Tyser * the License, or (at your option) any later version. 18ea0364f1SPeter Tyser * 19ea0364f1SPeter Tyser * This program is distributed in the hope that it will be useful, 20ea0364f1SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 21ea0364f1SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22ea0364f1SPeter Tyser * GNU General Public License for more details. 23ea0364f1SPeter Tyser * 24ea0364f1SPeter Tyser * You should have received a copy of the GNU General Public License 25ea0364f1SPeter Tyser * along with this program; if not, write to the Free Software 26ea0364f1SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 27ea0364f1SPeter Tyser * MA 02111-1307 USA 28ea0364f1SPeter Tyser */ 29ea0364f1SPeter Tyser 30ea0364f1SPeter Tyser #include <common.h> 31ea0364f1SPeter Tyser #include <div64.h> 32ea0364f1SPeter Tyser #include <asm/processor.h> 33ea0364f1SPeter Tyser #include <asm/clk.h> 34ea0364f1SPeter Tyser #include <asm/io.h> 35ea0364f1SPeter Tyser 36ea0364f1SPeter Tyser #define TMU_MAX_COUNTER (~0UL) 37ea0364f1SPeter Tyser 38ea0364f1SPeter Tyser static ulong timer_freq; 3961973afcSNobuhiro Iwamatsu static unsigned long last_tcnt; 4061973afcSNobuhiro Iwamatsu static unsigned long long overflow_ticks; 41ea0364f1SPeter Tyser 42ea0364f1SPeter Tyser static inline unsigned long long tick_to_time(unsigned long long tick) 43ea0364f1SPeter Tyser { 44ea0364f1SPeter Tyser tick *= CONFIG_SYS_HZ; 45ea0364f1SPeter Tyser do_div(tick, timer_freq); 46ea0364f1SPeter Tyser 47ea0364f1SPeter Tyser return tick; 48ea0364f1SPeter Tyser } 49ea0364f1SPeter Tyser 50ea0364f1SPeter Tyser static inline unsigned long long usec_to_tick(unsigned long long usec) 51ea0364f1SPeter Tyser { 52ea0364f1SPeter Tyser usec *= timer_freq; 53ea0364f1SPeter Tyser do_div(usec, 1000000); 54ea0364f1SPeter Tyser 55ea0364f1SPeter Tyser return usec; 56ea0364f1SPeter Tyser } 57ea0364f1SPeter Tyser 58ea0364f1SPeter Tyser static void tmu_timer_start (unsigned int timer) 59ea0364f1SPeter Tyser { 60ea0364f1SPeter Tyser if (timer > 2) 61ea0364f1SPeter Tyser return; 62ea0364f1SPeter Tyser writeb(readb(TSTR) | (1 << timer), TSTR); 63ea0364f1SPeter Tyser } 64ea0364f1SPeter Tyser 65ea0364f1SPeter Tyser static void tmu_timer_stop (unsigned int timer) 66ea0364f1SPeter Tyser { 67ea0364f1SPeter Tyser if (timer > 2) 68ea0364f1SPeter Tyser return; 69ea0364f1SPeter Tyser writeb(readb(TSTR) & ~(1 << timer), TSTR); 70ea0364f1SPeter Tyser } 71ea0364f1SPeter Tyser 72ea0364f1SPeter Tyser int timer_init (void) 73ea0364f1SPeter Tyser { 74ea0364f1SPeter Tyser /* Divide clock by CONFIG_SYS_TMU_CLK_DIV */ 75ea0364f1SPeter Tyser u16 bit = 0; 76ea0364f1SPeter Tyser 77ea0364f1SPeter Tyser switch (CONFIG_SYS_TMU_CLK_DIV) { 78ea0364f1SPeter Tyser case 1024: 79ea0364f1SPeter Tyser bit = 4; 80ea0364f1SPeter Tyser break; 81ea0364f1SPeter Tyser case 256: 82ea0364f1SPeter Tyser bit = 3; 83ea0364f1SPeter Tyser break; 84ea0364f1SPeter Tyser case 64: 85ea0364f1SPeter Tyser bit = 2; 86ea0364f1SPeter Tyser break; 87ea0364f1SPeter Tyser case 16: 88ea0364f1SPeter Tyser bit = 1; 89ea0364f1SPeter Tyser break; 90ea0364f1SPeter Tyser case 4: 91ea0364f1SPeter Tyser default: 92ea0364f1SPeter Tyser break; 93ea0364f1SPeter Tyser } 94ea0364f1SPeter Tyser writew(readw(TCR0) | bit, TCR0); 95ea0364f1SPeter Tyser 96ea0364f1SPeter Tyser /* Calc clock rate */ 97ea0364f1SPeter Tyser timer_freq = get_tmu0_clk_rate() >> ((bit + 1) * 2); 98ea0364f1SPeter Tyser 99ea0364f1SPeter Tyser tmu_timer_stop(0); 100ea0364f1SPeter Tyser tmu_timer_start(0); 101ea0364f1SPeter Tyser 10261973afcSNobuhiro Iwamatsu last_tcnt = 0; 10361973afcSNobuhiro Iwamatsu overflow_ticks = 0; 10461973afcSNobuhiro Iwamatsu 105ea0364f1SPeter Tyser return 0; 106ea0364f1SPeter Tyser } 107ea0364f1SPeter Tyser 108ea0364f1SPeter Tyser unsigned long long get_ticks (void) 109ea0364f1SPeter Tyser { 11061973afcSNobuhiro Iwamatsu unsigned long tcnt = 0 - readl(TCNT0); 11161973afcSNobuhiro Iwamatsu 112*78df8c68SNobuhiro Iwamatsu if (last_tcnt > tcnt) /* overflow */ 11361973afcSNobuhiro Iwamatsu overflow_ticks++; 11461973afcSNobuhiro Iwamatsu last_tcnt = tcnt; 11561973afcSNobuhiro Iwamatsu 11661973afcSNobuhiro Iwamatsu return (overflow_ticks << 32) | tcnt; 117ea0364f1SPeter Tyser } 118ea0364f1SPeter Tyser 119ea0364f1SPeter Tyser void __udelay (unsigned long usec) 120ea0364f1SPeter Tyser { 121ea0364f1SPeter Tyser unsigned long long tmp; 122ea0364f1SPeter Tyser ulong tmo; 123ea0364f1SPeter Tyser 124ea0364f1SPeter Tyser tmo = usec_to_tick(usec); 125ea0364f1SPeter Tyser tmp = get_ticks() + tmo; /* get current timestamp */ 126ea0364f1SPeter Tyser 127ea0364f1SPeter Tyser while (get_ticks() < tmp) /* loop till event */ 128ea0364f1SPeter Tyser /*NOP*/; 129ea0364f1SPeter Tyser } 130ea0364f1SPeter Tyser 131ea0364f1SPeter Tyser unsigned long get_timer (unsigned long base) 132ea0364f1SPeter Tyser { 133ea0364f1SPeter Tyser /* return msec */ 134ea0364f1SPeter Tyser return tick_to_time(get_ticks()) - base; 135ea0364f1SPeter Tyser } 136ea0364f1SPeter Tyser 137ea0364f1SPeter Tyser unsigned long get_tbclk (void) 138ea0364f1SPeter Tyser { 139ea0364f1SPeter Tyser return timer_freq; 140ea0364f1SPeter Tyser } 141