1ea0364f1SPeter Tyser /* 2ea0364f1SPeter Tyser * (C) Copyright 2009 3ea0364f1SPeter Tyser * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 4ea0364f1SPeter Tyser * 573f35e0bSNobuhiro Iwamatsu * (C) Copyright 2007-2012 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 * 111a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 12ea0364f1SPeter Tyser */ 13ea0364f1SPeter Tyser 14ea0364f1SPeter Tyser #include <common.h> 15ea0364f1SPeter Tyser #include <div64.h> 16ea0364f1SPeter Tyser #include <asm/processor.h> 17ea0364f1SPeter Tyser #include <asm/io.h> 1873f35e0bSNobuhiro Iwamatsu #include <sh_tmu.h> 1973f35e0bSNobuhiro Iwamatsu 20*861bd4bcSNobuhiro Iwamatsu #define TCR_TPSC 0x07 21*861bd4bcSNobuhiro Iwamatsu 2273f35e0bSNobuhiro Iwamatsu static struct tmu_regs *tmu = (struct tmu_regs *)TMU_BASE; 23ea0364f1SPeter Tyser 24d4430426SNobuhiro Iwamatsu static u16 bit; 2561973afcSNobuhiro Iwamatsu static unsigned long last_tcnt; 2661973afcSNobuhiro Iwamatsu static unsigned long long overflow_ticks; 27ea0364f1SPeter Tyser 28d4430426SNobuhiro Iwamatsu unsigned long get_tbclk(void) 29d4430426SNobuhiro Iwamatsu { 30d4430426SNobuhiro Iwamatsu return get_tmu0_clk_rate() >> ((bit + 1) * 2); 31d4430426SNobuhiro Iwamatsu } 32d4430426SNobuhiro Iwamatsu 33ea0364f1SPeter Tyser static inline unsigned long long tick_to_time(unsigned long long tick) 34ea0364f1SPeter Tyser { 35ea0364f1SPeter Tyser tick *= CONFIG_SYS_HZ; 36d4430426SNobuhiro Iwamatsu do_div(tick, get_tbclk()); 37ea0364f1SPeter Tyser 38ea0364f1SPeter Tyser return tick; 39ea0364f1SPeter Tyser } 40ea0364f1SPeter Tyser 41ea0364f1SPeter Tyser static inline unsigned long long usec_to_tick(unsigned long long usec) 42ea0364f1SPeter Tyser { 43d4430426SNobuhiro Iwamatsu usec *= get_tbclk(); 44ea0364f1SPeter Tyser do_div(usec, 1000000); 45ea0364f1SPeter Tyser 46ea0364f1SPeter Tyser return usec; 47ea0364f1SPeter Tyser } 48ea0364f1SPeter Tyser 49ea0364f1SPeter Tyser static void tmu_timer_start(unsigned int timer) 50ea0364f1SPeter Tyser { 51ea0364f1SPeter Tyser if (timer > 2) 52ea0364f1SPeter Tyser return; 5373f35e0bSNobuhiro Iwamatsu writeb(readb(&tmu->tstr) | (1 << timer), &tmu->tstr); 54ea0364f1SPeter Tyser } 55ea0364f1SPeter Tyser 56ea0364f1SPeter Tyser static void tmu_timer_stop(unsigned int timer) 57ea0364f1SPeter Tyser { 58ea0364f1SPeter Tyser if (timer > 2) 59ea0364f1SPeter Tyser return; 6073f35e0bSNobuhiro Iwamatsu writeb(readb(&tmu->tstr) & ~(1 << timer), &tmu->tstr); 61ea0364f1SPeter Tyser } 62ea0364f1SPeter Tyser 63ea0364f1SPeter Tyser int timer_init(void) 64ea0364f1SPeter Tyser { 65d4430426SNobuhiro Iwamatsu bit = (ffs(CONFIG_SYS_TMU_CLK_DIV) >> 1) - 1; 66*861bd4bcSNobuhiro Iwamatsu writew((readw(&tmu->tcr0) & ~TCR_TPSC) | bit, &tmu->tcr0); 67ea0364f1SPeter Tyser 68ea0364f1SPeter Tyser tmu_timer_stop(0); 69ea0364f1SPeter Tyser tmu_timer_start(0); 70ea0364f1SPeter Tyser 7161973afcSNobuhiro Iwamatsu last_tcnt = 0; 7261973afcSNobuhiro Iwamatsu overflow_ticks = 0; 7361973afcSNobuhiro Iwamatsu 74ea0364f1SPeter Tyser return 0; 75ea0364f1SPeter Tyser } 76ea0364f1SPeter Tyser 77ea0364f1SPeter Tyser unsigned long long get_ticks(void) 78ea0364f1SPeter Tyser { 7973f35e0bSNobuhiro Iwamatsu unsigned long tcnt = 0 - readl(&tmu->tcnt0); 8061973afcSNobuhiro Iwamatsu 8178df8c68SNobuhiro Iwamatsu if (last_tcnt > tcnt) /* overflow */ 8261973afcSNobuhiro Iwamatsu overflow_ticks++; 8361973afcSNobuhiro Iwamatsu last_tcnt = tcnt; 8461973afcSNobuhiro Iwamatsu 8561973afcSNobuhiro Iwamatsu return (overflow_ticks << 32) | tcnt; 86ea0364f1SPeter Tyser } 87ea0364f1SPeter Tyser 88ea0364f1SPeter Tyser void __udelay(unsigned long usec) 89ea0364f1SPeter Tyser { 90ea0364f1SPeter Tyser unsigned long long tmp; 91ea0364f1SPeter Tyser ulong tmo; 92ea0364f1SPeter Tyser 93ea0364f1SPeter Tyser tmo = usec_to_tick(usec); 94ea0364f1SPeter Tyser tmp = get_ticks() + tmo; /* get current timestamp */ 95ea0364f1SPeter Tyser 96ea0364f1SPeter Tyser while (get_ticks() < tmp) /* loop till event */ 97ea0364f1SPeter Tyser /*NOP*/; 98ea0364f1SPeter Tyser } 99ea0364f1SPeter Tyser 100ea0364f1SPeter Tyser unsigned long get_timer(unsigned long base) 101ea0364f1SPeter Tyser { 102ea0364f1SPeter Tyser /* return msec */ 103ea0364f1SPeter Tyser return tick_to_time(get_ticks()) - base; 104ea0364f1SPeter Tyser } 105ea0364f1SPeter Tyser 106d4430426SNobuhiro Iwamatsu void set_timer(unsigned long t) 107ea0364f1SPeter Tyser { 108d4430426SNobuhiro Iwamatsu writel((0 - t), &tmu->tcnt0); 109d4430426SNobuhiro Iwamatsu } 110d4430426SNobuhiro Iwamatsu 111d4430426SNobuhiro Iwamatsu void reset_timer(void) 112d4430426SNobuhiro Iwamatsu { 113d4430426SNobuhiro Iwamatsu tmu_timer_stop(0); 114d4430426SNobuhiro Iwamatsu set_timer(0); 115d4430426SNobuhiro Iwamatsu tmu_timer_start(0); 116ea0364f1SPeter Tyser } 117