[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v4 15/16] xen/arm: Update Dom0 GIC dt node with GICv3 information
From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> Update GIC device tree node for DOM0 with GICv3 information. GIC hw specfic device tree information is moved to respective GIC driver. Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> --- xen/arch/arm/domain_build.c | 47 ++------------------------ xen/arch/arm/gic-v2.c | 51 ++++++++++++++++++++++++++++ xen/arch/arm/gic-v3.c | 77 +++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/gic.c | 6 ++++ xen/include/asm-arm/gic.h | 7 +++- 5 files changed, 142 insertions(+), 46 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 15ed97b..c5905af 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -524,9 +524,6 @@ static int make_gic_node(const struct domain *d, void *fdt, const struct dt_device_node *node) { const struct dt_device_node *gic = dt_interrupt_controller; - const void *compatible = NULL; - u32 len; - __be32 *new_cells, *tmp; int res = 0; /* @@ -541,48 +538,7 @@ static int make_gic_node(const struct domain *d, void *fdt, DPRINT("Create gic node\n"); - compatible = dt_get_property(gic, "compatible", &len); - if ( !compatible ) - { - dprintk(XENLOG_ERR, "Can't find compatible property for the gic node\n"); - return -FDT_ERR_XEN(ENOENT); - } - - res = fdt_begin_node(fdt, "interrupt-controller"); - if ( res ) - return res; - - res = fdt_property(fdt, "compatible", compatible, len); - if ( res ) - return res; - - res = fdt_property_cell(fdt, "#interrupt-cells", 3); - if ( res ) - return res; - - res = fdt_property(fdt, "interrupt-controller", NULL, 0); - - if ( res ) - return res; - - len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node)); - len *= 2; /* GIC has two memory regions: Distributor + CPU interface */ - new_cells = xzalloc_bytes(len); - if ( new_cells == NULL ) - return -FDT_ERR_XEN(ENOMEM); - - tmp = new_cells; - DPRINT(" Set Distributor Base 0x%"PRIpaddr"-0x%"PRIpaddr"\n", - d->arch.vgic.dbase, d->arch.vgic.dbase + PAGE_SIZE - 1); - dt_set_range(&tmp, node, d->arch.vgic.dbase, PAGE_SIZE); - - DPRINT(" Set Cpu Base 0x%"PRIpaddr"-0x%"PRIpaddr"\n", - d->arch.vgic.cbase, d->arch.vgic.cbase + (PAGE_SIZE * 2) - 1); - dt_set_range(&tmp, node, d->arch.vgic.cbase, PAGE_SIZE * 2); - - res = fdt_property(fdt, "reg", new_cells, len); - xfree(new_cells); - + res = gic_make_node(d, node, fdt); if ( res ) return res; @@ -781,6 +737,7 @@ static int handle_node(struct domain *d, struct kernel_info *kinfo, static const struct dt_device_match gic_matches[] __initconst = { DT_MATCH_GIC_V2, + DT_MATCH_GIC_V3, { /* sentinel */ }, }; static const struct dt_device_match timer_matches[] __initconst = diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c index 8060de3..a1f65c3 100644 --- a/xen/arch/arm/gic-v2.c +++ b/xen/arch/arm/gic-v2.c @@ -27,6 +27,7 @@ #include <xen/softirq.h> #include <xen/list.h> #include <xen/device_tree.h> +#include <xen/libfdt/libfdt.h> #include <asm/p2m.h> #include <asm/domain.h> #include <asm/platform.h> @@ -538,6 +539,55 @@ static void gicv2_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask) BUG(); } +static int gicv2_make_dt_node(const struct domain *d, + const struct dt_device_node *node, void *fdt) +{ + const struct dt_device_node *gic = dt_interrupt_controller; + const void *compatible = NULL; + u32 len; + __be32 *new_cells, *tmp; + int res = 0; + + compatible = dt_get_property(gic, "compatible", &len); + if ( !compatible ) + { + dprintk(XENLOG_ERR, "Can't find compatible property for the gic node\n"); + return -FDT_ERR_XEN(ENOENT); + } + + res = fdt_begin_node(fdt, "interrupt-controller"); + if ( res ) + return res; + + res = fdt_property(fdt, "compatible", compatible, len); + if ( res ) + return res; + + res = fdt_property_cell(fdt, "#interrupt-cells", 3); + if ( res ) + return res; + + res = fdt_property(fdt, "interrupt-controller", NULL, 0); + + if ( res ) + return res; + + len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node)); + len *= 2; /* GIC has two memory regions: Distributor + CPU interface */ + new_cells = xzalloc_bytes(len); + if ( new_cells == NULL ) + return -FDT_ERR_XEN(ENOMEM); + + tmp = new_cells; + dt_set_range(&tmp, node, d->arch.vgic.dbase, PAGE_SIZE); + dt_set_range(&tmp, node, d->arch.vgic.cbase, PAGE_SIZE * 2); + + res = fdt_property(fdt, "reg", new_cells, len); + xfree(new_cells); + + return res; +} + /* XXX different for level vs edge */ static hw_irq_controller gicv2_host_irq_type = { .typename = "gic-v2", @@ -582,6 +632,7 @@ const static struct gic_hw_operations gicv2_ops = { .read_lr = gicv2_read_lr, .write_lr = gicv2_write_lr, .read_vmcr_priority = gicv2_read_vmcr_priority, + .make_dt_node = gicv2_make_dt_node, }; /* Set up the GIC */ diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index 7543fb4..654234f 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -953,6 +953,82 @@ static void gicv3_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask) BUG(); } +static int gicv3_make_dt_node(const struct domain *d, + const struct dt_device_node *node, void *fdt) +{ + const struct dt_device_node *gic = dt_interrupt_controller; + const void *compatible = NULL; + uint32_t len; + __be32 *new_cells, *tmp; + uint32_t rd_stride = 0; + uint32_t rd_count = 0; + + int i, res = 0; + + compatible = dt_get_property(gic, "compatible", &len); + if ( !compatible ) + { + dprintk(XENLOG_ERR, "Can't find compatible property for the gic node\n"); + return -FDT_ERR_XEN(ENOENT); + } + + res = fdt_begin_node(fdt, "interrupt-controller"); + if ( res ) + return res; + + res = fdt_property(fdt, "compatible", compatible, len); + if ( res ) + return res; + + res = fdt_property_cell(fdt, "#interrupt-cells", 3); + if ( res ) + return res; + + res = fdt_property(fdt, "interrupt-controller", NULL, 0); + if ( res ) + return res; + + res = dt_property_read_u32(gic, "redistributor-stride", &rd_stride); + if ( !res ) + rd_stride = 0; + + res = dt_property_read_u32(gic, "#redistributor-regions", &rd_count); + if ( !res ) + rd_count = 1; + + res = fdt_property_cell(fdt, "redistributor-stride", rd_stride); + if ( res ) + return res; + + res = fdt_property_cell(fdt, "#redistributor-regions", rd_count); + if ( res ) + return res; + + len = dt_cells_to_size(dt_n_addr_cells(node) + dt_n_size_cells(node)); + /* + * GIC has two memory regions: Distributor + rdist regions + * CPU interface and virtual cpu interfaces accessesed as System registers + * So cells are created only for Distributor and rdist regions + */ + len = len * (d->arch.vgic.rdist_count + 1); + new_cells = xzalloc_bytes(len); + if ( new_cells == NULL ) + return -FDT_ERR_XEN(ENOMEM); + + tmp = new_cells; + + dt_set_range(&tmp, node, d->arch.vgic.dbase, d->arch.vgic.dbase_size); + + for ( i = 0; i < d->arch.vgic.rdist_count; i++ ) + dt_set_range(&tmp, node, d->arch.vgic.rbase[i], + d->arch.vgic.rbase_size[i]); + + res = fdt_property(fdt, "reg", new_cells, len); + xfree(new_cells); + + return res; +} + const static hw_irq_controller gicv3_host_irq_type = { .typename = "gic-v3", .startup = gicv3_irq_startup, @@ -996,6 +1072,7 @@ const static struct gic_hw_operations gicv3_ops = { .write_lr = gicv3_write_lr, .read_vmcr_priority = gicv3_read_vmcr_priority, .secondary_init = gicv3_secondary_cpu_init, + .make_dt_node = gicv3_make_dt_node, }; /* Set up the GIC */ diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 9331216..2c50c72 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -622,6 +622,12 @@ void __cpuinit init_maintenance_interrupt(void) "irq-maintenance", NULL); } +int gic_make_node(const struct domain *d,const struct dt_device_node *node, + void *fdt) +{ + return gic_hw_ops->make_dt_node(d, node, fdt); +} + /* * Local variables: * mode: C diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index b40beb5..acf1304 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -156,7 +156,7 @@ #define DT_MATCH_GIC_V3_STRING1 "arm,gic-v3" -#define DT_MATCH_GIC_V3 DT_MATCH_COMPATIBLE(DT_MATCH_GIC_V3_STRING1); +#define DT_MATCH_GIC_V3 DT_MATCH_COMPATIBLE(DT_MATCH_GIC_V3_STRING1) /* * GICv3 registers that needs to be saved/restored @@ -332,10 +332,15 @@ struct gic_hw_operations { unsigned int (*read_vmcr_priority)(void); /* Secondary CPU init */ int (*secondary_init)(void); + int (*make_dt_node)(const struct domain *d, + const struct dt_device_node *node, void *fdt); }; void register_gic_ops(const struct gic_hw_operations *ops); extern void update_cpu_lr_mask(void); +int gic_make_node(const struct domain *d,const struct dt_device_node *node, + void *fdt); + #endif /* __ASSEMBLY__ */ #endif -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |