|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v8 3/4] 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;
- GICH APR and LR register offsets.
Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
Signed-off-by: Zoltan Kiss <zoltan.kiss@xxxxxxxxxx>
---
MAINTAINERS | 5 +
xen/arch/arm/Makefile | 1 +
xen/arch/arm/gic-hip04.c | 396 ++++++++++++++++++++++++-----------------------
3 files changed, 209 insertions(+), 193 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0f04742..b17aab1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -138,6 +138,11 @@ F: xen/drivers/char/omap-uart.c
F: xen/drivers/char/pl011.c
F: xen/drivers/passthrough/arm/
+HISILICON HIP04 SUPPORT
+M: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
+S: Supported
+F: xen/arch/arm/git-hip04.c
+
CPU POOLS
M: Juergen Gross <jgross@xxxxxxxx>
S: Supported
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 41aba2e..935999e 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -12,6 +12,7 @@ obj-y += domctl.o
obj-y += sysctl.o
obj-y += domain_build.o
obj-y += gic.o gic-v2.o
+obj-$(CONFIG_ARM_32) += gic-hip04.o
obj-$(CONFIG_ARM_64) += gic-v3.o
obj-y += io.o
obj-y += irq.o
diff --git a/xen/arch/arm/gic-hip04.c b/xen/arch/arm/gic-hip04.c
index 20cdbc9..94abdc4 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,69 @@ 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
+
+#define HIP04_GICH_APR 0x70
+#define HIP04_GICH_LR 0x80
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 +150,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,58 +158,58 @@ 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++ )
- v->arch.gic.v2.lr[i] = readl_gich(GICH_LR + i * 4);
+ for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
+ v->arch.gic.v2.lr[i] = readl_gich(HIP04_GICH_LR + i * 4);
- v->arch.gic.v2.apr = readl_gich(GICH_APR);
+ v->arch.gic.v2.apr = readl_gich(HIP04_GICH_APR);
v->arch.gic.v2.vmcr = readl_gich(GICH_VMCR);
/* Disable until next VCPU scheduled */
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++ )
- writel_gich(v->arch.gic.v2.lr[i], GICH_LR + i * 4);
+ for ( i = 0; i < hip04gic_info.nr_lrs; i++ )
+ writel_gich(v->arch.gic.v2.lr[i], HIP04_GICH_LR + i * 4);
- writel_gich(v->arch.gic.v2.apr, GICH_APR);
+ writel_gich(v->arch.gic.v2.apr, HIP04_GICH_APR);
writel_gich(v->arch.gic.v2.vmcr, GICH_VMCR);
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));
+ readl_gich(HIP04_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 +218,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, actual, 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));
@@ -232,7 +243,7 @@ static void gicv2_set_irq_properties(struct irq_desc *desc,
actual = readl_gicd(GICD_ICFGR + (irq / 16) * 4);
if ( ( cfg & edgebit ) ^ ( actual & edgebit ) )
{
- printk(XENLOG_WARNING "GICv2: WARNING: "
+ printk(XENLOG_WARNING "GIC-HIP04: WARNING: "
"CPU%d: Failed to configure IRQ%u as %s-triggered. "
"H/w forces to %s-triggered.\n",
smp_processor_id(), desc->irq,
@@ -244,62 +255,61 @@ static void gicv2_set_irq_properties(struct irq_desc
*desc,
}
/* 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);
- 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 = 32 * ((type & GICD_TYPE_LINES) + 1);
+ gic_cpus = 16;
+ printk("GIC-HIP04: %d lines, %d cpu%s%s (IID %8.8x).\n",
+ 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
@@ -328,41 +338,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;
@@ -378,9 +388,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:
@@ -389,20 +399,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) |
@@ -419,15 +429,15 @@ static void gicv2_update_lr(int lr, const struct
pending_irq *p,
<< GICH_V2_LR_PHYSICAL_SHIFT);
}
- writel_gich(lr_reg, GICH_LR + lr * 4);
+ writel_gich(lr_reg, HIP04_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);
+ writel_gich(0, HIP04_GICH_LR + lr * 4);
}
-static int gicv2v_setup(struct domain *d)
+static int hip04gicv_setup(struct domain *d)
{
int ret;
@@ -437,8 +447,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
{
@@ -454,25 +464,25 @@ 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;
- lrv = readl_gich(GICH_LR + lr * 4);
+ lrv = readl_gich(HIP04_GICH_LR + lr * 4);
lr_reg->pirq = (lrv >> GICH_V2_LR_PHYSICAL_SHIFT) &
GICH_V2_LR_PHYSICAL_MASK;
lr_reg->virq = (lrv >> GICH_V2_LR_VIRTUAL_SHIFT) & GICH_V2_LR_VIRTUAL_MASK;
lr_reg->priority = (lrv >> GICH_V2_LR_PRIORITY_SHIFT) &
GICH_V2_LR_PRIORITY_MASK;
@@ -481,7 +491,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;
@@ -495,10 +505,10 @@ static void gicv2_write_lr(int lr, const struct gic_lr
*lr_reg)
<< GICH_V2_LR_HW_SHIFT) |
((uint32_t)(lr_reg->grp & GICH_V2_LR_GRP_MASK) <<
GICH_V2_LR_GRP_SHIFT) );
- writel_gich(lrv, GICH_LR + lr * 4);
+ writel_gich(lrv, HIP04_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);
@@ -510,95 +520,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);
+ return readl_gich(HIP04_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;
@@ -652,143 +662,143 @@ 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) )
- panic("GICv2: Cannot find a valid address for the distributor");
+ res = dt_device_get_address(node, 0, &hip04gic.dbase, NULL);
+ if ( res || !hip04gic.dbase || (hip04gic.dbase & ~PAGE_MASK) )
+ panic("GIC-HIP04: 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) )
- panic("GICv2: Cannot find a valid address for the CPU");
+ res = dt_device_get_address(node, 1, &hip04gic.cbase, NULL);
+ if ( res || !hip04gic.cbase || (hip04gic.cbase & ~PAGE_MASK) )
+ panic("GIC-HIP04: 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) )
- panic("GICv2: Cannot find a valid address for the hypervisor");
+ res = dt_device_get_address(node, 2, &hip04gic.hbase, NULL);
+ if ( res || !hip04gic.hbase || (hip04gic.hbase & ~PAGE_MASK) )
+ panic("GIC-HIP04: 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) )
- panic("GICv2: Cannot find a valid address for the virtual CPU");
+ res = dt_device_get_address(node, 3, &hip04gic.vbase, NULL);
+ if ( res || !hip04gic.vbase || (hip04gic.vbase & ~PAGE_MASK) )
+ panic("GIC-HIP04: 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;
+ panic("GIC-HIP04: Cannot find the maintenance IRQ");
+ hip04gic_info.maintenance_irq = res;
/* Set the GIC as the primary interrupt controller */
dt_interrupt_controller = node;
/* TODO: Add check on distributor, cpu size */
- printk("GICv2 initialization:\n"
+ printk("GIC-HIP04 initialization:\n"
" gic_dist_addr=%"PRIpaddr"\n"
" gic_cpu_addr=%"PRIpaddr"\n"
" 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) )
- panic("GICv2 interfaces not page aligned");
+ if ( (hip04gic.dbase & ~PAGE_MASK) || (hip04gic.cbase & ~PAGE_MASK) ||
+ (hip04gic.hbase & ~PAGE_MASK) || (hip04gic.vbase & ~PAGE_MASK) )
+ panic("GIC-HIP04 interfaces not page aligned");
- gicv2.map_dbase = ioremap_nocache(gicv2.dbase, PAGE_SIZE);
- if ( !gicv2.map_dbase )
- panic("GICv2: Failed to ioremap for GIC distributor\n");
+ hip04gic.map_dbase = ioremap_nocache(hip04gic.dbase, PAGE_SIZE);
+ if ( !hip04gic.map_dbase )
+ panic("GIC-HIP04: 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] )
- panic("GICv2: Failed to ioremap for GIC CPU interface\n");
+ if ( !hip04gic.map_cbase[0] || !hip04gic.map_cbase[1] )
+ panic("GIC-HIP04: Failed to ioremap for GIC CPU interface\n");
- gicv2.map_hbase = ioremap_nocache(gicv2.hbase, PAGE_SIZE);
- if ( !gicv2.map_hbase )
- panic("GICv2: Failed to ioremap for GIC Virtual interface\n");
+ hip04gic.map_hbase = ioremap_nocache(hip04gic.hbase, PAGE_SIZE);
+ if ( !hip04gic.map_hbase )
+ panic("GIC-HIP04: 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 struct dt_device_match gicv2_dt_match[] __initconst =
+static const struct dt_device_match hip04gic_dt_match[] __initconst =
{
- DT_MATCH_GIC_V2,
+ DT_MATCH_COMPATIBLE("hisilicon,hip04-intc"),
{ /* sentinel */ },
};
-DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
- .dt_match = gicv2_dt_match,
- .init = gicv2_init,
+DT_DEVICE_START(hip04gic, "GIC-HIP04", DEVICE_GIC)
+ .dt_match = hip04gic_dt_match,
+ .init = hip04gic_init,
DT_DEVICE_END
/*
--
1.9.1
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |