bsp/leon3: Use new GPTIMER register block API

This commit is contained in:
Sebastian Huber
2021-07-19 09:26:33 +02:00
parent 8c9daf56f8
commit d85c505ab0
9 changed files with 188 additions and 166 deletions

View File

@@ -50,18 +50,15 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <rtems.h>
#include <bsp.h>
#include <stdlib.h>
#include <string.h>
#include <drvmgr/drvmgr.h> #include <drvmgr/drvmgr.h>
#include <grlib/ambapp_bus.h> #include <grlib/ambapp_bus.h>
#include <grlib/grlib.h>
#include <grlib/gptimer.h> #include <grlib/gptimer.h>
#include <grlib/gptimer-regs.h>
#include <grlib/io.h>
#include <grlib/tlib.h> #include <grlib/tlib.h>
#if defined(LEON3) #if defined(LEON3)
#include <leon.h> #include <bsp/leon3.h>
#endif #endif
#ifdef GPTIMER_INFO_AVAIL #ifdef GPTIMER_INFO_AVAIL
@@ -75,49 +72,21 @@
#include <grlib/grlib_impl.h> #include <grlib/grlib_impl.h>
/* GPTIMER Core Configuration Register (READ-ONLY) */
#define GPTIMER_CFG_TIMERS_BIT 0
#define GPTIMER_CFG_IRQ_BIT 3
#define GPTIMER_CFG_SI_BIT 8
#define GPTIMER_CFG_DF_BIT 9
#define GPTIMER_CFG_TIMERS (0x7<<GPTIMER_CFG_TIMERS_BIT)
#define GPTIMER_CFG_IRQ (0x1f<<GPTIMER_CFG_IRQ_BIT)
#define GPTIMER_CFG_SI (1<<GPTIMER_CFG_SI_BIT)
#define GPTIMER_CFG_DF (1<<GPTIMER_CFG_DF_BIT)
/* GPTIMER Timer Control Register */
#define GPTIMER_CTRL_EN_BIT 0
#define GPTIMER_CTRL_RS_BIT 1
#define GPTIMER_CTRL_LD_BIT 2
#define GPTIMER_CTRL_IE_BIT 3
#define GPTIMER_CTRL_IP_BIT 4
#define GPTIMER_CTRL_CH_BIT 5
#define GPTIMER_CTRL_DH_BIT 6
#define GPTIMER_CTRL_EN (1<<GPTIMER_CTRL_EN_BIT)
#define GPTIMER_CTRL_RS (1<<GPTIMER_CTRL_RS_BIT)
#define GPTIMER_CTRL_LD (1<<GPTIMER_CTRL_LD_BIT)
#define GPTIMER_CTRL_IE (1<<GPTIMER_CTRL_IE_BIT)
#define GPTIMER_CTRL_IP (1<<GPTIMER_CTRL_IP_BIT)
#define GPTIMER_CTRL_CH (1<<GPTIMER_CTRL_CH_BIT)
#define GPTIMER_CTRL_DH (1<<GPTIMER_CTRL_DH_BIT)
#define DBG(x...) #define DBG(x...)
/* GPTIMER timer private */ /* GPTIMER timer private */
struct gptimer_timer { struct gptimer_timer_priv {
struct tlib_dev tdev; /* Must be first in struct */ struct tlib_dev tdev; /* Must be first in struct */
struct gptimer_timer_regs *tregs; gptimer_timer *tregs;
char index; /* Timer Index in this driver */ char index; /* Timer Index in this driver */
char tindex; /* Timer Index In Hardware */ char tindex; /* Timer Index In Hardware */
unsigned char irq_ack_mask; uint32_t irq_ack_mask;
}; };
/* GPTIMER Core private */ /* GPTIMER Core private */
struct gptimer_priv { struct gptimer_priv {
struct drvmgr_dev *dev; struct drvmgr_dev *dev;
struct gptimer_regs *regs; gptimer *regs;
unsigned int base_clk; unsigned int base_clk;
unsigned int base_freq; unsigned int base_freq;
unsigned int widthmask; unsigned int widthmask;
@@ -126,7 +95,7 @@ struct gptimer_priv {
/* Structure per Timer unit, the core supports up to 8 timers */ /* Structure per Timer unit, the core supports up to 8 timers */
int timer_cnt; int timer_cnt;
struct gptimer_timer timers[0]; struct gptimer_timer_priv timers[0];
}; };
void gptimer_isr(void *data); void gptimer_isr(void *data);
@@ -200,14 +169,14 @@ void gptimer_register_drv (void)
int gptimer_init1(struct drvmgr_dev *dev) int gptimer_init1(struct drvmgr_dev *dev)
{ {
struct gptimer_priv *priv; struct gptimer_priv *priv;
struct gptimer_regs *regs; gptimer *regs;
struct amba_dev_info *ambadev; struct amba_dev_info *ambadev;
struct ambapp_core *pnpinfo; struct ambapp_core *pnpinfo;
int timer_hw_cnt, timer_cnt, timer_start; int timer_hw_cnt, timer_cnt, timer_start;
int i, size; int i, size;
struct gptimer_timer *timer; struct gptimer_timer_priv *timer;
union drvmgr_key_value *value; union drvmgr_key_value *value;
unsigned char irq_ack_mask; uint32_t irq_ack_mask;
/* Get device information from AMBA PnP information */ /* Get device information from AMBA PnP information */
ambadev = (struct amba_dev_info *)dev->businfo; ambadev = (struct amba_dev_info *)dev->businfo;
@@ -215,12 +184,12 @@ int gptimer_init1(struct drvmgr_dev *dev)
return -1; return -1;
} }
pnpinfo = &ambadev->info; pnpinfo = &ambadev->info;
regs = (struct gptimer_regs *)pnpinfo->apb_slv->start; regs = (gptimer *)pnpinfo->apb_slv->start;
DBG("GPTIMER[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); DBG("GPTIMER[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
/* Get number of Timers */ /* Get number of Timers */
timer_hw_cnt = regs->cfg & GPTIMER_CFG_TIMERS; timer_hw_cnt = GPTIMER_CONFIG_TIMERS_GET(grlib_load_32(&regs->config));
/* Let user spelect a range of timers to be used. In AMP systems /* Let user spelect a range of timers to be used. In AMP systems
* it is sometimes neccessary to leave timers for other CPU instances. * it is sometimes neccessary to leave timers for other CPU instances.
@@ -251,7 +220,7 @@ int gptimer_init1(struct drvmgr_dev *dev)
* are present. * are present.
*/ */
size = sizeof(struct gptimer_priv) + size = sizeof(struct gptimer_priv) +
timer_cnt*sizeof(struct gptimer_timer); timer_cnt*sizeof(struct gptimer_timer_priv);
priv = dev->priv = grlib_calloc(1, size); priv = dev->priv = grlib_calloc(1, size);
if ( !priv ) if ( !priv )
return DRVMGR_NOMEM; return DRVMGR_NOMEM;
@@ -277,24 +246,24 @@ int gptimer_init1(struct drvmgr_dev *dev)
*/ */
value = drvmgr_dev_key_get(priv->dev, "prescaler", DRVMGR_KT_INT); value = drvmgr_dev_key_get(priv->dev, "prescaler", DRVMGR_KT_INT);
if ( value ) if ( value )
regs->scaler_reload = value->i; grlib_store_32(&regs->sreload, value->i);
/* Get Frequency that the timers are operating in (after prescaler) */ /* Get Frequency that the timers are operating in (after prescaler) */
priv->base_freq = priv->base_clk / (priv->regs->scaler_reload + 1); priv->base_freq = priv->base_clk / (grlib_load_32(&regs->sreload) + 1);
/* Stop Timer and probe Pending bit. In newer hardware the /* Stop Timer and probe Pending bit. In newer hardware the
* timer has pending bit is cleared by writing a one to it, * timer has pending bit is cleared by writing a one to it,
* whereas older versions it is cleared with a zero. * whereas older versions it is cleared with a zero.
*/ */
priv->regs->timer[timer_start].ctrl = GPTIMER_CTRL_IP; grlib_store_32(&regs->timer[timer_start].tctrl, GPTIMER_TCTRL_IP);
if ((priv->regs->timer[timer_start].ctrl & GPTIMER_CTRL_IP) != 0) if ((grlib_load_32(&regs->timer[timer_start].tctrl) & GPTIMER_TCTRL_IP) != 0)
irq_ack_mask = ~GPTIMER_CTRL_IP; irq_ack_mask = ~GPTIMER_TCTRL_IP;
else else
irq_ack_mask = ~0; irq_ack_mask = ~0U;
/* Probe timer register width mask */ /* Probe timer register width mask */
priv->regs->timer[timer_start].value = 0xffffffff; grlib_store_32(&regs->timer[timer_start].tcntval, 0xffffffff);
priv->widthmask = priv->regs->timer[timer_start].value; priv->widthmask = grlib_load_32(&regs->timer[timer_start].tcntval);
priv->timer_cnt = timer_cnt; priv->timer_cnt = timer_cnt;
for (i=0; i<timer_cnt; i++) { for (i=0; i<timer_cnt; i++) {
@@ -314,7 +283,7 @@ int gptimer_init1(struct drvmgr_dev *dev)
* B. Each Timer have an individual IRQ. The number is: * B. Each Timer have an individual IRQ. The number is:
* BASE_IRQ + timer_index * BASE_IRQ + timer_index
*/ */
priv->separate_interrupt = (regs->cfg & GPTIMER_CFG_SI) != 0; priv->separate_interrupt = (grlib_load_32(&regs->config) & GPTIMER_CONFIG_SI) != 0;
return DRVMGR_OK; return DRVMGR_OK;
} }
@@ -326,7 +295,7 @@ static int gptimer_info(
void *p, int argc, char *argv[]) void *p, int argc, char *argv[])
{ {
struct gptimer_priv *priv = dev->priv; struct gptimer_priv *priv = dev->priv;
struct gptimer_timer *timer; struct gptimer_timer_priv *timer;
char buf[64]; char buf[64];
int i; int i;
@@ -337,7 +306,7 @@ static int gptimer_info(
print_line(p, buf); print_line(p, buf);
sprintf(buf, "REGS: 0x%08x", (unsigned int)priv->regs); sprintf(buf, "REGS: 0x%08x", (unsigned int)priv->regs);
print_line(p, buf); print_line(p, buf);
sprintf(buf, "BASE SCALER: %d", priv->regs->scaler_reload); sprintf(buf, "BASE SCALER: %d", grlib_load_32(&priv->regs->sreload));
print_line(p, buf); print_line(p, buf);
sprintf(buf, "BASE FREQ: %dkHz", priv->base_freq / 1000); sprintf(buf, "BASE FREQ: %dkHz", priv->base_freq / 1000);
print_line(p, buf); print_line(p, buf);
@@ -350,9 +319,9 @@ static int gptimer_info(
print_line(p, buf); print_line(p, buf);
sprintf(buf, " TLIB Index: %d", timer->index); sprintf(buf, " TLIB Index: %d", timer->index);
print_line(p, buf); print_line(p, buf);
sprintf(buf, " RELOAD REG: %d", timer->tregs->reload); sprintf(buf, " RELOAD REG: %d", grlib_load_32(&timer->tregs->trldval));
print_line(p, buf); print_line(p, buf);
sprintf(buf, " CTRL REG: %d", timer->tregs->ctrl); sprintf(buf, " CTRL REG: %d", grlib_load_32(&timer->tregs->tctrl));
print_line(p, buf); print_line(p, buf);
} }
@@ -360,24 +329,28 @@ static int gptimer_info(
} }
#endif #endif
static inline struct gptimer_priv *priv_from_timer(struct gptimer_timer *t) static inline struct gptimer_priv *priv_from_timer(struct gptimer_timer_priv *t)
{ {
return (struct gptimer_priv *) return (struct gptimer_priv *)
((unsigned int)t - ((unsigned int)t -
sizeof(struct gptimer_priv) - sizeof(struct gptimer_priv) -
t->index * sizeof(struct gptimer_timer)); t->index * sizeof(struct gptimer_timer_priv));
} }
static int gptimer_tlib_int_pend(struct tlib_dev *hand, int ack) static int gptimer_tlib_int_pend(struct tlib_dev *hand, int ack)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
unsigned int ctrl = timer->tregs->ctrl; uint32_t tctrl;
if ((ctrl & (GPTIMER_CTRL_IP | GPTIMER_CTRL_IE)) == tctrl = grlib_load_32(&timer->tregs->tctrl);
(GPTIMER_CTRL_IP | GPTIMER_CTRL_IE)) {
if ((tctrl & (GPTIMER_TCTRL_IP | GPTIMER_TCTRL_IE)) ==
(GPTIMER_TCTRL_IP | GPTIMER_TCTRL_IE)) {
/* clear Pending IRQ ? */ /* clear Pending IRQ ? */
if (ack) if (ack) {
timer->tregs->ctrl = ctrl & timer->irq_ack_mask; tctrl &= timer->irq_ack_mask;
grlib_store_32(&timer->tregs->tctrl, tctrl);
}
return 1; /* timer generated IRQ */ return 1; /* timer generated IRQ */
} else } else
return 0; /* was not timer causing IRQ */ return 0; /* was not timer causing IRQ */
@@ -406,12 +379,15 @@ void gptimer_isr(void *data)
static void gptimer_tlib_reset(struct tlib_dev *hand) static void gptimer_tlib_reset(struct tlib_dev *hand)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
uint32_t tctrl;
timer->tregs->ctrl = (timer->tregs->ctrl & timer->irq_ack_mask) & tctrl = grlib_load_32(&timer->tregs->tctrl);
GPTIMER_CTRL_IP; tctrl &= timer->irq_ack_mask;
timer->tregs->reload = 0xffffffff; tctrl &= GPTIMER_TCTRL_IP;
timer->tregs->ctrl = GPTIMER_CTRL_LD; grlib_store_32(&timer->tregs->tctrl, tctrl);
grlib_store_32(&timer->tregs->trldval, 0xffffffff);
grlib_store_32(&timer->tregs->tctrl, GPTIMER_TCTRL_LD);
} }
static void gptimer_tlib_get_freq( static void gptimer_tlib_get_freq(
@@ -419,24 +395,24 @@ static void gptimer_tlib_get_freq(
unsigned int *basefreq, unsigned int *basefreq,
unsigned int *tickrate) unsigned int *tickrate)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
struct gptimer_priv *priv = priv_from_timer(timer); struct gptimer_priv *priv = priv_from_timer(timer);
/* Calculate base frequency from Timer Clock and Prescaler */ /* Calculate base frequency from Timer Clock and Prescaler */
if ( basefreq ) if ( basefreq )
*basefreq = priv->base_freq; *basefreq = priv->base_freq;
if ( tickrate ) if ( tickrate )
*tickrate = timer->tregs->reload + 1; *tickrate = grlib_load_32(&timer->tregs->trldval) + 1;
} }
static int gptimer_tlib_set_freq(struct tlib_dev *hand, unsigned int tickrate) static int gptimer_tlib_set_freq(struct tlib_dev *hand, unsigned int tickrate)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
timer->tregs->reload = tickrate - 1; grlib_store_32(&timer->tregs->trldval, tickrate - 1);
/*Check that value was allowed (Timer may not be as wide as expected)*/ /*Check that value was allowed (Timer may not be as wide as expected)*/
if ( timer->tregs->reload != (tickrate - 1) ) if (grlib_load_32(&timer->tregs->trldval) != (tickrate - 1))
return -1; return -1;
else else
return 0; return 0;
@@ -444,8 +420,9 @@ static int gptimer_tlib_set_freq(struct tlib_dev *hand, unsigned int tickrate)
static void gptimer_tlib_irq_reg(struct tlib_dev *hand, tlib_isr_t func, void *data, int flags) static void gptimer_tlib_irq_reg(struct tlib_dev *hand, tlib_isr_t func, void *data, int flags)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
struct gptimer_priv *priv = priv_from_timer(timer); struct gptimer_priv *priv = priv_from_timer(timer);
uint32_t tctrl;
if ( priv->separate_interrupt ) { if ( priv->separate_interrupt ) {
drvmgr_interrupt_register(priv->dev, timer->tindex, drvmgr_interrupt_register(priv->dev, timer->tindex,
@@ -476,16 +453,21 @@ static void gptimer_tlib_irq_reg(struct tlib_dev *hand, tlib_isr_t func, void *d
} }
#endif #endif
timer->tregs->ctrl |= GPTIMER_CTRL_IE; tctrl = grlib_load_32(&timer->tregs->tctrl);
tctrl |= GPTIMER_TCTRL_IE;
grlib_store_32(&timer->tregs->tctrl, tctrl);
} }
static void gptimer_tlib_irq_unreg(struct tlib_dev *hand, tlib_isr_t func, void *data) static void gptimer_tlib_irq_unreg(struct tlib_dev *hand, tlib_isr_t func, void *data)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
struct gptimer_priv *priv = priv_from_timer(timer); struct gptimer_priv *priv = priv_from_timer(timer);
uint32_t tctrl;
/* Turn off IRQ at source, unregister IRQ handler */ /* Turn off IRQ at source, unregister IRQ handler */
timer->tregs->ctrl &= ~GPTIMER_CTRL_IE; tctrl = grlib_load_32(&timer->tregs->tctrl);
tctrl &= ~GPTIMER_TCTRL_IE;
grlib_store_32(&timer->tregs->tctrl, tctrl);
if ( priv->separate_interrupt ) { if ( priv->separate_interrupt ) {
drvmgr_interrupt_unregister(priv->dev, timer->tindex, drvmgr_interrupt_unregister(priv->dev, timer->tindex,
@@ -502,46 +484,54 @@ static void gptimer_tlib_irq_unreg(struct tlib_dev *hand, tlib_isr_t func, void
static void gptimer_tlib_start(struct tlib_dev *hand, int once) static void gptimer_tlib_start(struct tlib_dev *hand, int once)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
unsigned int ctrl; uint32_t tctrl;
/* Load the selected frequency before starting Frequency */ /* Load the selected frequency before starting Frequency */
ctrl = GPTIMER_CTRL_LD | GPTIMER_CTRL_EN; tctrl = grlib_load_32(&timer->tregs->tctrl);
tctrl &= timer->irq_ack_mask;
tctrl &= ~GPTIMER_TCTRL_RS;
tctrl |= GPTIMER_TCTRL_LD | GPTIMER_TCTRL_EN;
if ( once == 0 ) if ( once == 0 )
ctrl |= GPTIMER_CTRL_RS; /* Restart Timer */ tctrl |= GPTIMER_TCTRL_RS; /* Restart Timer */
timer->tregs->ctrl = ctrl | (timer->tregs->ctrl & timer->irq_ack_mask & grlib_store_32(&timer->tregs->tctrl, tctrl);
~GPTIMER_CTRL_RS);
} }
static void gptimer_tlib_stop(struct tlib_dev *hand) static void gptimer_tlib_stop(struct tlib_dev *hand)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
uint32_t tctrl;
/* Load the selected Frequency */ /* Load the selected Frequency */
timer->tregs->ctrl &= ~(GPTIMER_CTRL_EN|GPTIMER_CTRL_IP); tctrl = grlib_load_32(&timer->tregs->tctrl);
tctrl &= ~(GPTIMER_TCTRL_EN|GPTIMER_TCTRL_IP);
grlib_store_32(&timer->tregs->tctrl, tctrl);
} }
static void gptimer_tlib_restart(struct tlib_dev *hand) static void gptimer_tlib_restart(struct tlib_dev *hand)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
uint32_t tctrl;
timer->tregs->ctrl |= GPTIMER_CTRL_LD | GPTIMER_CTRL_EN; tctrl = grlib_load_32(&timer->tregs->tctrl);
tctrl |= GPTIMER_TCTRL_LD | GPTIMER_TCTRL_EN;
grlib_store_32(&timer->tregs->tctrl, tctrl);
} }
static void gptimer_tlib_get_counter( static void gptimer_tlib_get_counter(
struct tlib_dev *hand, struct tlib_dev *hand,
unsigned int *counter) unsigned int *counter)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
*counter = timer->tregs->value; *counter = grlib_load_32(&timer->tregs->tcntval);
} }
static void gptimer_tlib_get_widthmask( static void gptimer_tlib_get_widthmask(
struct tlib_dev *hand, struct tlib_dev *hand,
unsigned int *widthmask) unsigned int *widthmask)
{ {
struct gptimer_timer *timer = (struct gptimer_timer *)hand; struct gptimer_timer_priv *timer = (struct gptimer_timer_priv *)hand;
struct gptimer_priv *priv = priv_from_timer(timer); struct gptimer_priv *priv = priv_from_timer(timer);
*widthmask = priv->widthmask; *widthmask = priv->widthmask;

View File

@@ -33,23 +33,21 @@ bool benchmark_timer_find_average_overhead;
bool benchmark_timer_is_initialized = false; bool benchmark_timer_is_initialized = false;
extern volatile struct gptimer_regs *LEON3_Timer_Regs;
void benchmark_timer_initialize(void) void benchmark_timer_initialize(void)
{ {
/* /*
* Timer runs long and accurate enough not to require an interrupt. * Timer runs long and accurate enough not to require an interrupt.
*/ */
if (LEON3_Timer_Regs) { if (LEON3_Timer_Regs) {
gptimer_timer *timer = &LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX];
if ( benchmark_timer_is_initialized == false ) { if ( benchmark_timer_is_initialized == false ) {
/* approximately 1 us per countdown */ /* approximately 1 us per countdown */
LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].reload = 0xffffff; grlib_store_32( &timer->trldval, 0xffffff );
LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].value = 0xffffff; grlib_store_32( &timer->tcntval, 0xffffff );
} else { } else {
benchmark_timer_is_initialized = true; benchmark_timer_is_initialized = true;
} }
LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].ctrl = grlib_store_32( &timer->tctrl, GPTIMER_TCTRL_EN | GPTIMER_TCTRL_LD );
GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_LD;
} }
} }
@@ -62,7 +60,8 @@ benchmark_timer_t benchmark_timer_read(void)
uint32_t total; uint32_t total;
if (LEON3_Timer_Regs) { if (LEON3_Timer_Regs) {
total = LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].value; total =
grlib_load_32( &LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].tcntval );
total = 0xffffff - total; total = 0xffffff - total;

