mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
xen/arm: Retrieve timer interrupts from the device tree
Signed-off-by: Julien Grall <julien.grall@linaro.org> Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
71fa862f21
commit
f5bde3da40
3 files changed
+61
-13
No files matched your search
+2
-7
@@ -488,15 +488,10 @@ void gic_disable_cpu(void)
|
||||
|
||||
void gic_route_ppis(void)
|
||||
{
|
||||
/* XXX should get these from DT */
|
||||
/* GIC maintenance */
|
||||
gic_route_dt_irq(&gic.maintenance, 1u << smp_processor_id(), 0xa0);
|
||||
/* Hypervisor Timer */
|
||||
gic_route_irq(26, 1, 1u << smp_processor_id(), 0xa0);
|
||||
/* Virtual Timer */
|
||||
gic_route_irq(27, 1, 1u << smp_processor_id(), 0xa0);
|
||||
/* Physical Timer */
|
||||
gic_route_irq(30, 1, 1u << smp_processor_id(), 0xa0);
|
||||
/* Route timer interrupt */
|
||||
route_timer_interrupt();
|
||||
}
|
||||
|
||||
void gic_route_spis(void)
|
||||
|
||||
+47
-6
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/device_tree.h>
|
||||
#include <xen/init.h>
|
||||
#include <xen/irq.h>
|
||||
#include <xen/lib.h>
|
||||
@@ -46,6 +47,8 @@ uint64_t __read_mostly boot_count;
|
||||
* register-mapped time source in the SoC. */
|
||||
unsigned long __read_mostly cpu_khz; /* CPU clock frequency in kHz. */
|
||||
|
||||
static struct dt_irq timer_irq[MAX_TIMER_PPI];
|
||||
|
||||
/*static inline*/ s_time_t ticks_to_ns(uint64_t ticks)
|
||||
{
|
||||
return muldiv64(ticks, SECONDS(1), 1000 * cpu_khz);
|
||||
@@ -90,6 +93,29 @@ static uint32_t calibrate_timer(void)
|
||||
/* Set up the timer on the boot CPU */
|
||||
int __init init_xen_time(void)
|
||||
{
|
||||
struct dt_device_node *dev;
|
||||
int res;
|
||||
unsigned int i;
|
||||
|
||||
dev = dt_find_compatible_node(NULL, NULL, "arm,armv7-timer");
|
||||
if ( !dev )
|
||||
panic("Unable to find a compatible timer in the device tree\n");
|
||||
|
||||
dt_device_set_used_by(dev, DOMID_XEN);
|
||||
|
||||
/* Retrieve all IRQs for the timer */
|
||||
for ( i = TIMER_PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ )
|
||||
{
|
||||
res = dt_device_get_irq(dev, i, &timer_irq[i]);
|
||||
if ( res )
|
||||
panic("Timer: Unable to retrieve IRQ %u from the device tree\n", i);
|
||||
}
|
||||
|
||||
printk("Generic Timer IRQ: phys=%u hyp=%u virt=%u\n",
|
||||
timer_irq[TIMER_PHYS_NONSECURE_PPI].irq,
|
||||
timer_irq[TIMER_HYP_PPI].irq,
|
||||
timer_irq[TIMER_VIRT_PPI].irq);
|
||||
|
||||
/* Check that this CPU supports the Generic Timer interface */
|
||||
if ( !cpu_has_gentimer )
|
||||
panic("CPU does not support the Generic Timer v1 interface.\n");
|
||||
@@ -143,7 +169,8 @@ int reprogram_timer(s_time_t timeout)
|
||||
/* Handle the firing timer */
|
||||
static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
|
||||
{
|
||||
if ( irq == 26 && READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING )
|
||||
if ( irq == (timer_irq[TIMER_HYP_PPI].irq) &&
|
||||
READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING )
|
||||
{
|
||||
/* Signal the generic timer code to do its work */
|
||||
raise_softirq(TIMER_SOFTIRQ);
|
||||
@@ -151,7 +178,8 @@ static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
|
||||
WRITE_SYSREG32(0, CNTHP_CTL_EL2);
|
||||
}
|
||||
|
||||
if (irq == 30 && READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING )
|
||||
if ( irq == (timer_irq[TIMER_PHYS_NONSECURE_PPI].irq) &&
|
||||
READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING )
|
||||
{
|
||||
/* Signal the generic timer code to do its work */
|
||||
raise_softirq(TIMER_SOFTIRQ);
|
||||
@@ -167,6 +195,17 @@ static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
|
||||
vgic_vcpu_inject_irq(current, irq, 1);
|
||||
}
|
||||
|
||||
/* Route timer's IRQ on this CPU */
|
||||
void __cpuinit route_timer_interrupt(void)
|
||||
{
|
||||
gic_route_dt_irq(&timer_irq[TIMER_PHYS_NONSECURE_PPI],
|
||||
1u << smp_processor_id(), 0xa0);
|
||||
gic_route_dt_irq(&timer_irq[TIMER_HYP_PPI],
|
||||
1u << smp_processor_id(), 0xa0);
|
||||
gic_route_dt_irq(&timer_irq[TIMER_VIRT_PPI],
|
||||
1u << smp_processor_id(), 0xa0);
|
||||
}
|
||||
|
||||
/* Set up the timer interrupt on this CPU */
|
||||
void __cpuinit init_timer_interrupt(void)
|
||||
{
|
||||
@@ -184,10 +223,12 @@ void __cpuinit init_timer_interrupt(void)
|
||||
WRITE_SYSREG32(0, CNTHP_CTL_EL2); /* Hypervisor's timer disabled */
|
||||
isb();
|
||||
|
||||
/* XXX Need to find this IRQ number from devicetree? */
|
||||
request_irq(26, timer_interrupt, 0, "hyptimer", NULL);
|
||||
request_irq(27, vtimer_interrupt, 0, "virtimer", NULL);
|
||||
request_irq(30, timer_interrupt, 0, "phytimer", NULL);
|
||||
request_dt_irq(&timer_irq[TIMER_HYP_PPI], timer_interrupt, 0,
|
||||
"hyptimer", NULL);
|
||||
request_dt_irq(&timer_irq[TIMER_VIRT_PPI], vtimer_interrupt, 0,
|
||||
"virtimer", NULL);
|
||||
request_dt_irq(&timer_irq[TIMER_PHYS_NONSECURE_PPI], timer_interrupt, 0,
|
||||
"phytimer", NULL);
|
||||
}
|
||||
|
||||
/* Wait a set number of microseconds */
|
||||
|
||||
@@ -11,6 +11,18 @@ static inline cycles_t get_cycles (void)
|
||||
struct tm;
|
||||
struct tm wallclock_time(void);
|
||||
|
||||
/* List of timer's IRQ */
|
||||
enum timer_ppi
|
||||
{
|
||||
TIMER_PHYS_SECURE_PPI = 0,
|
||||
TIMER_PHYS_NONSECURE_PPI = 1,
|
||||
TIMER_VIRT_PPI = 2,
|
||||
TIMER_HYP_PPI = 3,
|
||||
MAX_TIMER_PPI = 4,
|
||||
};
|
||||
|
||||
/* Route timer's IRQ on this CPU */
|
||||
extern void __cpuinit route_timer_interrupt(void);
|
||||
|
||||
/* Set up the timer interrupt on this CPU */
|
||||
extern void __cpuinit init_timer_interrupt(void);
|
||||
|
||||