[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v6 3/5] xen/arm: Make gic-v2 code handle hip04-d01 platform



The GIC in this platform is mainly compatible with the standard
GICv2 beside:
- ITARGET is extended to 16 bit to support 16 CPUs;
- SGI mask is extended to support 16 CPUs;
- maximum supported interrupt is 510.

Use nr_lines to check for maximum irq supported. hip04-d01 support less
interrupts due to some field restriction. Any value above this is already
an error.

Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
Signed-off-by: Zoltan Kiss <zoltan.kiss@xxxxxxxxxx>
---
 xen/arch/arm/Makefile       |   3 +
 xen/arch/arm/domain_build.c |   1 +
 xen/arch/arm/gic-hip04.c    | 351 ++++++++++++++++++++++----------------------
 xen/arch/arm/gic.c          |   3 +-
 xen/include/asm-arm/gic.h   |   4 +
 5 files changed, 188 insertions(+), 174 deletions(-)

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 41aba2e..fad72d2 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -12,6 +12,9 @@ obj-y += domctl.o
 obj-y += sysctl.o
 obj-y += domain_build.o
 obj-y += gic.o gic-v2.o
+ifeq (arm32,$(XEN_TARGET_ARCH))
+obj-$(HAS_NON_STANDARD_DRIVERS) += gic-hip04.o
+endif
 obj-$(CONFIG_ARM_64) += gic-v3.o
 obj-y += io.o
 obj-y += irq.o
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index c2dcb49..0834053 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1038,6 +1038,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_HIP04,
         DT_MATCH_GIC_V3,
         { /* sentinel */ },
     };
diff --git a/xen/arch/arm/gic-hip04.c b/xen/arch/arm/gic-hip04.c
index a401e3f..84d60fd 100644
--- a/xen/arch/arm/gic-hip04.c
+++ b/xen/arch/arm/gic-hip04.c
@@ -1,7 +1,8 @@
 /*
- * xen/arch/arm/gic-v2.c
+ * xen/arch/arm/gic-hip04.c
  *
- * ARM Generic Interrupt Controller support v2
+ * Generic Interrupt Controller for HiSilicon Hip04 platform
+ * Based heavily from gic-v2.c
  *
  * Tim Deegan <tim@xxxxxxx>
  * Copyright (c) 2011 Citrix Systems.
@@ -71,59 +72,66 @@ static struct {
     void __iomem * map_hbase; /* IO Address of virtual interface registers */
     paddr_t vbase;            /* Address of virtual cpu interface registers */
     spinlock_t lock;
-} gicv2;
+} hip04gic;
 
-static struct gic_info gicv2_info;
+static struct gic_info hip04gic_info;
 
 /* The GIC mapping of CPU interfaces does not necessarily match the
  * logical CPU numbering. Let's use mapping as returned by the GIC
  * itself
  */
-static DEFINE_PER_CPU(u8, gic_cpu_id);
+static DEFINE_PER_CPU(u16, gic_cpu_id);
 
 /* Maximum cpu interface per GIC */
-#define NR_GIC_CPU_IF 8
+#define NR_GIC_CPU_IF 16
+
+#define HIP04_GICD_SGI_TARGET_SHIFT 8
 
 static inline void writeb_gicd(uint8_t val, unsigned int offset)
 {
-    writeb_relaxed(val, gicv2.map_dbase + offset);
+    writeb_relaxed(val, hip04gic.map_dbase + offset);
+}
+
+static inline void writew_gicd(uint16_t val, unsigned int offset)
+{
+    writew_relaxed(val, hip04gic.map_dbase + offset);
 }
 
 static inline void writel_gicd(uint32_t val, unsigned int offset)
 {
-    writel_relaxed(val, gicv2.map_dbase + offset);
+    writel_relaxed(val, hip04gic.map_dbase + offset);
 }
 
 static inline uint32_t readl_gicd(unsigned int offset)
 {
-    return readl_relaxed(gicv2.map_dbase + offset);
+    return readl_relaxed(hip04gic.map_dbase + offset);
 }
 
 static inline void writel_gicc(uint32_t val, unsigned int offset)
 {
     unsigned int page = offset >> PAGE_SHIFT;
     offset &= ~PAGE_MASK;
-    writel_relaxed(val, gicv2.map_cbase[page] + offset);
+    writel_relaxed(val, hip04gic.map_cbase[page] + offset);
 }
 
 static inline uint32_t readl_gicc(unsigned int offset)
 {
     unsigned int page = offset >> PAGE_SHIFT;
     offset &= ~PAGE_MASK;
-    return readl_relaxed(gicv2.map_cbase[page] + offset);
+    return readl_relaxed(hip04gic.map_cbase[page] + offset);
 }
 
 static inline void writel_gich(uint32_t val, unsigned int offset)
 {
-    writel_relaxed(val, gicv2.map_hbase + offset);
+    writel_relaxed(val, hip04gic.map_hbase + offset);
 }
 
 static inline uint32_t readl_gich(int unsigned offset)
 {
-    return readl_relaxed(gicv2.map_hbase + offset);
+    return readl_relaxed(hip04gic.map_hbase + offset);
 }
 
