drivers: arcv2_timer0: add support for smp
* use global free running counter as global wall clock (clock source) * use arc internal timer 0 as local time event (clock event) Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
parent
1f4232ad7e
commit
31a0371a0a
1 changed files with 90 additions and 4 deletions
|
@ -35,10 +35,16 @@
|
||||||
|
|
||||||
static struct k_spinlock lock;
|
static struct k_spinlock lock;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
volatile static u64_t last_time;
|
||||||
|
volatile static u64_t start_time;
|
||||||
|
|
||||||
|
#else
|
||||||
static u32_t last_load;
|
static u32_t last_load;
|
||||||
|
|
||||||
static u32_t cycle_count;
|
static u32_t cycle_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -106,6 +112,7 @@ static ALWAYS_INLINE void timer0_limit_register_set(u32_t count)
|
||||||
z_arc_v2_aux_reg_write(_ARC_V2_TMR0_LIMIT, count);
|
z_arc_v2_aux_reg_write(_ARC_V2_TMR0_LIMIT, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_SMP
|
||||||
static u32_t elapsed(void)
|
static u32_t elapsed(void)
|
||||||
{
|
{
|
||||||
u32_t val, ov, ctrl;
|
u32_t val, ov, ctrl;
|
||||||
|
@ -118,6 +125,7 @@ static u32_t elapsed(void)
|
||||||
ov = (ctrl & _ARC_V2_TMR_CTRL_IP) ? last_load : 0;
|
ov = (ctrl & _ARC_V2_TMR_CTRL_IP) ? last_load : 0;
|
||||||
return val + ov;
|
return val + ov;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -137,10 +145,25 @@ static void timer_int_handler(void *unused)
|
||||||
/* clear the interrupt by writing 0 to IP bit of the control register */
|
/* clear the interrupt by writing 0 to IP bit of the control register */
|
||||||
timer0_control_register_set(_ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE);
|
timer0_control_register_set(_ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
u64_t curr_time;
|
||||||
|
k_spinlock_key_t key;
|
||||||
|
|
||||||
|
key = k_spin_lock(&lock);
|
||||||
|
/* gfrc is the wall clock */
|
||||||
|
curr_time = z_arc_connect_gfrc_read();
|
||||||
|
|
||||||
|
dticks = (curr_time - last_time) / CYC_PER_TICK;
|
||||||
|
last_time = curr_time;
|
||||||
|
|
||||||
|
k_spin_unlock(&lock, key);
|
||||||
|
|
||||||
|
z_clock_announce(dticks);
|
||||||
|
#else
|
||||||
cycle_count += last_load;
|
cycle_count += last_load;
|
||||||
dticks = last_load / CYC_PER_TICK;
|
dticks = last_load / CYC_PER_TICK;
|
||||||
|
|
||||||
z_clock_announce(TICKLESS ? dticks : 1);
|
z_clock_announce(TICKLESS ? dticks : 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +184,14 @@ int z_clock_driver_init(struct device *device)
|
||||||
/* ensure that the timer will not generate interrupts */
|
/* ensure that the timer will not generate interrupts */
|
||||||
timer0_control_register_set(0);
|
timer0_control_register_set(0);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
IRQ_CONNECT(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY,
|
||||||
|
timer_int_handler, NULL, 0);
|
||||||
|
|
||||||
|
timer0_limit_register_set(CYC_PER_TICK - 1);
|
||||||
|
last_time = z_arc_connect_gfrc_read();
|
||||||
|
start_time = last_time;
|
||||||
|
#else
|
||||||
last_load = CYC_PER_TICK;
|
last_load = CYC_PER_TICK;
|
||||||
|
|
||||||
IRQ_CONNECT(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY,
|
IRQ_CONNECT(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY,
|
||||||
|
@ -169,6 +200,7 @@ int z_clock_driver_init(struct device *device)
|
||||||
timer0_limit_register_set(last_load - 1);
|
timer0_limit_register_set(last_load - 1);
|
||||||
#ifdef CONFIG_BOOT_TIME_MEASUREMENT
|
#ifdef CONFIG_BOOT_TIME_MEASUREMENT
|
||||||
cycle_count = timer0_count_register_get();
|
cycle_count = timer0_count_register_get();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
timer0_count_register_set(0);
|
timer0_count_register_set(0);
|
||||||
timer0_control_register_set(_ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE);
|
timer0_control_register_set(_ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE);
|
||||||
|
@ -186,6 +218,33 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
|
||||||
* then shut off the counter. (Note: we can assume if idle==true
|
* then shut off the counter. (Note: we can assume if idle==true
|
||||||
* that interrupts are already disabled)
|
* that interrupts are already disabled)
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
if (IS_ENABLED(CONFIG_TICKLESS_IDLE) && idle && ticks == K_FOREVER) {
|
||||||
|
timer0_control_register_set(0);
|
||||||
|
timer0_count_register_set(0);
|
||||||
|
timer0_limit_register_set(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_TICKLESS_KERNEL)
|
||||||
|
u32_t delay;
|
||||||
|
u32_t key;
|
||||||
|
|
||||||
|
ticks = MIN(MAX_TICKS, MAX(ticks - 1, 0));
|
||||||
|
|
||||||
|
/* Desired delay in the future */
|
||||||
|
delay = (ticks == 0) ? CYC_PER_TICK : ticks * CYC_PER_TICK;
|
||||||
|
|
||||||
|
key = z_arch_irq_lock();
|
||||||
|
|
||||||
|
timer0_limit_register_set(delay - 1);
|
||||||
|
timer0_count_register_set(0);
|
||||||
|
timer0_control_register_set(_ARC_V2_TMR_CTRL_NH |
|
||||||
|
_ARC_V2_TMR_CTRL_IE);
|
||||||
|
|
||||||
|
z_arch_irq_unlock(key);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
if (IS_ENABLED(CONFIG_TICKLESS_IDLE) && idle && ticks == K_FOREVER) {
|
if (IS_ENABLED(CONFIG_TICKLESS_IDLE) && idle && ticks == K_FOREVER) {
|
||||||
timer0_control_register_set(0);
|
timer0_control_register_set(0);
|
||||||
timer0_count_register_set(0);
|
timer0_count_register_set(0);
|
||||||
|
@ -221,6 +280,7 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
|
||||||
|
|
||||||
k_spin_unlock(&lock, key);
|
k_spin_unlock(&lock, key);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
u32_t z_clock_elapsed(void)
|
u32_t z_clock_elapsed(void)
|
||||||
|
@ -229,20 +289,31 @@ u32_t z_clock_elapsed(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32_t cyc;
|
||||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||||
u32_t cyc = elapsed();
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
cyc = (z_arc_connect_gfrc_read() - last_time) / CYC_PER_TICK;
|
||||||
|
#else
|
||||||
|
cyc = elapsed() / CYC_PER_TICK;
|
||||||
|
#endif
|
||||||
|
|
||||||
k_spin_unlock(&lock, key);
|
k_spin_unlock(&lock, key);
|
||||||
return cyc / CYC_PER_TICK;
|
|
||||||
|
return cyc;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32_t z_timer_cycle_get_32(void)
|
u32_t z_timer_cycle_get_32(void)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
return z_arc_connect_gfrc_read() - start_time;
|
||||||
|
#else
|
||||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||||
u32_t ret = elapsed() + cycle_count;
|
u32_t ret = elapsed() + cycle_count;
|
||||||
|
|
||||||
k_spin_unlock(&lock, key);
|
k_spin_unlock(&lock, key);
|
||||||
return ret;
|
return ret;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -272,3 +343,18 @@ void sys_clock_disable(void)
|
||||||
|
|
||||||
irq_disable(IRQ_TIMER0);
|
irq_disable(IRQ_TIMER0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
void smp_timer_init(void)
|
||||||
|
{
|
||||||
|
/* set the initial status of timer0 of each slave core
|
||||||
|
*/
|
||||||
|
timer0_control_register_set(0);
|
||||||
|
timer0_count_register_set(0);
|
||||||
|
timer0_limit_register_set(0);
|
||||||
|
|
||||||
|
z_irq_priority_set(IRQ_TIMER0, CONFIG_ARCV2_TIMER_IRQ_PRIORITY, 0);
|
||||||
|
irq_enable(IRQ_TIMER0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue