blob: 38e2e2879c8e556694b51990e858c3b487a50ed0 [file] [log] [blame]
wdenkbd1575f2003-10-14 19:43:55 +00001/*
Michael Schwingen7ddf55e2011-05-23 00:00:00 +02002 * (C) Copyright 2010
3 * Michael Schwingen, michael@schwingen.org
4 *
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02005 * (C) Copyright 2006
6 * Stefan Roese, DENX Software Engineering, sr@denx.de.
7 *
wdenkbd1575f2003-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 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +020016 * SPDX-License-Identifier: GPL-2.0+
wdenkbd1575f2003-10-14 19:43:55 +000017 */
18
19#include <common.h>
20#include <asm/arch/ixp425.h>
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020021#include <asm/io.h>
22#include <div64.h>
wdenkbd1575f2003-10-14 19:43:55 +000023
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020024DECLARE_GLOBAL_DATA_PTR;
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020025
26/*
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020027 * The IXP42x time-stamp timer runs at 2*OSC_IN (66.666MHz when using a
28 * 33.333MHz crystal).
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020029 */
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020030static inline unsigned long long tick_to_time(unsigned long long tick)
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020031{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020032 tick *= CONFIG_SYS_HZ;
33 do_div(tick, CONFIG_IXP425_TIMER_CLK);
34 return tick;
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020035}
36
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020037static inline unsigned long long time_to_tick(unsigned long long time)
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020038{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020039 time *= CONFIG_IXP425_TIMER_CLK;
40 do_div(time, CONFIG_SYS_HZ);
41 return time;
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020042}
43
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020044static inline unsigned long long us_to_tick(unsigned long long us)
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020045{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020046 us = us * CONFIG_IXP425_TIMER_CLK + 999999;
47 do_div(us, 1000000);
48 return us;
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020049}
50
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020051unsigned long long get_ticks(void)
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020052{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020053 ulong now = readl(IXP425_OSTS_B);
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020054
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020055 if (readl(IXP425_OSST) & IXP425_OSST_TIMER_TS_PEND) {
56 /* rollover of timestamp timer register */
Simon Glassdddf3452012-12-13 20:48:37 +000057 gd->arch.timestamp += (0xFFFFFFFF - gd->arch.lastinc) + now + 1;
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020058 writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST);
59 } else {
60 /* move stamp forward with absolut diff ticks */
Simon Glassdddf3452012-12-13 20:48:37 +000061 gd->arch.timestamp += (now - gd->arch.lastinc);
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020062 }
Simon Glassa848da52012-12-13 20:48:35 +000063 gd->arch.lastinc = now;
Simon Glassdddf3452012-12-13 20:48:37 +000064 return gd->arch.timestamp;
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020065}
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020066
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020067
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020068void reset_timer_masked(void)
wdenk655a0f92003-10-30 21:49:38 +000069{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020070 /* capture current timestamp counter */
Simon Glassa848da52012-12-13 20:48:35 +000071 gd->arch.lastinc = readl(IXP425_OSTS_B);
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020072 /* start "advancing" time stamp from 0 */
Simon Glassdddf3452012-12-13 20:48:37 +000073 gd->arch.timestamp = 0;
wdenk655a0f92003-10-30 21:49:38 +000074}
75
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020076ulong get_timer_masked(void)
wdenkbd1575f2003-10-14 19:43:55 +000077{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020078 return tick_to_time(get_ticks());
wdenkbd1575f2003-10-14 19:43:55 +000079}
80
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020081ulong get_timer(ulong base)
wdenkbd1575f2003-10-14 19:43:55 +000082{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020083 return get_timer_masked() - base;
84}
wdenkbd1575f2003-10-14 19:43:55 +000085
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020086/* delay x useconds AND preserve advance timestamp value */
87void __udelay(unsigned long usec)
wdenkbd1575f2003-10-14 19:43:55 +000088{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020089 unsigned long long tmp;
90
91 tmp = get_ticks() + us_to_tick(usec);
92
93 while (get_ticks() < tmp)
94 ;
wdenkbd1575f2003-10-14 19:43:55 +000095}
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +020096
97int timer_init(void)
98{
Michael Schwingen7ddf55e2011-05-23 00:00:00 +020099 writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST);
Jean-Christophe PLAGNIOL-VILLARD8c9fc002009-05-15 23:47:02 +0200100 return 0;
101}