-static unsigned int gicv2_cpu_mask(const cpumask_t *cpumask)
+static unsigned int hip04gic_cpu_mask(const cpumask_t *cpumask)
 {
     unsigned int cpu;
     unsigned int mask = 0;
@@ -139,7 +147,7 @@ static unsigned int gicv2_cpu_mask(const cpumask_t *cpumask)
     return mask;
 }
 
-static void gicv2_save_state(struct vcpu *v)
+static void hip04gic_save_state(struct vcpu *v)
 {
     int i;
 
@@ -147,7 +155,7 @@ static void gicv2_save_state(struct vcpu *v)
      * this call and it only accesses struct vcpu fields that cannot be
      * accessed simultaneously by another pCPU.
      */
-    for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+    for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
         v->arch.gic.v2.lr[i] = readl_gich(GICH_LR + i * 4);
 
     v->arch.gic.v2.apr = readl_gich(GICH_APR);
@@ -156,11 +164,11 @@ static void gicv2_save_state(struct vcpu *v)
     writel_gich(0, GICH_HCR);
 }
 
-static void gicv2_restore_state(const struct vcpu *v)
+static void hip04gic_restore_state(const struct vcpu *v)
 {
     int i;
 
-    for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+    for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
         writel_gich(v->arch.gic.v2.lr[i], GICH_LR + i * 4);
 
     writel_gich(v->arch.gic.v2.apr, GICH_APR);
@@ -168,37 +176,37 @@ static void gicv2_restore_state(const struct vcpu *v)
     writel_gich(GICH_HCR_EN, GICH_HCR);
 }
 
-static void gicv2_dump_state(const struct vcpu *v)
+static void hip04gic_dump_state(const struct vcpu *v)
 {
     int i;
 
     if ( v == current )
     {
-        for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+        for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
             printk("   HW_LR[%d]=%x\n", i,
                    readl_gich(GICH_LR + i * 4));
     }
     else
     {
-        for ( i = 0; i < gicv2_info.nr_lrs; i++ )
+        for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
             printk("   VCPU_LR[%d]=%x\n", i, v->arch.gic.v2.lr[i]);
     }
 }
 
-static void gicv2_eoi_irq(struct irq_desc *irqd)
+static void hip04gic_eoi_irq(struct irq_desc *irqd)
 {
     int irq = irqd->irq;
     /* Lower the priority */
     writel_gicc(irq, GICC_EOIR);
 }
 
-static void gicv2_dir_irq(struct irq_desc *irqd)
+static void hip04gic_dir_irq(struct irq_desc *irqd)
 {
     /* Deactivate */
     writel_gicc(irqd->irq, GICC_DIR);
 }
 
-static unsigned int gicv2_read_irq(void)
+static unsigned int hip04gic_read_irq(void)
 {
     return (readl_gicc(GICC_IAR) & GICC_IA_IRQ);
 }
@@ -207,19 +215,19 @@ static unsigned int gicv2_read_irq(void)
  * needs to be called with a valid cpu_mask, ie each cpu in the mask has
  * already called gic_cpu_init
  */
