From mboxrd@z Thu Jan 1 00:00:00 1970 From: vijay.kilari@gmail.com Subject: [PATCH for-4.5 v11 5/7] xen/arm: Update Dom0 GIC dt node with GICv3 information Date: Fri, 12 Sep 2014 16:39:47 +0530 Message-ID: <1410520189-9086-6-git-send-email-vijay.kilari@gmail.com> References: <1410520189-9086-1-git-send-email-vijay.kilari@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1410520189-9086-1-git-send-email-vijay.kilari@gmail.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Ian.Campbell@citrix.com, julien.grall@linaro.org, stefano.stabellini@eu.citrix.com, stefano.stabellini@citrix.com, tim@xen.org, xen-devel@lists.xen.org Cc: Prasun.Kapoor@caviumnetworks.com, Vijaya Kumar K , manish.jaggi@caviumnetworks.com, vijay.kilari@gmail.com List-Id: xen-devel@lists.xenproject.org From: Vijaya Kumar K 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 Acked-by: Julien Grall Acked-by: Ian Campbell --- xen/arch/arm/domain_build.c | 47 ++------------------------ xen/arch/arm/gic-v2.c | 51 ++++++++++++++++++++++++++++ xen/arch/arm/gic-v3.c | 78 +++++++++++++++++++++++++++++++++++++++++++ xen/arch/arm/gic.c | 6 ++++ xen/include/asm-arm/gic.h | 4 +++ 5 files changed, 141 insertions(+), 45 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 2d316dd..90abc3a 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -777,9 +777,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; /* @@ -794,48 +791,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; @@ -1058,6 +1014,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 78ad4de..f053b5d 100644 --- a/xen/arch/arm/gic-v2.c +++ b/xen/arch/arm/gic-v2.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -585,6 +586,55 @@ static void gicv2_irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_m spin_unlock(&gicv2.lock); } +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", @@ -630,6 +680,7 @@ const static struct gic_hw_operations gicv2_ops = { .write_lr = gicv2_write_lr, .read_vmcr_priority = gicv2_read_vmcr_priority, .read_apr = gicv2_read_apr, + .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 6ccde02..ca450f9 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -1027,6 +1028,82 @@ static void gicv3_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask) spin_unlock(&gicv3.lock); } +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; +} + static const hw_irq_controller gicv3_host_irq_type = { .typename = "gic-v3", .startup = gicv3_irq_startup, @@ -1071,6 +1148,7 @@ static const struct gic_hw_operations gicv3_ops = { .read_vmcr_priority = gicv3_read_vmcr_priority, .read_apr = gicv3_read_apr, .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 6611ba0..70d10d6 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -625,6 +625,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 c4daf5b..51a0a26 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -336,9 +336,13 @@ struct gic_hw_operations { unsigned int (*read_apr)(int apr_reg); /* 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); +int gic_make_node(const struct domain *d,const struct dt_device_node *node, + void *fdt); #endif /* __ASSEMBLY__ */ #endif -- 1.7.9.5