View File

@@ -30,14 +30,12 @@
*/ */
#include <bsp.h> #include <bsp.h>
#include <bsp/leon3.h>
#include <bsp/watchdog.h> #include <bsp/watchdog.h>
#include <grlib/grlib.h>
extern volatile struct gptimer_regs *LEON3_Timer_Regs;
struct gptimer_watchdog_priv { struct gptimer_watchdog_priv {
struct gptimer_regs *regs; gptimer *regs;
struct gptimer_timer_regs *timer; gptimer_timer *timer;
int timerno; int timerno;
}; };
@@ -60,10 +58,10 @@ int bsp_watchdog_init(void)
* functionality is available or not, we assume that it is if we * functionality is available or not, we assume that it is if we
* reached this function. * reached this function.
*/ */
bsp_watchdogs[0].regs = (struct gptimer_regs *)LEON3_Timer_Regs; bsp_watchdogs[0].regs = LEON3_Timer_Regs;
/* Find Timer that has watchdog functionality */ /* Find Timer that has watchdog functionality */
timercnt = bsp_watchdogs[0].regs->cfg & 0x7; timercnt = grlib_load_32(&bsp_watchdogs[0].regs->config) & 0x7;
if (timercnt < 2) /* First timer system clock timer */ if (timercnt < 2) /* First timer system clock timer */
return 0; return 0;
@@ -76,6 +74,9 @@ int bsp_watchdog_init(void)
void bsp_watchdog_reload(int watchdog, unsigned int reload_value) void bsp_watchdog_reload(int watchdog, unsigned int reload_value)
{ {
gptimer_timer *timer;
uint32_t tctrl;
if (bsp_watchdog_count == 0) if (bsp_watchdog_count == 0)
bsp_watchdog_init(); bsp_watchdog_init();
@@ -83,10 +84,12 @@ void bsp_watchdog_reload(int watchdog, unsigned int reload_value)
return; return;
/* Kick watchdog, and clear interrupt pending bit */ /* Kick watchdog, and clear interrupt pending bit */
bsp_watchdogs[watchdog].timer->reload = reload_value; timer = bsp_watchdogs[watchdog].timer;
bsp_watchdogs[watchdog].timer->ctrl = grlib_store_32(&timer->trldval, reload_value);
(GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_EN) | tctrl = grlib_load_32(&timer->tctrl);
(bsp_watchdogs[watchdog].timer->ctrl & ~(1<<4)); tctrl |= GPTIMER_TCTRL_LD | GPTIMER_TCTRL_EN;
tctrl &= ~GPTIMER_TCTRL_IP;
grlib_store_32(&timer->tctrl, tctrl);
} }
void bsp_watchdog_stop(int watchdog) void bsp_watchdog_stop(int watchdog)
@@ -98,7 +101,7 @@ void bsp_watchdog_stop(int watchdog)
return; return;
/* Stop watchdog timer */ /* Stop watchdog timer */
bsp_watchdogs[watchdog].timer->ctrl = 0; grlib_store_32(&bsp_watchdogs[watchdog].timer->tctrl, 0);
} }
/* Use watchdog timer to reset system */ /* Use watchdog timer to reset system */

