Timer capability added, Baremetal5 added as Timer Sevice, Code not

tested yet.
This commit is contained in:
Amit Mahajan
2009-11-25 13:50:24 +05:30
parent b53cc73747
commit 9f57cb7c67
12 changed files with 495 additions and 1 deletions

View File

@@ -0,0 +1,67 @@
/*
* SP804 Primecell Timer offsets
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __SP804_TIMER_H__
#define __SP804_TIMER_H__
#define SP804_TIMER2_OFFSET 0x20
/* Base address of Timers for differen platforms */
#if defined(PLATFORM_PB926)
#define TIMER0_PHYS_BASE 0x101E2000
#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER2_PHYS_BASE 0x101E3000
#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET)
#elif defined(PLATFORM_EB)
#define TIMER0_PHYS_BASE 0x10011000
#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER2_PHYS_BASE 0x10012000
#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET)
#elif defined(PLATFORM_PB11MPCORE) || defined(PLATFORM_PBA8)
#define TIMER0_PHYS_BASE 0x10011000
#define TIMER1_PHYS_BASE (TIMER0_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER2_PHYS_BASE 0x10012000
#define TIMER3_PHYS_BASE (TIMER2_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER4_PHYS_BASE 0x10018000
#define TIMER5_PHYS_BASE (TIMER4_PHYS_BASE + SP804_TIMER2_OFFSET)
#define TIMER6_PHYS_BASE 0x10019000
#define TIMER7_PHYS_BASE (TIMER6_PHYS_BASE + SP804_TIMER2_OFFSET)
#endif
/* Run mode of timers */
#define SP804_TIMER_RUNMODE_FREERUN 0
#define SP804_TIMER_RUNMODE_PERIODIC 1
/* Wrap mode of timers */
#define SP804_TIMER_WRAPMODE_WRAPPING 0
#define SP804_TIMER_WRAPMODE_ONESHOT 1
/* Operational width of timer */
#define SP804_TIMER_WIDTH16BIT 0
#define SP804_TIMER_WIDTH32BIT 1
/* Enable/disable irq on timer */
#define SP804_TIMER_IRQDISABLE 0
#define SP804_TIMER_IRQENABLE 1
/* Register offsets */
#define SP804_TIMERLOAD 0x0
#define SP804_TIMERVALUE 0x4
#define SP804_TIMERCONTROL 0x8
#define SP804_TIMERINTCLR 0xC
#define SP804_TIMERRIS 0x10
#define SP804_TIMERMIS 0x14
#define SP804_TIMERBGLOAD 0x18
void sp804_init(unsigned int timer_base, int runmode, int wrapmode, \
int width, int irq_enable);
void sp804_irq_handler(unsigned int timer_base);
void sp804_enable(unsigned int timer_base, int enable);
void sp804_set_irq(unsigned int timer_base, int enable);
unsigned int sp804_read_value(unsigned int timer_base);
#endif /* __SP804_TIMER_H__ */

View File

@@ -0,0 +1,104 @@
/*
* SP804 Primecell Timer driver
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <sp804_timer.h>
#define read(a) *((volatile unsigned int *)(a))
#define write(v, a) (*((volatile unsigned int *)(a)) = v)
#define setbit(bit, a) write(read(a) | bit, a)
#define clrbit(bit, a) write(read(a) & ~bit, a)
void sp804_irq_handler(unsigned int timer_base)
{
/*
* Timer enabled as Periodic/Wrapper only needs irq clearing
* as it automatically reloads and wraps
*/
write(1, (timer_base + SP804_TIMERINTCLR));
}
static inline void sp804_control(unsigned int timer_base, int bit, int setclr)
{
unsigned long addr = (timer_base + SP804_TIMERCONTROL);
setclr ? setbit(bit, addr) : clrbit(bit, addr);
}
/*
* Sets timer's run mode:
* @periodic: periodic mode = 1, free-running = 0.
*/
#define SP804_PEREN (1 << 6)
static inline void sp804_set_runmode(unsigned int timer_base, int periodic)
{
sp804_control(timer_base, SP804_PEREN, periodic);
}
/*
* Sets timer's wrapping mode:
* @oneshot: oneshot = 1, wrapping = 0.
*/
#define SP804_ONESHOT (1 << 0)
static inline void sp804_set_wrapmode(unsigned int timer_base, int oneshot)
{
sp804_control(timer_base, SP804_ONESHOT, oneshot);
}
/*
* Sets the operational width of timers.
* In 16bit mode, top halfword is ignored.
* @width: 32bit mode = 1; 16bit mode = 0
*/
#define SP804_32BIT (1 << 1)
static inline void sp804_set_widthmode(unsigned int timer_base, int width)
{
sp804_control(timer_base, SP804_32BIT, width);
}
/*
* Enable/disable timer:
* @enable: enable = 1, disable = 0;
*/
#define SP804_ENABLE (1 << 7)
void sp804_enable(unsigned int timer_base, int enable)
{
sp804_control(timer_base, SP804_ENABLE, enable);
}
/*
* Enable/disable local irq register:
* @enable: enable = 1, disable = 0
*/
#define SP804_IRQEN (1 << 5)
void sp804_set_irq(unsigned int timer_base, int enable)
{
sp804_control(timer_base, SP804_IRQEN, enable);
}
/* Loads timer with value in val */
static inline void sp804_load_value(unsigned int timer_base, unsigned int val)
{
write(val, (timer_base + SP804_TIMERLOAD));
}
/* Returns current timer value */
unsigned int sp804_read_value(unsigned int timer_base)
{
return read(timer_base + SP804_TIMERVALUE);
}
/* TODO: Define macro values for duration */
void sp804_init(unsigned int timer_base, int run_mode, int wrap_mode, \
int width, int irq_enable)
{
/* 1 tick per usec */
const int duration = 250;
sp804_set_runmode(timer_base, run_mode); /* Periodic */
sp804_set_wrapmode(timer_base, wrap_mode); /* Wrapping */
sp804_set_widthmode(timer_base, width); /* 32 bit */
sp804_set_irq(timer_base, irq_enable); /* Enable */
sp804_load_value(timer_base, duration);
}