blob: 663d9890899603b47b52a41d3139b312b5ad96d8 [file] [log] [blame]
wdenk2d5b5612003-10-14 19:43:55 +00001/*
Michael Schwingence04bb42011-05-23 00:00:00 +02002 * (C) Copyright 2010
3 * Michael Schwingen, michael@schwingen.org
4 *
Wolfgang Denkba94a1b2006-05-30 15:56:48 +02005 * (C) Copyright 2006
6 * Stefan Roese, DENX Software Engineering, sr@denx.de.
7 *
wdenk2d5b5612003-10-14 19:43:55 +00008 * (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>
Michael Schwingence04bb42011-05-23 00:00:00 +020037#include <asm/io.h>
38#include <div64.h>
wdenk2d5b5612003-10-14 19:43:55 +000039
Michael Schwingence04bb42011-05-23 00:00:00 +020040DECLARE_GLOBAL_DATA_PTR;
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020041
42/*
Michael Schwingence04bb42011-05-23 00:00:00 +020043 * The IXP42x time-stamp timer runs at 2*OSC_IN (66.666MHz when using a
44 * 33.333MHz crystal).
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020045 */
Michael Schwingence04bb42011-05-23 00:00:00 +020046static inline unsigned long long tick_to_time(unsigned long long tick)
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020047{
Michael Schwingence04bb42011-05-23 00:00:00 +020048 tick *= CONFIG_SYS_HZ;
49 do_div(tick, CONFIG_IXP425_TIMER_CLK);
50 return tick;
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020051}
52
Michael Schwingence04bb42011-05-23 00:00:00 +020053static inline unsigned long long time_to_tick(unsigned long long time)
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020054{
Michael Schwingence04bb42011-05-23 00:00:00 +020055 time *= CONFIG_IXP425_TIMER_CLK;
56 do_div(time, CONFIG_SYS_HZ);
57 return time;
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020058}
59
Michael Schwingence04bb42011-05-23 00:00:00 +020060static inline unsigned long long us_to_tick(unsigned long long us)
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020061{
Michael Schwingence04bb42011-05-23 00:00:00 +020062 us = us * CONFIG_IXP425_TIMER_CLK + 999999;
63 do_div(us, 1000000);
64 return us;
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020065}
66
Michael Schwingence04bb42011-05-23 00:00:00 +020067unsigned long long get_ticks(void)
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020068{
Michael Schwingence04bb42011-05-23 00:00:00 +020069 ulong now = readl(IXP425_OSTS_B);
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +020070
Michael Schwingence04bb42011-05-23 00:00:00 +020071 if (readl(IXP425_OSST) & IXP425_OSST_TIMER_TS_PEND) {
72 /* rollover of timestamp timer register */
Simon Glassb4d51db2012-12-13 20:48:37 +000073 gd->arch.timestamp += (0xFFFFFFFF - gd->arch.lastinc) + now + 1;
Michael Schwingence04bb42011-05-23 00:00:00 +020074 writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST);
75 } else {
76 /* move stamp forward with absolut diff ticks */
Simon Glassb4d51db2012-12-13 20:48:37 +000077 gd->arch.timestamp += (now - gd->arch.lastinc);
wdenk2d5b5612003-10-14 19:43:55 +000078 }
Simon Glass582601d2012-12-13 20:48:35 +000079 gd->arch.lastinc = now;
Simon Glassb4d51db2012-12-13 20:48:37 +000080 return gd->arch.timestamp;
Michael Schwingence04bb42011-05-23 00:00:00 +020081}
82
83
84void reset_timer_masked(void)
85{
86 /* capture current timestamp counter */
Simon Glass582601d2012-12-13 20:48:35 +000087 gd->arch.lastinc = readl(IXP425_OSTS_B);
Michael Schwingence04bb42011-05-23 00:00:00 +020088 /* start "advancing" time stamp from 0 */
Simon Glassb4d51db2012-12-13 20:48:37 +000089 gd->arch.timestamp = 0;
Michael Schwingence04bb42011-05-23 00:00:00 +020090}
91
Michael Schwingence04bb42011-05-23 00:00:00 +020092ulong 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
Michael Schwingence04bb42011-05-23 00:00:00 +0200102/* 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 ;
wdenk2d5b5612003-10-14 19:43:55 +0000111}
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +0200112
113int timer_init(void)
114{
Michael Schwingence04bb42011-05-23 00:00:00 +0200115 writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST);
Jean-Christophe PLAGNIOL-VILLARDb54384e2009-05-15 23:47:02 +0200116 return 0;
117}