aboutsummaryrefslogtreecommitdiffstats
path: root/xen
diff options
context:
space:
mode:
authorJulien Grall <julien.grall@linaro.org>2013-09-13 13:49:25 +0100
committerIan Campbell <ian.campbell@citrix.com>2013-09-17 15:28:51 +0100
commit5b73b82d2fddc450c73a268e1e70f5b25b6232c0 (patch)
treecc2048077cb70069e2fd40cd8d8e2819c3df2c3a /xen
parent42d85eed433e34c531715bbbe1d2bbdc8ab8861a (diff)
downloadxen-5b73b82d2fddc450c73a268e1e70f5b25b6232c0.tar.gz
xen-5b73b82d2fddc450c73a268e1e70f5b25b6232c0.tar.bz2
xen-5b73b82d2fddc450c73a268e1e70f5b25b6232c0.zip
xen/arm: Create a fake timer node in dom0 device tree
Recreate the timer node and remove hypervisor specific interrupt. Signed-off-by: Julien Grall <julien.grall@linaro.org> Acked-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'xen')
-rw-r--r--xen/arch/arm/domain_build.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 87382d5229..cda1e13d7a 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -512,6 +512,67 @@ static int make_gic_node(const struct domain *d, void *fdt,
return res;
}
+static int make_timer_node(const struct domain *d, void *fdt,
+ const struct dt_device_node *parent)
+{
+ static const struct dt_device_match timer_ids[] __initconst =
+ {
+ DT_MATCH_COMPATIBLE("arm,armv7-timer"),
+ DT_MATCH_COMPATIBLE("arm,armv8-timer"),
+ { /* sentinel */ },
+ };
+ struct dt_device_node *dev;
+ u32 len;
+ const void *compatible;
+ int res;
+ const struct dt_irq *irq;
+ gic_interrupt_t intrs[3];
+
+ DPRINT("Create timer node\n");
+
+ dev = dt_find_matching_node(NULL, timer_ids);
+ if ( !dev )
+ {
+ dprintk(XENLOG_ERR, "Missing timer node in the device tree?\n");
+ return -FDT_ERR_XEN(ENOENT);
+ }
+
+ compatible = dt_get_property(dev, "compatible", &len);
+ if ( !compatible )
+ {
+ dprintk(XENLOG_ERR, "Can't find compatible property for timer node\n");
+ return -FDT_ERR_XEN(ENOENT);
+ }
+
+ res = fdt_begin_node(fdt, "timer");
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "compatible", compatible, len);
+ if ( res )
+ return res;
+
+ irq = timer_dt_irq(TIMER_PHYS_SECURE_PPI);
+ DPRINT(" Secure interrupt %u\n", irq->irq);
+ set_interrupt_ppi(intrs[0], irq->irq, 0xf, irq->type);
+
+ irq = timer_dt_irq(TIMER_PHYS_NONSECURE_PPI);
+ DPRINT(" Non secure interrupt %u\n", irq->irq);
+ set_interrupt_ppi(intrs[1], irq->irq, 0xf, irq->type);
+
+ irq = timer_dt_irq(TIMER_VIRT_PPI);
+ DPRINT(" Virt interrupt %u\n", irq->irq);
+ set_interrupt_ppi(intrs[2], irq->irq, 0xf, irq->type);
+
+ res = fdt_property_interrupts(fdt, intrs, 3);
+ if ( res )
+ return res;
+
+ res = fdt_end_node(fdt);
+
+ return res;
+}
+
/* Map the device in the domain */
static int map_device(struct domain *d, const struct dt_device_node *dev)
{
@@ -602,6 +663,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
DT_MATCH_COMPATIBLE("arm,psci"),
DT_MATCH_PATH("/cpus"),
DT_MATCH_GIC,
+ DT_MATCH_TIMER,
{ /* sentinel */ },
};
const struct dt_device_node *child;
@@ -679,6 +741,10 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo,
res = make_gic_node(d, kinfo->fdt, np);
if ( res )
return res;
+
+ res = make_timer_node(d, kinfo->fdt, np);
+ if ( res )
+ return res;
}
res = fdt_end_node(kinfo->fdt);