-static void gicv2_set_irq_properties(struct irq_desc *desc,
+static void hip04gic_set_irq_properties(struct irq_desc *desc,
                                    const cpumask_t *cpu_mask,
                                    unsigned int priority)
 {
     uint32_t cfg, edgebit;
-    unsigned int mask = gicv2_cpu_mask(cpu_mask);
+    unsigned int mask = hip04gic_cpu_mask(cpu_mask);
     unsigned int irq = desc->irq;
     unsigned int type = desc->arch.type;
 
     ASSERT(type != DT_IRQ_TYPE_INVALID);
     ASSERT(spin_is_locked(&desc->lock));
 
-    spin_lock(&gicv2.lock);
+    spin_lock(&hip04gic.lock);
     /* Set edge / level */
     cfg = readl_gicd(GICD_ICFGR + (irq / 16) * 4);
     edgebit = 2u << (2 * (irq % 16));
@@ -230,62 +238,61 @@ static void gicv2_set_irq_properties(struct irq_desc 
*desc,
     writel_gicd(cfg, GICD_ICFGR + (irq / 16) * 4);
 
     /* Set target CPU mask (RAZ/WI on uniprocessor) */
-    writeb_gicd(mask, GICD_ITARGETSR + irq);
+    writew_gicd(mask, GICD_ITARGETSR + irq * 2);
     /* Set priority */
     writeb_gicd(priority, GICD_IPRIORITYR + irq);
 
-    spin_unlock(&gicv2.lock);
+    spin_unlock(&hip04gic.lock);
 }
 
-static void __init gicv2_dist_init(void)
+static void __init hip04gic_dist_init(void)
 {
     uint32_t type;
     uint32_t cpumask;
     uint32_t gic_cpus;
     int i;
 
-    cpumask = readl_gicd(GICD_ITARGETSR) & 0xff;
-    cpumask |= cpumask << 8;
+    cpumask = readl_gicd(GICD_ITARGETSR) & 0xffff;
     cpumask |= cpumask << 16;
 
     /* Disable the distributor */
     writel_gicd(0, GICD_CTLR);
 
     type = readl_gicd(GICD_TYPER);
-    gicv2_info.nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
-    gic_cpus = 1 + ((type & GICD_TYPE_CPUS) >> 5);
+    hip04gic_info.nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1);
+    gic_cpus = 16;
     printk("GICv2: %d lines, %d cpu%s%s (IID %8.8x).\n",
-           gicv2_info.nr_lines, gic_cpus, (gic_cpus == 1) ? "" : "s",
+           hip04gic_info.nr_lines, gic_cpus, (gic_cpus == 1) ? "" : "s",
            (type & GICD_TYPE_SEC) ? ", secure" : "",
            readl_gicd(GICD_IIDR));
 
     /* Default all global IRQs to level, active low */
-    for ( i = 32; i < gicv2_info.nr_lines; i += 16 )
+    for ( i = 32; i < hip04gic_info.nr_lines; i += 16 )
         writel_gicd(0x0, GICD_ICFGR + (i / 16) * 4);
 
     /* Route all global IRQs to this CPU */
-    for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
-        writel_gicd(cpumask, GICD_ITARGETSR + (i / 4) * 4);
+    for ( i = 32; i < hip04gic_info.nr_lines; i += 2 )
+        writel_gicd(cpumask, GICD_ITARGETSR + (i / 2) * 4);
 
     /* Default priority for global interrupts */
-    for ( i = 32; i < gicv2_info.nr_lines; i += 4 )
+    for ( i = 32; i < hip04gic_info.nr_lines; i += 4 )
         writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 |
                     GIC_PRI_IRQ << 8 | GIC_PRI_IRQ,
                     GICD_IPRIORITYR + (i / 4) * 4);
 
     /* Disable all global interrupts */
-    for ( i = 32; i < gicv2_info.nr_lines; i += 32 )
+    for ( i = 32; i < hip04gic_info.nr_lines; i += 32 )
         writel_gicd(~0x0, GICD_ICENABLER + (i / 32) * 4);
 
     /* Turn on the distributor */
     writel_gicd(GICD_CTL_ENABLE, GICD_CTLR);
 }
 