View File

@@ -42,7 +42,7 @@
#include <bsp.h> #include <bsp.h>
#include <bsp/fatal.h> #include <bsp/fatal.h>
#include <bsp/irq.h> #include <bsp/irq.h>
#include <leon.h> #include <bsp/leon3.h>
#include <rtems/rtems/intr.h> #include <rtems/rtems/intr.h>
#include <grlib/ambapp.h> #include <grlib/ambapp.h>
#include <grlib/irqamp.h> #include <grlib/irqamp.h>
@@ -148,7 +148,7 @@ static void leon3_tc_do_tick(void)
do { \ do { \
/* Assume timer found during BSP initialization */ \ /* Assume timer found during BSP initialization */ \
if (LEON3_Timer_Regs) { \ if (LEON3_Timer_Regs) { \
clkirq = (LEON3_Timer_Regs->cfg & 0xf8) >> 3; \ clkirq = (grlib_load_32(&LEON3_Timer_Regs->config) & 0xf8) >> 3; \
\ \
Adjust_clkirq_for_node(); \ Adjust_clkirq_for_node(); \
} \ } \
@@ -185,19 +185,22 @@ static void bsp_clock_handler_install(rtems_interrupt_handler isr)
static void leon3_clock_initialize(void) static void leon3_clock_initialize(void)
{ {
irqamp_timestamp *irqmp_ts; irqamp_timestamp *irqmp_ts;
volatile struct gptimer_regs *gpt; gptimer_timer *timer;
struct timecounter *tc; struct timecounter *tc;
timer = &LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX];
grlib_store_32(
&timer->trldval,
rtems_configuration_get_microseconds_per_tick() - 1
);
grlib_store_32(
&timer->tctrl,
GPTIMER_TCTRL_EN | GPTIMER_TCTRL_RS | GPTIMER_TCTRL_LD | GPTIMER_TCTRL_IE
);
irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs); irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
gpt = LEON3_Timer_Regs;
tc = &leon3_tc; tc = &leon3_tc;
gpt->timer[LEON3_CLOCK_INDEX].reload =
rtems_configuration_get_microseconds_per_tick() - 1;
gpt->timer[LEON3_CLOCK_INDEX].ctrl =
GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_RS |
GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_IE;
leon3_up_counter_enable(); leon3_up_counter_enable();
if (leon3_up_counter_is_available()) { if (leon3_up_counter_is_available()) {
@@ -231,8 +234,10 @@ static void leon3_clock_initialize(void)
* controller. At least on SMP configurations we must use a second timer * controller. At least on SMP configurations we must use a second timer
* in free running mode for the timecounter. * in free running mode for the timecounter.
*/ */
gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].ctrl = grlib_store_32(
GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_IE; &LEON3_Timer_Regs->timer[LEON3_COUNTER_GPTIMER_INDEX].tctrl,
GPTIMER_TCTRL_EN | GPTIMER_TCTRL_IE
);
tc->tc_get_timecount = _SPARC_Get_timecount_down; tc->tc_get_timecount = _SPARC_Get_timecount_down;
#else #else
@@ -241,7 +246,7 @@ static void leon3_clock_initialize(void)
counter = &_SPARC_Counter_mutable; counter = &_SPARC_Counter_mutable;
counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled; counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
counter->read = _SPARC_Counter_read_clock; counter->read = _SPARC_Counter_read_clock;
counter->counter_register = &gpt->timer[LEON3_CLOCK_INDEX].value; counter->counter_register = &timer->tcntval;
counter->pending_register = grlib_load_32(&LEON3_IrqCtrl_Regs->ipend); counter->pending_register = grlib_load_32(&LEON3_IrqCtrl_Regs->ipend);
counter->pending_mask = UINT32_C(1) << clkirq; counter->pending_mask = UINT32_C(1) << clkirq;
counter->accumulated = rtems_configuration_get_microseconds_per_tick(); counter->accumulated = rtems_configuration_get_microseconds_per_tick();

View File

@@ -9,7 +9,7 @@
*/ */
/* /*
* Copyright (C) 2021 embedded brains GmbH & Co. KG * Copyright (C) 2014, 2021 embedded brains GmbH & Co. KG
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -37,6 +37,7 @@
#define LIBBSP_SPARC_LEON3_BSP_LEON3_H #define LIBBSP_SPARC_LEON3_BSP_LEON3_H
#include <grlib/apbuart-regs.h> #include <grlib/apbuart-regs.h>
#include <grlib/gptimer-regs.h>
#include <bsp/irqimpl.h> #include <bsp/irqimpl.h>
@@ -151,6 +152,47 @@ static inline uint32_t leon3_get_data_cache_config_register( void )
return leon3_get_system_register( 0xc ); return leon3_get_system_register( 0xc );
} }
/**
* @brief This constant defines the index of the GPTIMER timer used by the
* clock driver.
*/
#if defined(RTEMS_MULTIPROCESSING)
#define LEON3_CLOCK_INDEX \
( rtems_configuration_get_user_multiprocessing_table() ? LEON3_Cpu_Index : 0 )
#else
#define LEON3_CLOCK_INDEX 0
#endif
/**
* @brief This constant defines the index of the GPTIMER timer used by the
* CPU counter if the CPU counter uses the GPTIMER.
*/
#if defined(RTEMS_SMP)
#define LEON3_COUNTER_GPTIMER_INDEX ( LEON3_CLOCK_INDEX + 1 )
#else
#define LEON3_COUNTER_GPTIMER_INDEX LEON3_CLOCK_INDEX
#endif
/**
* @brief This constant defines the frequency set by the boot loader of the
* first GPTIMER instance.
*
* We assume that a boot loader (usually GRMON) initialized the GPTIMER 0 to
* run with 1MHz. This is used to determine all clock frequencies of the PnP
* devices. See also ambapp_freq_init() and ambapp_freq_get().
*/
#define LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER 1000000
/**
* @brief This pointer provides the GPTIMER register block address.
*/
extern gptimer *LEON3_Timer_Regs;
/**
* @brief This pointer provides the GPTIMER device information block.
*/
extern struct ambapp_dev *LEON3_Timer_Adev;
/** /**
* @brief Gets the LEON up-counter low register (%ASR23) value. * @brief Gets the LEON up-counter low register (%ASR23) value.
* *

View File

@@ -142,10 +142,6 @@ extern "C" {
#define LEON_REG_UART_CTRL_FA 0x80000000 /* FIFO Available */ #define LEON_REG_UART_CTRL_FA 0x80000000 /* FIFO Available */
#define LEON_REG_UART_CTRL_FA_BIT 31 #define LEON_REG_UART_CTRL_FA_BIT 31
/* LEON3 GP Timer */
extern volatile struct gptimer_regs *LEON3_Timer_Regs;
extern struct ambapp_dev *LEON3_Timer_Adev;
/* Macros used for manipulating bits in LEON3 GP Timer Control Register */ /* Macros used for manipulating bits in LEON3 GP Timer Control Register */
#define LEON3_IRQMPSTATUS_CPUNR 28 #define LEON3_IRQMPSTATUS_CPUNR 28
@@ -316,26 +312,6 @@ extern struct ambapp_dev *LEON3_Timer_Adev;
#define LEON_REG_TIMER_COUNTER_DEFINED_MASK 0x00000003 #define LEON_REG_TIMER_COUNTER_DEFINED_MASK 0x00000003
#define LEON_REG_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000003 #define LEON_REG_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000003
#if defined(RTEMS_MULTIPROCESSING)
#define LEON3_CLOCK_INDEX \
(rtems_configuration_get_user_multiprocessing_table() ? LEON3_Cpu_Index : 0)
#else
#define LEON3_CLOCK_INDEX 0
#endif
#if defined(RTEMS_SMP)
#define LEON3_COUNTER_GPTIMER_INDEX (LEON3_CLOCK_INDEX + 1)
#else
#define LEON3_COUNTER_GPTIMER_INDEX LEON3_CLOCK_INDEX
#endif
/*
* We assume that a boot loader (usually GRMON) initialized the GPTIMER 0 to
* run with 1MHz. This is used to determine all clock frequencies of the PnP
* devices. See also ambapp_freq_init() and ambapp_freq_get().
*/
#define LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER 1000000
/* Load 32-bit word by forcing a cache-miss */ /* Load 32-bit word by forcing a cache-miss */
static inline unsigned int leon_r32_no_cache(uintptr_t addr) static inline unsigned int leon_r32_no_cache(uintptr_t addr)
{ {

View File

@@ -118,7 +118,8 @@ RTEMS_SYSINIT_ITEM(
/* Pointers to Interrupt Controller configuration registers */ /* Pointers to Interrupt Controller configuration registers */
irqamp *LEON3_IrqCtrl_Regs; irqamp *LEON3_IrqCtrl_Regs;
struct ambapp_dev *LEON3_IrqCtrl_Adev; struct ambapp_dev *LEON3_IrqCtrl_Adev;
volatile struct gptimer_regs *LEON3_Timer_Regs;
gptimer *LEON3_Timer_Regs;
struct ambapp_dev *LEON3_Timer_Adev; struct ambapp_dev *LEON3_Timer_Adev;
/* /*
@@ -170,14 +171,14 @@ static void amba_initialize(void)
VENDOR_GAISLER, GAISLER_GPTIMER, VENDOR_GAISLER, GAISLER_GPTIMER,
ambapp_find_by_idx, &leon3_timer_core_index); ambapp_find_by_idx, &leon3_timer_core_index);
if (adev) { if (adev) {
LEON3_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start; LEON3_Timer_Regs = (gptimer *)DEV_TO_APB(adev)->start;
LEON3_Timer_Adev = adev; LEON3_Timer_Adev = adev;
/* Register AMBA Bus Frequency */ /* Register AMBA Bus Frequency */
ambapp_freq_init( ambapp_freq_init(
plb, plb,
LEON3_Timer_Adev, LEON3_Timer_Adev,
(LEON3_Timer_Regs->scaler_reload + 1) (grlib_load_32(&LEON3_Timer_Regs->sreload) + 1)
* LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER * LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
); );
/* Set user prescaler configuration. Use this to increase accuracy of timer /* Set user prescaler configuration. Use this to increase accuracy of timer
@@ -186,7 +187,7 @@ static void amba_initialize(void)
* GRTIMER/GPTIMER hardware. See HW manual. * GRTIMER/GPTIMER hardware. See HW manual.
*/ */
if (leon3_timer_prescaler) if (leon3_timer_prescaler)
LEON3_Timer_Regs->scaler_reload = leon3_timer_prescaler; grlib_store_32(&LEON3_Timer_Regs->sreload, leon3_timer_prescaler);
} }
} }

View File

@@ -14,15 +14,17 @@
*/ */
#include <bsp.h> #include <bsp.h>
#include <leon.h> #include <bsp/leon3.h>
void rtems_bsp_delay(int usecs) void rtems_bsp_delay(int usecs)
{ {
uint32_t then; uint32_t then;
gptimer_timer *regs;
then =LEON3_Timer_Regs->timer[0].value; regs = &LEON3_Timer_Regs->timer[0];
then =grlib_load_32(&regs->tcntval);
then += usecs; then += usecs;
while (LEON3_Timer_Regs->timer[0].value >= then) while (grlib_load_32(&regs->tcntval) >= then)
; ;
} }

View File

@@ -25,7 +25,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <leon.h> #include <bsp/leon3.h>
#include <grlib/irqamp.h> #include <grlib/irqamp.h>
#include <rtems/counter.h> #include <rtems/counter.h>
@@ -42,7 +42,7 @@ uint32_t _CPU_Counter_frequency(void)
static void leon3_counter_initialize(void) static void leon3_counter_initialize(void)
{ {
irqamp_timestamp *irqmp_ts; irqamp_timestamp *irqmp_ts;
volatile struct gptimer_regs *gpt; gptimer *gpt;
SPARC_Counter *counter; SPARC_Counter *counter;
irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs); irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
@@ -68,19 +68,23 @@ static void leon3_counter_initialize(void)
leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_IrqCtrl_Adev); leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_IrqCtrl_Adev);
} else if (gpt != NULL) { } else if (gpt != NULL) {
gptimer_timer *timer;
uint32_t tctrl;
/* Fall back to the first GPTIMER if available */ /* Fall back to the first GPTIMER if available */
timer = &gpt->timer[LEON3_COUNTER_GPTIMER_INDEX];
counter->read_isr_disabled = _SPARC_Counter_read_down; counter->read_isr_disabled = _SPARC_Counter_read_down;
counter->read = _SPARC_Counter_read_down; counter->read = _SPARC_Counter_read_down;
counter->counter_register = &gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].value; counter->counter_register = &timer->tcntval;
/* Enable timer just in case no clock driver is configured */ /* Enable timer just in case no clock driver is configured */
gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].reload = 0xffffffff; grlib_store_32(&timer->trldval, 0xffffffff);
gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].ctrl |= GPTIMER_TIMER_CTRL_EN | tctrl = grlib_load_32(&timer->tctrl);
GPTIMER_TIMER_CTRL_RS | tctrl |= GPTIMER_TCTRL_EN | GPTIMER_TCTRL_RS | GPTIMER_TCTRL_LD;
GPTIMER_TIMER_CTRL_LD; grlib_store_32(&timer->tctrl, tctrl);
leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) / leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) /
(gpt->scaler_reload + 1); (grlib_load_32(&gpt->sreload) + 1);
} }
} }