1/* 2 * (C) Copyright 2010 3 * Michael Schwingen, michael@schwingen.org 4 * 5 * (C) Copyright 2006 6 * Stefan Roese, DENX Software Engineering, sr@denx.de. 7 * 8 * (C) Copyright 2002 9 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 10 * Marius Groeger <mgroeger@sysgo.de> 11 * 12 * (C) Copyright 2002 13 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 14 * Alex Zuepke <azu@sysgo.de> 15 * 16 * See file CREDITS for list of people who contributed to this 17 * project. 18 * 19 * This program is free software; you can redistribute it and/or 20 * modify it under the terms of the GNU General Public License as 21 * published by the Free Software Foundation; either version 2 of 22 * the License, or (at your option) any later version. 23 * 24 * This program is distributed in the hope that it will be useful, 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * GNU General Public License for more details. 28 * 29 * You should have received a copy of the GNU General Public License 30 * along with this program; if not, write to the Free Software 31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 32 * MA 02111-1307 USA 33 */ 34 35#include <common.h> 36#include <asm/arch/ixp425.h> 37#include <asm/io.h> 38#include <div64.h> 39 40DECLARE_GLOBAL_DATA_PTR; 41 42/* 43 * The IXP42x time-stamp timer runs at 2*OSC_IN (66.666MHz when using a 44 * 33.333MHz crystal). 45 */ 46static inline unsigned long long tick_to_time(unsigned long long tick) 47{ 48 tick *= CONFIG_SYS_HZ; 49 do_div(tick, CONFIG_IXP425_TIMER_CLK); 50 return tick; 51} 52 53static inline unsigned long long time_to_tick(unsigned long long time) 54{ 55 time *= CONFIG_IXP425_TIMER_CLK; 56 do_div(time, CONFIG_SYS_HZ); 57 return time; 58} 59 60static inline unsigned long long us_to_tick(unsigned long long us) 61{ 62 us = us * CONFIG_IXP425_TIMER_CLK + 999999; 63 do_div(us, 1000000); 64 return us; 65} 66 67unsigned long long get_ticks(void) 68{ 69 ulong now = readl(IXP425_OSTS_B); 70 71 if (readl(IXP425_OSST) & IXP425_OSST_TIMER_TS_PEND) { 72 /* rollover of timestamp timer register */ 73 gd->timestamp += (0xFFFFFFFF - gd->lastinc) + now + 1; 74 writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST); 75 } else { 76 /* move stamp forward with absolut diff ticks */ 77 gd->timestamp += (now - gd->lastinc); 78 } 79 gd->lastinc = now; 80 return gd->timestamp; 81} 82 83 84void reset_timer_masked(void) 85{ 86 /* capture current timestamp counter */ 87 gd->lastinc = readl(IXP425_OSTS_B); 88 /* start "advancing" time stamp from 0 */ 89 gd->timestamp = 0; 90} 91 92ulong get_timer_masked(void) 93{ 94 return tick_to_time(get_ticks()); 95} 96 97ulong get_timer(ulong base) 98{ 99 return get_timer_masked() - base; 100} 101 102/* delay x useconds AND preserve advance timestamp value */ 103void __udelay(unsigned long usec) 104{ 105 unsigned long long tmp; 106 107 tmp = get_ticks() + us_to_tick(usec); 108 109 while (get_ticks() < tmp) 110 ; 111} 112 113int timer_init(void) 114{ 115 writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST); 116 return 0; 117} 118