-static void __cpuinit gicv2_cpu_init(void)
+static void __cpuinit hip04gic_cpu_init(void)
 {
     int i;
 
-    this_cpu(gic_cpu_id) = readl_gicd(GICD_ITARGETSR) & 0xff;
+    this_cpu(gic_cpu_id) = readl_gicd(GICD_ITARGETSR) & 0xffff;
 
     /* The first 32 interrupts (PPI and SGI) are banked per-cpu, so
      * even though they are controlled with GICD registers, they must
@@ -314,41 +321,41 @@ static void __cpuinit gicv2_cpu_init(void)
     writel_gicc(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC_CTLR);
 }
 
-static void gicv2_cpu_disable(void)
+static void hip04gic_cpu_disable(void)
 {
     writel_gicc(0x0, GICC_CTLR);
 }
 
-static void __cpuinit gicv2_hyp_init(void)
+static void __cpuinit hip04gic_hyp_init(void)
 {
     uint32_t vtr;
     uint8_t nr_lrs;
 
     vtr = readl_gich(GICH_VTR);
     nr_lrs  = (vtr & GICH_V2_VTR_NRLRGS) + 1;
-    gicv2_info.nr_lrs = nr_lrs;
+    hip04gic_info.nr_lrs = nr_lrs;
 
     writel_gich(GICH_MISR_EOI, GICH_MISR);
 }
 
-static void __cpuinit gicv2_hyp_disable(void)
+static void __cpuinit hip04gic_hyp_disable(void)
 {
     writel_gich(0, GICH_HCR);
 }
 
-static int gicv2_secondary_cpu_init(void)
+static int hip04gic_secondary_cpu_init(void)
 {
-    spin_lock(&gicv2.lock);
+    spin_lock(&hip04gic.lock);
 
-    gicv2_cpu_init();
-    gicv2_hyp_init();
+    hip04gic_cpu_init();
+    hip04gic_hyp_init();
 
-    spin_unlock(&gicv2.lock);
+    spin_unlock(&hip04gic.lock);
 
     return 0;
 }
 
-static void gicv2_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
+static void hip04gic_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode,
                            const cpumask_t *cpu_mask)
 {
     unsigned int mask = 0;
@@ -364,9 +371,9 @@ static void gicv2_send_SGI(enum gic_sgi sgi, enum 
gic_sgi_mode irqmode,
         break;
     case SGI_TARGET_LIST:
         cpumask_and(&online_mask, cpu_mask, &cpu_online_map);
-        mask = gicv2_cpu_mask(&online_mask);
+        mask = hip04gic_cpu_mask(&online_mask);
         writel_gicd(GICD_SGI_TARGET_LIST |
-                    (mask << GICD_SGI_TARGET_SHIFT) | sgi,
+                    (mask << HIP04_GICD_SGI_TARGET_SHIFT) | sgi,
                     GICD_SGIR);
         break;
     default:
@@ -375,20 +382,20 @@ static void gicv2_send_SGI(enum gic_sgi sgi, enum 
gic_sgi_mode irqmode,
 }
 
 /* Shut down the per-CPU GIC interface */
-static void gicv2_disable_interface(void)
+static void hip04gic_disable_interface(void)
 {
-    spin_lock(&gicv2.lock);
-    gicv2_cpu_disable();
-    gicv2_hyp_disable();
-    spin_unlock(&gicv2.lock);
+    spin_lock(&hip04gic.lock);
+    hip04gic_cpu_disable();
+    hip04gic_hyp_disable();
+    spin_unlock(&hip04gic.lock);
 }
 
-static void gicv2_update_lr(int lr, const struct pending_irq *p,
+static void hip04gic_update_lr(int lr, const struct pending_irq *p,
                             unsigned int state)
 {
     uint32_t lr_reg;
 
-    BUG_ON(lr >= gicv2_info.nr_lrs);
+    BUG_ON(lr >= hip04gic_info.nr_lrs);
     BUG_ON(lr < 0);
 
     lr_reg = (((state & GICH_V2_LR_STATE_MASK) << GICH_V2_LR_STATE_SHIFT)  |
@@ -408,12 +415,12 @@ static void gicv2_update_lr(int lr, const struct 
pending_irq *p,
     writel_gich(lr_reg, GICH_LR + lr * 4);
 }
 
-static void gicv2_clear_lr(int lr)
+static void hip04gic_clear_lr(int lr)
 {
     writel_gich(0, GICH_LR + lr * 4);
 }
 
-static int gicv2v_setup(struct domain *d)
+static int hip04gicv_setup(struct domain *d)
 {
     int ret;
 
@@ -423,8 +430,8 @@ static int gicv2v_setup(struct domain *d)
      */
     if ( is_hardware_domain(d) )
     {
-        d->arch.vgic.dbase = gicv2.dbase;
-        d->arch.vgic.cbase = gicv2.cbase;
+        d->arch.vgic.dbase = hip04gic.dbase;
+        d->arch.vgic.cbase = hip04gic.cbase;
     }
     else
     {
@@ -440,21 +447,21 @@ static int gicv2v_setup(struct domain *d)
      * GIC_64K_STRIDE quirk. The DTB passed to the guest reflects this.
      */
     ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase), 1,
-                            paddr_to_pfn(gicv2.vbase));
+                            paddr_to_pfn(hip04gic.vbase));
     if ( ret )
         return ret;
 
     if ( !platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
         ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
-                               2, paddr_to_pfn(gicv2.vbase + PAGE_SIZE));
+                               2, paddr_to_pfn(hip04gic.vbase + PAGE_SIZE));
     else
         ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
-                               2, paddr_to_pfn(gicv2.vbase + 16*PAGE_SIZE));
+                               2, paddr_to_pfn(hip04gic.vbase + 16*PAGE_SIZE));
 
     return ret;
 }
 
-static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
+static void hip04gic_read_lr(int lr, struct gic_lr *lr_reg)
 {
     uint32_t lrv;
 
@@ -467,7 +474,7 @@ static void gicv2_read_lr(int lr, struct gic_lr *lr_reg)
     lr_reg->grp       = (lrv >> GICH_V2_LR_GRP_SHIFT) & GICH_V2_LR_GRP_MASK;
 }
 
