/*
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ *
+ * (C) Copyright 2008
+ * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
+ *
+ * (C) Copyright 2004
+ * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
+ *
+ * (C) Copyright 2002-2004
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
* (C) Copyright 2003
* Texas Instruments <www.ti.com>
*
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Alex Zuepke <azu@sysgo.de>
*
- * (C) Copyright 2002-2004
- * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
- *
- * (C) Copyright 2004
- * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
- *
- * (C) Copyright 2008
- * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
- *
* See file CREDITS for list of people who contributed to this
* project.
*
*/
#include <common.h>
-#include <asm/proc/ptrace.h>
#include <div64.h>
+#include <asm/io.h>
-#include "xscutimer_hw.h"
+DECLARE_GLOBAL_DATA_PTR;
-#define TIMER_LOAD_VAL 0xFFFFFFFF
+struct scu_timer {
+ u32 load; /* Timer Load Register */
+ u32 counter; /* Timer Counter Register */
+ u32 control; /* Timer Control Register */
+};
-/* Internal tick units */
-/* Last decremneter snapshot */
-static unsigned long lastdec;
-/* Monotonic incrementing timer */
-static unsigned long long timestamp;
+static struct scu_timer *timer_base =
+ (struct scu_timer *) CONFIG_SCUTIMER_BASEADDR;
-static void XScuTimer_WriteReg (u32 Reg, u32 Data)
-{
- *(volatile u32 *) (XPAR_SCUTIMER_BASEADDR + Reg) = Data;
-}
-
-static u32 XScuTimer_ReadReg (u32 Reg)
-{
- return *(u32 *) (XPAR_SCUTIMER_BASEADDR + Reg);
-}
-
-#define XScuTimer_GetCounterValue() \
- XScuTimer_ReadReg(XSCUTIMER_COUNTER_OFFSET)
+#define SCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /* Prescaler */
+#define SCUTIMER_CONTROL_PRESCALER_SHIFT 8
+#define SCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002 /* Auto-reload */
+#define SCUTIMER_CONTROL_ENABLE_MASK 0x00000001 /* Timer enable */
+#define TIMER_LOAD_VAL 0xFFFFFFFF
+#define TIMER_PRESCALE 255
+#define TIMER_TICK_HZ (CONFIG_CPU_FREQ_HZ / 2 / TIMER_PRESCALE)
-int timer_init()
+int timer_init(void)
{
- u32 val;
+ const u32 emask = SCUTIMER_CONTROL_AUTO_RELOAD_MASK |
+ (TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
+ SCUTIMER_CONTROL_ENABLE_MASK;
- /*
- * Load the timer counter register.
- */
- XScuTimer_WriteReg(XSCUTIMER_LOAD_OFFSET, 0xFFFFFFFF);
+ /* Load the timer counter register */
+ writel(0xFFFFFFFF, &timer_base->counter);
/*
- * Start the A9Timer device.
+ * Start the A9Timer device
+ * Enable Auto reload mode, Clear prescaler control bits
+ * Set prescaler value, Enable the decrementer
*/
- val = XScuTimer_ReadReg(XSCUTIMER_CONTROL_OFFSET);
- /* Enable Auto reload mode. */
- val |= XSCUTIMER_CONTROL_AUTO_RELOAD_MASK;
- /* Clear prescaler control bits */
- val &= ~XSCUTIMER_CONTROL_PRESCALER_MASK;
- /* Set prescaler value */
- val |= (CONFIG_TIMER_PRESCALE << XSCUTIMER_CONTROL_PRESCALER_SHIFT);
- /* Enable the decrementer */
- val |= XSCUTIMER_CONTROL_ENABLE_MASK;
- XScuTimer_WriteReg(XSCUTIMER_CONTROL_OFFSET, val);
-
- /* This must not be called before relocation */
- /*reset_timer_masked();*/
+ clrsetbits_le32(&timer_base->control, SCUTIMER_CONTROL_PRESCALER_MASK,
+ emask);
+
+ /* Reset time */
+ gd->lastinc = readl(&timer_base->counter) /
+ (TIMER_TICK_HZ / CONFIG_SYS_HZ);
+ gd->tbl = 0;
return 0;
}
-/*
- * timer without interrupts
- */
-
/*
* This function is derived from PowerPC code (read timebase as long long).
* On ARM it just returns the timer value.
*/
-unsigned long long get_ticks(void)
+ulong get_timer_masked(void)
{
ulong now;
- now = XScuTimer_GetCounterValue() / (TIMER_TICK_HZ/CONFIG_SYS_HZ);
+ now = readl(&timer_base->counter) / (TIMER_TICK_HZ / CONFIG_SYS_HZ);
- if (lastdec >= now) {
- /* normal mode */
- timestamp += lastdec - now;
+ if (gd->lastinc >= now) {
+ /* Normal mode */
+ gd->tbl += gd->lastinc - now;
} else {
- /* we have an overflow ... */
- timestamp += lastdec + TIMER_LOAD_VAL - now;
+ /* We have an overflow ... */
+ gd->tbl += gd->lastinc + TIMER_LOAD_VAL - now;
}
- lastdec = now;
+ gd->lastinc = now;
- return timestamp;
+ return gd->tbl;
}
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
-{
- return (ulong)CONFIG_SYS_HZ;
-}
-
-void reset_timer_masked(void)
+void __udelay(unsigned long usec)
{
- /* reset time */
- lastdec = XScuTimer_GetCounterValue() / (TIMER_TICK_HZ/CONFIG_SYS_HZ);
- timestamp = 0;
-}
+ unsigned long long tmp;
+ ulong tmo;
-void reset_timer(void)
-{
- reset_timer_masked();
-}
+ tmo = usec / (1000000 / CONFIG_SYS_HZ);
+ tmp = get_ticks() + tmo; /* Get current timestamp */
-ulong get_timer_masked(void)
-{
- unsigned long long res = get_ticks();
- return res;
+ while (get_ticks() < tmp) { /* Loop till event */
+ /* NOP */;
+ }
}
+/* Timer without interrupts */
ulong get_timer(ulong base)
{
return get_timer_masked() - base;
}
-void set_timer(ulong t)
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
{
- timestamp = t;
+ return get_timer(0);
}
-void __udelay(unsigned long usec)
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
{
- unsigned long long tmp;
- ulong tmo;
-
- tmo = usec / (1000000 / CONFIG_SYS_HZ);
- tmp = get_ticks() + tmo; /* get current timestamp */
-
- while (get_ticks() < tmp) { /* loop till event */
- /*NOP*/;
- }
+ return CONFIG_SYS_HZ;
}
-
+++ /dev/null
-/*
- * (C) Copyright 2012 Xilinx
- *
- * Xilinx hardware interface to the Timer.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#ifndef XSCUTIMER_HW_H /* prevent circular inclusions */
-#define XSCUTIMER_HW_H /* by using protection macros */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/***************************** Include Files *********************************/
-#ifdef NOTNOW_BHILL
-#include "xil_types.h"
-#include "xil_io.h"
-#endif
-/************************** Constant Definitions *****************************/
-
-/** @name Register Map
- * Offsets of registers from the start of the device
- * @{
- */
-
-#define XSCUTIMER_LOAD_OFFSET 0x00 /**< Timer Load Register */
-#define XSCUTIMER_COUNTER_OFFSET 0x04 /**< Timer Counter Register */
-#define XSCUTIMER_CONTROL_OFFSET 0x08 /**< Timer Control Register */
-#define XSCUTIMER_ISR_OFFSET 0x0C /**< Timer Interrupt
- Status Register */
-/* @} */
-
-/** @name Timer Control register
- * This register bits control the prescaler, Intr enable,
- * auto-reload and timer enable.
- * @{
- */
-
-#define XSCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /**< Prescaler */
-#define XSCUTIMER_CONTROL_PRESCALER_SHIFT 8
-#define XSCUTIMER_CONTROL_IRQ_ENABLE_MASK 0x00000004 /**< Intr enable */
-#define XSCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002 /**< Auto-reload */
-#define XSCUTIMER_CONTROL_ENABLE_MASK 0x00000001 /**< Timer enable */
-/* @} */
-
-/** @name Interrupt Status register
- * This register indicates the Timer counter register has reached zero.
- * @{
- */
-
-#define XSCUTIMER_ISR_EVENT_FLAG_MASK 0x00000001 /**< Event flag */
-/*@}*/
-
-/**************************** Type Definitions *******************************/
-
-/***************** Macros (Inline Functions) Definitions *********************/
-
-/************************** Function Prototypes ******************************/
-
-/************************** Variable Definitions *****************************/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* end of protection macro */