/*
 * Copyright 2003 Yannis Mitsos and George Thanos 
 * {gmitsos@gthanos}@telecom.ntua.gr
 * Released under GPL2, see the file COPYING in the top directory
 *
 */
#include "etherboot.h"
#include "timer.h"
#include "e132_xs_board.h"
#include "init.h"

/* get timer returns the contents of the timer */
static inline unsigned long get_timer(void)
{
	unsigned long result;
	__asm__ __volatile__("
					ORI	SR, 0x20
					mov	%0, TR" 
					: "=l"(result));
	return result;
}

/* ------ Calibrate the TSC ------- 
 * Time how long it takes to excute a loop that runs in known time.
 * And find the convertion needed to get to CLOCK_TICK_RATE
 */

static unsigned long configure_timer(void)
{
	unsigned long TPR_value; /* Timer Prescalar Value */

	TPR_value = 0x000C00000;
	
	asm volatile (" 
				FETCH   4	
				ORI		SR, 0x20
				MOV		TPR, %0
				ORI		SR, 0x20
				MOVI	TR, 0x0"
				: /* no outputs */
				: "l" (TPR_value)
				); 

	printf("The time prescaler register is set to: <%#x>\n",TPR_value);
	return (1);
}

static unsigned long clocks_per_tick;

static void setup_timers(void)
{
	if (!clocks_per_tick) {
		clocks_per_tick = configure_timer();
	}
}

unsigned long currticks(void)
{
	return get_timer()/clocks_per_tick;
}

static unsigned long timer_timeout;
static int __timer_running(void)
{
	return get_timer() < timer_timeout;
}

void udelay(unsigned int usecs)
{
	unsigned long now;
	now = get_timer();
	timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
	while(__timer_running());
}
void ndelay(unsigned int nsecs)
{
	unsigned long now;
	now = get_timer();
	timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
	while(__timer_running());
}

void load_timer2(unsigned int timer2_ticks)
{
	unsigned long now;
	unsigned long clocks;
	now = get_timer();
	clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
	timer_timeout = now + clocks;
}

int timer2_running(void)
{
	return __timer_running();
}

INIT_FN ( INIT_TIMERS, setup_timers, NULL, NULL );