-static void gicv2_write_lr(int lr, const struct gic_lr *lr_reg)
+static void hip04gic_write_lr(int lr, const struct gic_lr *lr_reg)
 {
     uint32_t lrv = 0;
 
@@ -484,7 +491,7 @@ static void gicv2_write_lr(int lr, const struct gic_lr 
*lr_reg)
     writel_gich(lrv, GICH_LR + lr * 4);
 }
 
-static void gicv2_hcr_status(uint32_t flag, bool_t status)
+static void hip04gic_hcr_status(uint32_t flag, bool_t status)
 {
     uint32_t hcr = readl_gich(GICH_HCR);
 
@@ -496,95 +503,95 @@ static void gicv2_hcr_status(uint32_t flag, bool_t status)
     writel_gich(hcr, GICH_HCR);
 }
 
-static unsigned int gicv2_read_vmcr_priority(void)
+static unsigned int hip04gic_read_vmcr_priority(void)
 {
    return ((readl_gich(GICH_VMCR) >> GICH_V2_VMCR_PRIORITY_SHIFT)
            & GICH_V2_VMCR_PRIORITY_MASK);
 }
 
-static unsigned int gicv2_read_apr(int apr_reg)
+static unsigned int hip04gic_read_apr(int apr_reg)
 {
    return readl_gich(GICH_APR);
 }
 
-static void gicv2_irq_enable(struct irq_desc *desc)
+static void hip04gic_irq_enable(struct irq_desc *desc)
 {
     unsigned long flags;
     int irq = desc->irq;
 
     ASSERT(spin_is_locked(&desc->lock));
 
-    spin_lock_irqsave(&gicv2.lock, flags);
+    spin_lock_irqsave(&hip04gic.lock, flags);
     clear_bit(_IRQ_DISABLED, &desc->status);
     dsb(sy);
     /* Enable routing */
     writel_gicd((1u << (irq % 32)), GICD_ISENABLER + (irq / 32) * 4);
-    spin_unlock_irqrestore(&gicv2.lock, flags);
+    spin_unlock_irqrestore(&hip04gic.lock, flags);
 }
 
-static void gicv2_irq_disable(struct irq_desc *desc)
+static void hip04gic_irq_disable(struct irq_desc *desc)
 {
     unsigned long flags;
     int irq = desc->irq;
 
     ASSERT(spin_is_locked(&desc->lock));
 
-    spin_lock_irqsave(&gicv2.lock, flags);
+    spin_lock_irqsave(&hip04gic.lock, flags);
     /* Disable routing */
     writel_gicd(1u << (irq % 32), GICD_ICENABLER + (irq / 32) * 4);
     set_bit(_IRQ_DISABLED, &desc->status);
-    spin_unlock_irqrestore(&gicv2.lock, flags);
+    spin_unlock_irqrestore(&hip04gic.lock, flags);
 }
 
-static unsigned int gicv2_irq_startup(struct irq_desc *desc)
+static unsigned int hip04gic_irq_startup(struct irq_desc *desc)
 {
-    gicv2_irq_enable(desc);
+    hip04gic_irq_enable(desc);
 
     return 0;
 }
 
-static void gicv2_irq_shutdown(struct irq_desc *desc)
+static void hip04gic_irq_shutdown(struct irq_desc *desc)
 {
-    gicv2_irq_disable(desc);
+    hip04gic_irq_disable(desc);
 }
 
-static void gicv2_irq_ack(struct irq_desc *desc)
+static void hip04gic_irq_ack(struct irq_desc *desc)
 {
     /* No ACK -- reading IAR has done this for us */
 }
 
-static void gicv2_host_irq_end(struct irq_desc *desc)
+static void hip04gic_host_irq_end(struct irq_desc *desc)
 {
     /* Lower the priority */
-    gicv2_eoi_irq(desc);
+    hip04gic_eoi_irq(desc);
     /* Deactivate */
-    gicv2_dir_irq(desc);
+    hip04gic_dir_irq(desc);
 }
 
-static void gicv2_guest_irq_end(struct irq_desc *desc)
+static void hip04gic_guest_irq_end(struct irq_desc *desc)
 {
     /* Lower the priority of the IRQ */
-    gicv2_eoi_irq(desc);
+    hip04gic_eoi_irq(desc);
     /* Deactivation happens in maintenance interrupt / via GICV */
 }
 
-static void gicv2_irq_set_affinity(struct irq_desc *desc, const cpumask_t 
*cpu_mask)
+static void hip04gic_irq_set_affinity(struct irq_desc *desc, const cpumask_t 
*cpu_mask)
 {
     unsigned int mask;
 
     ASSERT(!cpumask_empty(cpu_mask));
 
-    spin_lock(&gicv2.lock);
+    spin_lock(&hip04gic.lock);
 
-    mask = gicv2_cpu_mask(cpu_mask);
+    mask = hip04gic_cpu_mask(cpu_mask);
 
     /* Set target CPU mask (RAZ/WI on uniprocessor) */
-    writeb_gicd(mask, GICD_ITARGETSR + desc->irq);
+    writew_gicd(mask, GICD_ITARGETSR + desc->irq * 2);
 
-    spin_unlock(&gicv2.lock);
+    spin_unlock(&hip04gic.lock);
 }
 
-static int gicv2_make_dt_node(const struct domain *d,
+static int hip04gic_make_dt_node(const struct domain *d,
                               const struct dt_device_node *node, void *fdt)
 {
     const struct dt_device_node *gic = dt_interrupt_controller;
@@ -637,80 +644,80 @@ static int gicv2_make_dt_node(const struct domain *d,
 }
 
 /* XXX different for level vs edge */
-static hw_irq_controller gicv2_host_irq_type = {
-    .typename     = "gic-v2",
-    .startup      = gicv2_irq_startup,
-    .shutdown     = gicv2_irq_shutdown,
-    .enable       = gicv2_irq_enable,
-    .disable      = gicv2_irq_disable,
-    .ack          = gicv2_irq_ack,
-    .end          = gicv2_host_irq_end,
-    .set_affinity = gicv2_irq_set_affinity,
+static hw_irq_controller hip04gic_host_irq_type = {
+    .typename     = "gic-hip04",
+    .startup      = hip04gic_irq_startup,
+    .shutdown     = hip04gic_irq_shutdown,
+    .enable       = hip04gic_irq_enable,
+    .disable      = hip04gic_irq_disable,
+    .ack          = hip04gic_irq_ack,
+    .end          = hip04gic_host_irq_end,
+    .set_affinity = hip04gic_irq_set_affinity,
 };
 
-static hw_irq_controller gicv2_guest_irq_type = {
-    .typename     = "gic-v2",
-    .startup      = gicv2_irq_startup,
-    .shutdown     = gicv2_irq_shutdown,
-    .enable       = gicv2_irq_enable,
-    .disable      = gicv2_irq_disable,
-    .ack          = gicv2_irq_ack,
-    .end          = gicv2_guest_irq_end,
-    .set_affinity = gicv2_irq_set_affinity,
+static hw_irq_controller hip04gic_guest_irq_type = {
+    .typename     = "gic-hip04",
+    .startup      = hip04gic_irq_startup,
+    .shutdown     = hip04gic_irq_shutdown,
+    .enable       = hip04gic_irq_enable,
+    .disable      = hip04gic_irq_disable,
+    .ack          = hip04gic_irq_ack,
+    .end          = hip04gic_guest_irq_end,
+    .set_affinity = hip04gic_irq_set_affinity,
 };
 
-const static struct gic_hw_operations gicv2_ops = {
-    .info                = &gicv2_info,
-    .secondary_init      = gicv2_secondary_cpu_init,
-    .save_state          = gicv2_save_state,
-    .restore_state       = gicv2_restore_state,
-    .dump_state          = gicv2_dump_state,
-    .gicv_setup          = gicv2v_setup,
-    .gic_host_irq_type   = &gicv2_host_irq_type,
-    .gic_guest_irq_type  = &gicv2_guest_irq_type,
-    .eoi_irq             = gicv2_eoi_irq,
-    .deactivate_irq      = gicv2_dir_irq,
-    .read_irq            = gicv2_read_irq,
-    .set_irq_properties  = gicv2_set_irq_properties,
-    .send_SGI            = gicv2_send_SGI,
-    .disable_interface   = gicv2_disable_interface,
-    .update_lr           = gicv2_update_lr,
-    .update_hcr_status   = gicv2_hcr_status,
-    .clear_lr            = gicv2_clear_lr,
-    .read_lr             = gicv2_read_lr,
-    .write_lr            = gicv2_write_lr,
-    .read_vmcr_priority  = gicv2_read_vmcr_priority,
-    .read_apr            = gicv2_read_apr,
-    .make_dt_node        = gicv2_make_dt_node,
+const static struct gic_hw_operations hip04gic_ops = {
+    .info                = &hip04gic_info,
+    .secondary_init      = hip04gic_secondary_cpu_init,
+    .save_state          = hip04gic_save_state,
+    .restore_state       = hip04gic_restore_state,
+    .dump_state          = hip04gic_dump_state,
+    .gicv_setup          = hip04gicv_setup,
+    .gic_host_irq_type   = &hip04gic_host_irq_type,
+    .gic_guest_irq_type  = &hip04gic_guest_irq_type,
+    .eoi_irq             = hip04gic_eoi_irq,
+    .deactivate_irq      = hip04gic_dir_irq,
+    .read_irq            = hip04gic_read_irq,
+    .set_irq_properties  = hip04gic_set_irq_properties,
+    .send_SGI            = hip04gic_send_SGI,
+    .disable_interface   = hip04gic_disable_interface,
+    .update_lr           = hip04gic_update_lr,
+    .update_hcr_status   = hip04gic_hcr_status,
+    .clear_lr            = hip04gic_clear_lr,
+    .read_lr             = hip04gic_read_lr,
+    .write_lr            = hip04gic_write_lr,
+    .read_vmcr_priority  = hip04gic_read_vmcr_priority,
+    .read_apr            = hip04gic_read_apr,
+    .make_dt_node        = hip04gic_make_dt_node,
 };
 
 /* Set up the GIC */
-static int __init gicv2_init(struct dt_device_node *node, const void *data)
+static int __init hip04gic_init(struct dt_device_node *node, const void *data)
 {
     int res;
 
     dt_device_set_used_by(node, DOMID_XEN);
 
-    res = dt_device_get_address(node, 0, &gicv2.dbase, NULL);
-    if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) )
+    res = dt_device_get_address(node, 0, &hip04gic.dbase, NULL);
+    if ( res || !hip04gic.dbase || (hip04gic.dbase & ~PAGE_MASK) )
         panic("GICv2: Cannot find a valid address for the distributor");
 
-    res = dt_device_get_address(node, 1, &gicv2.cbase, NULL);
-    if ( res || !gicv2.cbase || (gicv2.cbase & ~PAGE_MASK) )
+    res = dt_device_get_address(node, 1, &hip04gic.cbase, NULL);
+    if ( res || !hip04gic.cbase || (hip04gic.cbase & ~PAGE_MASK) )
         panic("GICv2: Cannot find a valid address for the CPU");
 
-    res = dt_device_get_address(node, 2, &gicv2.hbase, NULL);
-    if ( res || !gicv2.hbase || (gicv2.hbase & ~PAGE_MASK) )
+    res = dt_device_get_address(node, 2, &hip04gic.hbase, NULL);
+    if ( res || !hip04gic.hbase || (hip04gic.hbase & ~PAGE_MASK) )
         panic("GICv2: Cannot find a valid address for the hypervisor");
 
-    res = dt_device_get_address(node, 3, &gicv2.vbase, NULL);
-    if ( res || !gicv2.vbase || (gicv2.vbase & ~PAGE_MASK) )
+    res = dt_device_get_address(node, 3, &hip04gic.vbase, NULL);
+    if ( res || !hip04gic.vbase || (hip04gic.vbase & ~PAGE_MASK) )
         panic("GICv2: Cannot find a valid address for the virtual CPU");
 
     res = platform_get_irq(node, 0);
     if ( res < 0 )
         panic("GICv2: Cannot find the maintenance IRQ");
-    gicv2_info.maintenance_irq = res;
+    hip04gic_info.maintenance_irq = res;
 
     /* Set the GIC as the primary interrupt controller */
     dt_interrupt_controller = node;
@@ -723,59 +730,57 @@ static int __init gicv2_init(struct dt_device_node *node, 
const void *data)
               "        gic_hyp_addr=%"PRIpaddr"\n"
               "        gic_vcpu_addr=%"PRIpaddr"\n"
               "        gic_maintenance_irq=%u\n",
-              gicv2.dbase, gicv2.cbase, gicv2.hbase, gicv2.vbase,
-              gicv2_info.maintenance_irq);
+              hip04gic.dbase, hip04gic.cbase, hip04gic.hbase, hip04gic.vbase,
+              hip04gic_info.maintenance_irq);
 
-    if ( (gicv2.dbase & ~PAGE_MASK) || (gicv2.cbase & ~PAGE_MASK) ||
-         (gicv2.hbase & ~PAGE_MASK) || (gicv2.vbase & ~PAGE_MASK) )
+    if ( (hip04gic.dbase & ~PAGE_MASK) || (hip04gic.cbase & ~PAGE_MASK) ||
+         (hip04gic.hbase & ~PAGE_MASK) || (hip04gic.vbase & ~PAGE_MASK) )
         panic("GICv2 interfaces not page aligned");
 
-    gicv2.map_dbase = ioremap_nocache(gicv2.dbase, PAGE_SIZE);
-    if ( !gicv2.map_dbase )
+    hip04gic.map_dbase = ioremap_nocache(hip04gic.dbase, PAGE_SIZE);
+    if ( !hip04gic.map_dbase )
         panic("GICv2: Failed to ioremap for GIC distributor\n");
 
-    gicv2.map_cbase[0] = ioremap_nocache(gicv2.cbase, PAGE_SIZE);
+    hip04gic.map_cbase[0] = ioremap_nocache(hip04gic.cbase, PAGE_SIZE);
 
     if ( platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
-        gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE * 0x10,
+        hip04gic.map_cbase[1] = ioremap_nocache(hip04gic.cbase + PAGE_SIZE * 
0x10,
                                            PAGE_SIZE);
     else
-        gicv2.map_cbase[1] = ioremap_nocache(gicv2.cbase + PAGE_SIZE, 
PAGE_SIZE);
+        hip04gic.map_cbase[1] = ioremap_nocache(hip04gic.cbase + PAGE_SIZE, 
PAGE_SIZE);
 
-    if ( !gicv2.map_cbase[0] || !gicv2.map_cbase[1] )
+    if ( !hip04gic.map_cbase[0] || !hip04gic.map_cbase[1] )
         panic("GICv2: Failed to ioremap for GIC CPU interface\n");
 
-    gicv2.map_hbase = ioremap_nocache(gicv2.hbase, PAGE_SIZE);
-    if ( !gicv2.map_hbase )
+    hip04gic.map_hbase = ioremap_nocache(hip04gic.hbase, PAGE_SIZE);
+    if ( !hip04gic.map_hbase )
         panic("GICv2: Failed to ioremap for GIC Virtual interface\n");
 
     /* Global settings: interrupt distributor */
-    spin_lock_init(&gicv2.lock);
-    spin_lock(&gicv2.lock);
+    spin_lock_init(&hip04gic.lock);
+    spin_lock(&hip04gic.lock);
 
-    gicv2_dist_init();
-    gicv2_cpu_init();
-    gicv2_hyp_init();
+    hip04gic_dist_init();
+    hip04gic_cpu_init();
+    hip04gic_hyp_init();
 
-    spin_unlock(&gicv2.lock);
+    spin_unlock(&hip04gic.lock);
 
-    gicv2_info.hw_version = GIC_V2;
-    register_gic_ops(&gicv2_ops);
+    hip04gic_info.hw_version = GIC_V2;
+    register_gic_ops(&hip04gic_ops);
 
     return 0;
 }
 
-static const char * const gicv2_dt_compat[] __initconst =
+static const char * const hip04gic_dt_compat[] __initconst =
 {
-    DT_COMPAT_GIC_CORTEX_A15,
-    DT_COMPAT_GIC_CORTEX_A7,
-    DT_COMPAT_GIC_400,
+    DT_COMPAT_GIC_HIP04,
     NULL
 };
 
-DT_DEVICE_START(gicv2, "GICv2:", DEVICE_GIC)
-        .compatible = gicv2_dt_compat,
-        .init = gicv2_init,
+DT_DEVICE_START(hip04gic, "GIC-HIP04:", DEVICE_GIC)
+        .compatible = hip04gic_dt_compat,
+        .init = hip04gic_init,
 DT_DEVICE_END
 
 /*
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 390c8b0..e4512a8 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -565,12 +565,13 @@ static void do_sgi(struct cpu_user_regs *regs, enum 
gic_sgi sgi)
 void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
 {
     unsigned int irq;
+    unsigned int max_irq = gic_hw_ops->info->nr_lines;
 
     do  {
         /* Reading IRQ will ACK it */
         irq = gic_hw_ops->read_irq();
 
-        if ( likely(irq >= 16 && irq < 1021) )
+        if ( likely(irq >= 16 && irq < max_irq) )
         {
             local_irq_enable();
             do_IRQ(regs, irq, is_fiq);
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 187dc46..a36f486 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -160,6 +160,10 @@
                         DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_CORTEX_A7), \
                         DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_400)
 
+#define DT_COMPAT_GIC_HIP04          "hisilicon,hip04-intc"
+
+#define DT_MATCH_GIC_HIP04 DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_HIP04)
+
 #define DT_COMPAT_GIC_V3             "arm,gic-v3"
 
 #define DT_MATCH_GIC_V3 DT_MATCH_COMPATIBLE(DT_COMPAT_GIC_V3)
-- 
1.9.1



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.