Message ID | 1454418784-28245-1-git-send-email-zoltan.kiss@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, 2016-02-02 at 13:13 +0000, Zoltan Kiss wrote: > This platform is no longer actively used, but it makes GICv2 development > harder. > > Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org> Thanks, I appreciate the proactive removal of no-longer supported platforms. I was going to ask you to confirm that you were still part of Huawei while on secondment to Linaro, but I see you have CCd that other hat of yours as well, which is good enough for me. Hence: Acked-by: Ian Campbell <ian.campbell@citrix.com> and applied. I don't see anything obvious in the wiki / docs which would need updating/deleting, if you know of anything please could you either update or let us know. Thanks, Ian. > --- > diff --git a/MAINTAINERS b/MAINTAINERS > index 7c1bf82..12f147c 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -177,11 +177,6 @@ S: Supported > F: xen/arch/x86/debug.c > F: tools/debugger/gdbsx/ > > -HISILICON HIP04 SUPPORT > -M: Zoltan Kiss <zoltan.kiss@huawei.com> > -S: Supported > -F: xen/arch/arm/gic-hip04.c > - > INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) > M: Gang Wei <gang.wei@intel.com> > M: Shane Wang <shane.wang@intel.com> > diff --git a/docs/misc/arm/early-printk.txt b/docs/misc/arm/early- > printk.txt > index 7e03955..41b528b 100644 > --- a/docs/misc/arm/early-printk.txt > +++ b/docs/misc/arm/early-printk.txt > @@ -37,7 +37,6 @@ the name of the machine: > - dra7: printk with 8250 on DRA7 platform > - exynos5250: printk with the second UART > - fastmodel: printk on ARM Fastmodel software emulators > - - hip04-d01: printk with 8250 on HiSilicon Hip-04 D01 > - juno: printk with pl011 on Juno platform > - lager: printk with SCIF0 on Renesas R-Car H2 processors > - midway: printk with the pl011 on Calxeda Midway processors > diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile > index 2f050f5..6a58a41 100644 > --- a/xen/arch/arm/Makefile > +++ b/xen/arch/arm/Makefile > @@ -12,7 +12,6 @@ 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_HAS_GICV3) += gic-v3.o > obj-y += io.o > obj-y += irq.o > diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk > index 4947e64..d6bbe7c 100644 > --- a/xen/arch/arm/Rules.mk > +++ b/xen/arch/arm/Rules.mk > @@ -42,7 +42,6 @@ EARLY_PRINTK_brcm := 8250,0xF040AB00,2 > EARLY_PRINTK_dra7 := 8250,0x4806A000,2 > EARLY_PRINTK_fastmodel := pl011,0x1c090000,115200 > EARLY_PRINTK_exynos5250 := exynos4210,0x12c20000 > -EARLY_PRINTK_hip04-d01 := 8250,0xE4007000,2 > EARLY_PRINTK_juno := pl011,0x7ff80000 > EARLY_PRINTK_lager := scif,0xe6e60000 > EARLY_PRINTK_midway := pl011,0xfff36000 > diff --git a/xen/arch/arm/gic-hip04.c b/xen/arch/arm/gic-hip04.c > deleted file mode 100644 > index a42cf24..0000000 > --- a/xen/arch/arm/gic-hip04.c > +++ /dev/null > @@ -1,757 +0,0 @@ > -/* > - * xen/arch/arm/gic-hip04.c > - * > - * Generic Interrupt Controller for HiSilicon Hip04 platform > - * Based heavily on gic-v2.c (id > 3bcf563fec26378f7f4cf1e2ad0d4d5b3f341919) > - * > - * Tim Deegan <tim@xen.org> > - * Copyright (c) 2011 Citrix Systems. > - * > - * This program is free software; you can redistribute it and/or modify > - * it under the terms of the GNU General Public License as published by > - * the Free Software Foundation; either version 2 of the License, or > - * (at your option) any later version. > - * > - * This program is distributed in the hope that it will be useful, > - * but WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > - * GNU General Public License for more details. > - */ > - > -#include <xen/config.h> > -#include <xen/lib.h> > -#include <xen/init.h> > -#include <xen/mm.h> > -#include <xen/irq.h> > -#include <xen/sched.h> > -#include <xen/errno.h> > -#include <xen/softirq.h> > -#include <xen/list.h> > -#include <xen/device_tree.h> > -#include <xen/libfdt/libfdt.h> > -#include <xen/sizes.h> > -#include <asm/p2m.h> > -#include <asm/domain.h> > -#include <asm/platform.h> > -#include <asm/device.h> > - > -#include <asm/io.h> > -#include <asm/gic.h> > - > -/* > - * LR register definitions are GIC v2 specific. > - * Moved these definitions from header file to here > - */ > -#define GICH_V2_LR_VIRTUAL_MASK 0x3ff > -#define GICH_V2_LR_VIRTUAL_SHIFT 0 > -#define GICH_V2_LR_PHYSICAL_MASK 0x3ff > -#define GICH_V2_LR_PHYSICAL_SHIFT 10 > -#define GICH_V2_LR_STATE_MASK 0x3 > -#define GICH_V2_LR_STATE_SHIFT 28 > -#define GICH_V2_LR_PRIORITY_SHIFT 23 > -#define GICH_V2_LR_PRIORITY_MASK 0x1f > -#define GICH_V2_LR_HW_SHIFT 31 > -#define GICH_V2_LR_HW_MASK 0x1 > -#define GICH_V2_LR_GRP_SHIFT 30 > -#define GICH_V2_LR_GRP_MASK 0x1 > -#define GICH_V2_LR_MAINTENANCE_IRQ (1<<19) > -#define GICH_V2_LR_GRP1 (1<<30) > -#define GICH_V2_LR_HW (1<<31) > -#define GICH_V2_LR_CPUID_SHIFT 9 > -#define GICH_V2_VTR_NRLRGS 0x3f > - > -#define GICH_V2_VMCR_PRIORITY_MASK 0x1f > -#define GICH_V2_VMCR_PRIORITY_SHIFT 27 > - > -/* Global state */ > -static struct { > - void __iomem * map_dbase; /* IO mapped Address of distributor > registers */ > - void __iomem * map_cbase[2]; /* IO mapped Address of CPU interface > registers */ > - void __iomem * map_hbase; /* IO Address of virtual interface > registers */ > - spinlock_t lock; > -} gicv2; > - > -static struct gic_info gicv2_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(u16, gic_cpu_id); > - > -/* Maximum cpu interface per GIC */ > -#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); > -} > - > -static inline void writew_gicd(uint16_t val, unsigned int offset) > -{ > - writew_relaxed(val, gicv2.map_dbase + offset); > -} > - > -static inline void writel_gicd(uint32_t val, unsigned int offset) > -{ > - writel_relaxed(val, gicv2.map_dbase + offset); > -} > - > -static inline uint32_t readl_gicd(unsigned int offset) > -{ > - return readl_relaxed(gicv2.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); > -} > - > -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); > -} > - > -static inline void writel_gich(uint32_t val, unsigned int offset) > -{ > - writel_relaxed(val, gicv2.map_hbase + offset); > -} > - > -static inline uint32_t readl_gich(int unsigned offset) > -{ > - return readl_relaxed(gicv2.map_hbase + offset); > -} > - > -static unsigned int hip04gic_cpu_mask(const cpumask_t *cpumask) > -{ > - unsigned int cpu; > - unsigned int mask = 0; > - cpumask_t possible_mask; > - > - cpumask_and(&possible_mask, cpumask, &cpu_possible_map); > - for_each_cpu( cpu, &possible_mask ) > - { > - ASSERT(cpu < NR_GIC_CPU_IF); > - mask |= per_cpu(gic_cpu_id, cpu); > - } > - > - return mask; > -} > - > -static void hip04gic_save_state(struct vcpu *v) > -{ > - int i; > - > - /* No need for spinlocks here because interrupts are disabled around > - * 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(HIP04_GICH_LR + i * 4); > - > - 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 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], HIP04_GICH_LR + i * 4); > - > - 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 hip04gic_dump_state(const struct vcpu *v) > -{ > - int i; > - > - if ( v == current ) > - { > - for ( i = 0; i < gicv2_info.nr_lrs; i++ ) > - printk(" HW_LR[%d]=%x\n", i, > - readl_gich(HIP04_GICH_LR + i * 4)); > - } > - else > - { > - for ( i = 0; i < gicv2_info.nr_lrs; i++ ) > - printk(" VCPU_LR[%d]=%x\n", i, v->arch.gic.v2.lr[i]); > - } > -} > - > -static void hip04gic_eoi_irq(struct irq_desc *irqd) > -{ > - int irq = irqd->irq; > - /* Lower the priority */ > - writel_gicc(irq, GICC_EOIR); > -} > - > -static void hip04gic_dir_irq(struct irq_desc *irqd) > -{ > - /* Deactivate */ > - writel_gicc(irqd->irq, GICC_DIR); > -} > - > -static unsigned int hip04gic_read_irq(void) > -{ > - return (readl_gicc(GICC_IAR) & GICC_IA_IRQ); > -} > - > -/* > - * needs to be called with a valid cpu_mask, ie each cpu in the mask has > - * already called gic_cpu_init > - */ > -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 = 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); > - /* Set edge / level */ > - cfg = readl_gicd(GICD_ICFGR + (irq / 16) * 4); > - edgebit = 2u << (2 * (irq % 16)); > - if ( type & DT_IRQ_TYPE_LEVEL_MASK ) > - cfg &= ~edgebit; > - else if ( type & DT_IRQ_TYPE_EDGE_BOTH ) > - cfg |= edgebit; > - writel_gicd(cfg, GICD_ICFGR + (irq / 16) * 4); > - > - actual = readl_gicd(GICD_ICFGR + (irq / 16) * 4); > - if ( ( cfg & edgebit ) ^ ( actual & edgebit ) ) > - { > - 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, > - cfg & edgebit ? "Edge" : "Level", > - actual & edgebit ? "Edge" : "Level"); > - desc->arch.type = actual & edgebit ? > - DT_IRQ_TYPE_EDGE_RISING : > - DT_IRQ_TYPE_LEVEL_HIGH; > - } > - > - /* Set target CPU mask (RAZ/WI on uniprocessor) */ > - writew_gicd(mask, GICD_ITARGETSR + irq * 2); > - /* Set priority */ > - writeb_gicd(priority, GICD_IPRIORITYR + irq); > - > - spin_unlock(&gicv2.lock); > -} > - > -static void __init hip04gic_dist_init(void) > -{ > - uint32_t type; > - uint32_t cpumask; > - uint32_t gic_cpus; > - unsigned int nr_lines; > - int i; > - > - cpumask = readl_gicd(GICD_ITARGETSR) & 0xffff; > - cpumask |= cpumask << 16; > - > - /* Disable the distributor */ > - writel_gicd(0, GICD_CTLR); > - > - type = readl_gicd(GICD_TYPER); > - nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1); > - gic_cpus = 16; > - printk("GIC-HIP04: %d lines, %d cpu%s%s (IID %8.8x).\n", > - 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 < nr_lines; i += 16 ) > - writel_gicd(0x0, GICD_ICFGR + (i / 16) * 4); > - > - /* Route all global IRQs to this CPU */ > - for ( i = 32; i < nr_lines; i += 2 ) > - writel_gicd(cpumask, GICD_ITARGETSR + (i / 2) * 4); > - > - /* Default priority for global interrupts */ > - for ( i = 32; i < 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 < nr_lines; i += 32 ) > - writel_gicd(~0x0, GICD_ICENABLER + (i / 32) * 4); > - > - /* Only 1020 interrupts are supported */ > - gicv2_info.nr_lines = min(1020U, nr_lines); > - > - /* Turn on the distributor */ > - writel_gicd(GICD_CTL_ENABLE, GICD_CTLR); > -} > - > -static void hip04gic_cpu_init(void) > -{ > - int i; > - > - 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 > - * be set up here with the other per-cpu state. */ > - writel_gicd(0xffff0000, GICD_ICENABLER); /* Disable all PPI */ > - writel_gicd(0x0000ffff, GICD_ISENABLER); /* Enable all SGI */ > - > - /* Set SGI priorities */ > - for ( i = 0; i < 16; i += 4 ) > - writel_gicd(GIC_PRI_IPI << 24 | GIC_PRI_IPI << 16 | > - GIC_PRI_IPI << 8 | GIC_PRI_IPI, > - GICD_IPRIORITYR + (i / 4) * 4); > - > - /* Set PPI priorities */ > - for ( i = 16; i < 32; i += 4 ) > - writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 | > - GIC_PRI_IRQ << 8 | GIC_PRI_IRQ, > - GICD_IPRIORITYR + (i / 4) * 4); > - > - /* Local settings: interface controller */ > - /* Don't mask by priority */ > - writel_gicc(0xff, GICC_PMR); > - /* Finest granularity of priority */ > - writel_gicc(0x0, GICC_BPR); > - /* Turn on delivery */ > - writel_gicc(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC_CTLR); > -} > - > -static void hip04gic_cpu_disable(void) > -{ > - writel_gicc(0x0, GICC_CTLR); > -} > - > -static void 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; > -} > - > -static void hip04gic_hyp_disable(void) > -{ > - writel_gich(0, GICH_HCR); > -} > - > -static int hip04gic_secondary_cpu_init(void) > -{ > - spin_lock(&gicv2.lock); > - > - hip04gic_cpu_init(); > - hip04gic_hyp_init(); > - > - spin_unlock(&gicv2.lock); > - > - return 0; > -} > - > -static void hip04gic_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode > irqmode, > - const cpumask_t *cpu_mask) > -{ > - unsigned int mask = 0; > - cpumask_t online_mask; > - > - switch ( irqmode ) > - { > - case SGI_TARGET_OTHERS: > - writel_gicd(GICD_SGI_TARGET_OTHERS | sgi, GICD_SGIR); > - break; > - case SGI_TARGET_SELF: > - writel_gicd(GICD_SGI_TARGET_SELF | sgi, GICD_SGIR); > - break; > - case SGI_TARGET_LIST: > - cpumask_and(&online_mask, cpu_mask, &cpu_online_map); > - mask = hip04gic_cpu_mask(&online_mask); > - writel_gicd(GICD_SGI_TARGET_LIST | > - (mask << HIP04_GICD_SGI_TARGET_SHIFT) | sgi, > - GICD_SGIR); > - break; > - default: > - BUG(); > - } > -} > - > -/* Shut down the per-CPU GIC interface */ > -static void hip04gic_disable_interface(void) > -{ > - spin_lock(&gicv2.lock); > - hip04gic_cpu_disable(); > - hip04gic_hyp_disable(); > - spin_unlock(&gicv2.lock); > -} > - > -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 < 0); > - > - lr_reg = (((state & GICH_V2_LR_STATE_MASK) << > GICH_V2_LR_STATE_SHIFT) | > - ((GIC_PRI_TO_GUEST(p->priority) & > GICH_V2_LR_PRIORITY_MASK) > - << > GICH_V2_LR_PRIORITY_SHIFT) | > - ((p->irq & GICH_V2_LR_VIRTUAL_MASK) << > GICH_V2_LR_VIRTUAL_SHIFT)); > - > - if ( p->desc != NULL ) > - lr_reg |= GICH_V2_LR_HW | ((p->desc->irq & > GICH_V2_LR_PHYSICAL_MASK ) > - << GICH_V2_LR_PHYSICAL_SHIFT); > - > - writel_gich(lr_reg, HIP04_GICH_LR + lr * 4); > -} > - > -static void hip04gic_clear_lr(int lr) > -{ > - writel_gich(0, HIP04_GICH_LR + lr * 4); > -} > - > -static void hip04gic_read_lr(int lr, struct gic_lr *lr_reg) > -{ > - uint32_t lrv; > - > - 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; > - lr_reg->state = (lrv >> GICH_V2_LR_STATE_SHIFT) & > GICH_V2_LR_STATE_MASK; > - lr_reg->hw_status = (lrv >> GICH_V2_LR_HW_SHIFT) & > GICH_V2_LR_HW_MASK; > - lr_reg->grp = (lrv >> GICH_V2_LR_GRP_SHIFT) & > GICH_V2_LR_GRP_MASK; > -} > - > -static void hip04gic_write_lr(int lr, const struct gic_lr *lr_reg) > -{ > - uint32_t lrv = 0; > - > - lrv = ( ((lr_reg->pirq & GICH_V2_LR_PHYSICAL_MASK) << > GICH_V2_LR_PHYSICAL_SHIFT) | > - ((lr_reg->virq & GICH_V2_LR_VIRTUAL_MASK) << > GICH_V2_LR_VIRTUAL_SHIFT) | > - ((uint32_t)(lr_reg->priority & GICH_V2_LR_PRIORITY_MASK) > - << GICH_V2_LR_PRIORITY_SHIFT) | > - ((uint32_t)(lr_reg->state & GICH_V2_LR_STATE_MASK) > - << GICH_V2_LR_STATE_SHIFT) | > - ((uint32_t)(lr_reg->hw_status & GICH_V2_LR_HW_MASK) > - << GICH_V2_LR_HW_SHIFT) | > - ((uint32_t)(lr_reg->grp & GICH_V2_LR_GRP_MASK) << > GICH_V2_LR_GRP_SHIFT) ); > - > - writel_gich(lrv, HIP04_GICH_LR + lr * 4); > -} > - > -static void hip04gic_hcr_status(uint32_t flag, bool_t status) > -{ > - uint32_t hcr = readl_gich(GICH_HCR); > - > - if ( status ) > - hcr |= flag; > - else > - hcr &= (~flag); > - > - writel_gich(hcr, GICH_HCR); > -} > - > -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 hip04gic_read_apr(int apr_reg) > -{ > - return readl_gich(HIP04_GICH_APR); > -} > - > -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); > - 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); > -} > - > -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); > - /* Disable routing */ > - writel_gicd(1u << (irq % 32), GICD_ICENABLER + (irq / 32) * 4); > - set_bit(_IRQ_DISABLED, &desc->status); > - spin_unlock_irqrestore(&gicv2.lock, flags); > -} > - > -static unsigned int hip04gic_irq_startup(struct irq_desc *desc) > -{ > - hip04gic_irq_enable(desc); > - > - return 0; > -} > - > -static void hip04gic_irq_shutdown(struct irq_desc *desc) > -{ > - hip04gic_irq_disable(desc); > -} > - > -static void hip04gic_irq_ack(struct irq_desc *desc) > -{ > - /* No ACK -- reading IAR has done this for us */ > -} > - > -static void hip04gic_host_irq_end(struct irq_desc *desc) > -{ > - /* Lower the priority */ > - hip04gic_eoi_irq(desc); > - /* Deactivate */ > - hip04gic_dir_irq(desc); > -} > - > -static void hip04gic_guest_irq_end(struct irq_desc *desc) > -{ > - /* Lower the priority of the IRQ */ > - hip04gic_eoi_irq(desc); > - /* Deactivation happens in maintenance interrupt / via GICV */ > -} > - > -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); > - > - mask = hip04gic_cpu_mask(cpu_mask); > - > - /* Set target CPU mask (RAZ/WI on uniprocessor) */ > - writew_gicd(mask, GICD_ITARGETSR + desc->irq * 2); > - > - spin_unlock(&gicv2.lock); > -} > - > -static int hip04gic_make_hwdom_dt_node(const struct domain *d, > - const struct dt_device_node *gic, > - void *fdt) > -{ > - const void *compatible; > - u32 len; > - const __be32 *regs; > - int res = 0; > - > - /* > - * Replace compatibility string with a standard one. > - * dom0 will see a compatible GIC. This as GICC is compatible > - * with standard one and GICD (emulated by Xen) is compatible > - * to standard. Otherwise we should implement HIP04 GICD in > - * the virtual GIC. > - * This actually limit CPU number to 8 for dom0. > - */ > - compatible = DT_COMPAT_GIC_CORTEX_A15; > - len = strlen((char*) compatible) + 1; > - > - res = fdt_property(fdt, "compatible", compatible, len); > - if ( res ) > - return res; > - > - /* > - * DTB provides up to 4 regions to handle virtualization > - * (in order GICD, GICC, GICH and GICV interfaces) > - * however dom0 just needs GICD and GICC provided by Xen. > - */ > - regs = dt_get_property(gic, "reg", &len); > - if ( !regs ) > - { > - dprintk(XENLOG_ERR, "Can't find reg property for the gic > node\n"); > - return -FDT_ERR_XEN(ENOENT); > - } > - > - len = dt_cells_to_size(dt_n_addr_cells(gic) + dt_n_size_cells(gic)); > - len *= 2; > - > - res = fdt_property(fdt, "reg", regs, len); > - > - return res; > -} > - > -/* XXX different for level vs edge */ > -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 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, > -}; > - > -static int __init hip04gic_init(void) > -{ > - int res; > - paddr_t hbase, dbase, cbase, csize, vbase; > - const struct dt_device_node *node = gicv2_info.node; > - > - res = dt_device_get_address(node, 0, &dbase, NULL); > - if ( res ) > - panic("GIC-HIP04: Cannot find a valid address for the > distributor"); > - > - res = dt_device_get_address(node, 1, &cbase, &csize); > - if ( res ) > - panic("GIC-HIP04: Cannot find a valid address for the CPU"); > - > - res = dt_device_get_address(node, 2, &hbase, NULL); > - if ( res ) > - panic("GIC-HIP04: Cannot find a valid address for the > hypervisor"); > - > - res = dt_device_get_address(node, 3, &vbase, NULL); > - if ( res ) > - panic("GIC-HIP04: Cannot find a valid address for the virtual > CPU"); > - > - res = platform_get_irq(node, 0); > - if ( res < 0 ) > - panic("GIC-HIP04: Cannot find the maintenance IRQ"); > - gicv2_info.maintenance_irq = res; > - > - /* TODO: Add check on distributor, cpu size */ > - > - 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", > - dbase, cbase, hbase, vbase, > - gicv2_info.maintenance_irq); > - > - if ( (dbase & ~PAGE_MASK) || (cbase & ~PAGE_MASK) || > - (hbase & ~PAGE_MASK) || (vbase & ~PAGE_MASK) ) > - panic("GIC-HIP04 interfaces not page aligned"); > - > - gicv2.map_dbase = ioremap_nocache(dbase, PAGE_SIZE); > - if ( !gicv2.map_dbase ) > - panic("GIC-HIP04: Failed to ioremap for GIC distributor\n"); > - > - gicv2.map_cbase[0] = ioremap_nocache(cbase, PAGE_SIZE); > - gicv2.map_cbase[1] = ioremap_nocache(cbase + PAGE_SIZE, PAGE_SIZE); > - > - if ( !gicv2.map_cbase[0] || !gicv2.map_cbase[1] ) > - panic("GIC-HIP04: Failed to ioremap for GIC CPU interface\n"); > - > - gicv2.map_hbase = ioremap_nocache(hbase, PAGE_SIZE); > - if ( !gicv2.map_hbase ) > - panic("GIC-HIP04: Failed to ioremap for GIC Virtual > interface\n"); > - > - vgic_v2_setup_hw(dbase, cbase, csize, vbase, 0); > - > - /* Global settings: interrupt distributor */ > - spin_lock_init(&gicv2.lock); > - spin_lock(&gicv2.lock); > - > - hip04gic_dist_init(); > - hip04gic_cpu_init(); > - hip04gic_hyp_init(); > - > - spin_unlock(&gicv2.lock); > - > - return 0; > -} > - > -const static struct gic_hw_operations hip04gic_ops = { > - .info = &gicv2_info, > - .init = hip04gic_init, > - .secondary_init = hip04gic_secondary_cpu_init, > - .save_state = hip04gic_save_state, > - .restore_state = hip04gic_restore_state, > - .dump_state = hip04gic_dump_state, > - .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_hwdom_dt_node = hip04gic_make_hwdom_dt_node, > -}; > - > -/* Set up the GIC */ > -static int __init hip04gic_preinit(struct dt_device_node *node, > - const void *data) > -{ > - gicv2_info.hw_version = GIC_V2; > - gicv2_info.node = node; > - register_gic_ops(&hip04gic_ops); > - dt_irq_xlate = gic_irq_xlate; > - > - return 0; > -} > - > -static const struct dt_device_match hip04gic_dt_match[] __initconst = > -{ > - DT_MATCH_COMPATIBLE("hisilicon,hip04-intc"), > - { /* sentinel */ }, > -}; > - > -DT_DEVICE_START(hip04gic, "GIC-HIP04", DEVICE_GIC) > - .dt_match = hip04gic_dt_match, > - .init = hip04gic_preinit, > -DT_DEVICE_END > - > -/* > - * Local variables: > - * mode: C > - * c-file-style: "BSD" > - * c-basic-offset: 4 > - * indent-tabs-mode: nil > - * End: > - */ > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel
diff --git a/MAINTAINERS b/MAINTAINERS index 7c1bf82..12f147c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -177,11 +177,6 @@ S: Supported F: xen/arch/x86/debug.c F: tools/debugger/gdbsx/ -HISILICON HIP04 SUPPORT -M: Zoltan Kiss <zoltan.kiss@huawei.com> -S: Supported -F: xen/arch/arm/gic-hip04.c - INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) M: Gang Wei <gang.wei@intel.com> M: Shane Wang <shane.wang@intel.com> diff --git a/docs/misc/arm/early-printk.txt b/docs/misc/arm/early-printk.txt index 7e03955..41b528b 100644 --- a/docs/misc/arm/early-printk.txt +++ b/docs/misc/arm/early-printk.txt @@ -37,7 +37,6 @@ the name of the machine: - dra7: printk with 8250 on DRA7 platform - exynos5250: printk with the second UART - fastmodel: printk on ARM Fastmodel software emulators - - hip04-d01: printk with 8250 on HiSilicon Hip-04 D01 - juno: printk with pl011 on Juno platform - lager: printk with SCIF0 on Renesas R-Car H2 processors - midway: printk with the pl011 on Calxeda Midway processors diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 2f050f5..6a58a41 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -12,7 +12,6 @@ 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_HAS_GICV3) += gic-v3.o obj-y += io.o obj-y += irq.o diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk index 4947e64..d6bbe7c 100644 --- a/xen/arch/arm/Rules.mk +++ b/xen/arch/arm/Rules.mk @@ -42,7 +42,6 @@ EARLY_PRINTK_brcm := 8250,0xF040AB00,2 EARLY_PRINTK_dra7 := 8250,0x4806A000,2 EARLY_PRINTK_fastmodel := pl011,0x1c090000,115200 EARLY_PRINTK_exynos5250 := exynos4210,0x12c20000 -EARLY_PRINTK_hip04-d01 := 8250,0xE4007000,2 EARLY_PRINTK_juno := pl011,0x7ff80000 EARLY_PRINTK_lager := scif,0xe6e60000 EARLY_PRINTK_midway := pl011,0xfff36000 diff --git a/xen/arch/arm/gic-hip04.c b/xen/arch/arm/gic-hip04.c deleted file mode 100644 index a42cf24..0000000 --- a/xen/arch/arm/gic-hip04.c +++ /dev/null @@ -1,757 +0,0 @@ -/* - * xen/arch/arm/gic-hip04.c - * - * Generic Interrupt Controller for HiSilicon Hip04 platform - * Based heavily on gic-v2.c (id 3bcf563fec26378f7f4cf1e2ad0d4d5b3f341919) - * - * Tim Deegan <tim@xen.org> - * Copyright (c) 2011 Citrix Systems. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <xen/config.h> -#include <xen/lib.h> -#include <xen/init.h> -#include <xen/mm.h> -#include <xen/irq.h> -#include <xen/sched.h> -#include <xen/errno.h> -#include <xen/softirq.h> -#include <xen/list.h> -#include <xen/device_tree.h> -#include <xen/libfdt/libfdt.h> -#include <xen/sizes.h> -#include <asm/p2m.h> -#include <asm/domain.h> -#include <asm/platform.h> -#include <asm/device.h> - -#include <asm/io.h> -#include <asm/gic.h> - -/* - * LR register definitions are GIC v2 specific. - * Moved these definitions from header file to here - */ -#define GICH_V2_LR_VIRTUAL_MASK 0x3ff -#define GICH_V2_LR_VIRTUAL_SHIFT 0 -#define GICH_V2_LR_PHYSICAL_MASK 0x3ff -#define GICH_V2_LR_PHYSICAL_SHIFT 10 -#define GICH_V2_LR_STATE_MASK 0x3 -#define GICH_V2_LR_STATE_SHIFT 28 -#define GICH_V2_LR_PRIORITY_SHIFT 23 -#define GICH_V2_LR_PRIORITY_MASK 0x1f -#define GICH_V2_LR_HW_SHIFT 31 -#define GICH_V2_LR_HW_MASK 0x1 -#define GICH_V2_LR_GRP_SHIFT 30 -#define GICH_V2_LR_GRP_MASK 0x1 -#define GICH_V2_LR_MAINTENANCE_IRQ (1<<19) -#define GICH_V2_LR_GRP1 (1<<30) -#define GICH_V2_LR_HW (1<<31) -#define GICH_V2_LR_CPUID_SHIFT 9 -#define GICH_V2_VTR_NRLRGS 0x3f - -#define GICH_V2_VMCR_PRIORITY_MASK 0x1f -#define GICH_V2_VMCR_PRIORITY_SHIFT 27 - -/* Global state */ -static struct { - void __iomem * map_dbase; /* IO mapped Address of distributor registers */ - void __iomem * map_cbase[2]; /* IO mapped Address of CPU interface registers */ - void __iomem * map_hbase; /* IO Address of virtual interface registers */ - spinlock_t lock; -} gicv2; - -static struct gic_info gicv2_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(u16, gic_cpu_id); - -/* Maximum cpu interface per GIC */ -#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); -} - -static inline void writew_gicd(uint16_t val, unsigned int offset) -{ - writew_relaxed(val, gicv2.map_dbase + offset); -} - -static inline void writel_gicd(uint32_t val, unsigned int offset) -{ - writel_relaxed(val, gicv2.map_dbase + offset); -} - -static inline uint32_t readl_gicd(unsigned int offset) -{ - return readl_relaxed(gicv2.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); -} - -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); -} - -static inline void writel_gich(uint32_t val, unsigned int offset) -{ - writel_relaxed(val, gicv2.map_hbase + offset); -} - -static inline uint32_t readl_gich(int unsigned offset) -{ - return readl_relaxed(gicv2.map_hbase + offset); -} - -static unsigned int hip04gic_cpu_mask(const cpumask_t *cpumask) -{ - unsigned int cpu; - unsigned int mask = 0; - cpumask_t possible_mask; - - cpumask_and(&possible_mask, cpumask, &cpu_possible_map); - for_each_cpu( cpu, &possible_mask ) - { - ASSERT(cpu < NR_GIC_CPU_IF); - mask |= per_cpu(gic_cpu_id, cpu); - } - - return mask; -} - -static void hip04gic_save_state(struct vcpu *v) -{ - int i; - - /* No need for spinlocks here because interrupts are disabled around - * 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(HIP04_GICH_LR + i * 4); - - 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 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], HIP04_GICH_LR + i * 4); - - 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 hip04gic_dump_state(const struct vcpu *v) -{ - int i; - - if ( v == current ) - { - for ( i = 0; i < gicv2_info.nr_lrs; i++ ) - printk(" HW_LR[%d]=%x\n", i, - readl_gich(HIP04_GICH_LR + i * 4)); - } - else - { - for ( i = 0; i < gicv2_info.nr_lrs; i++ ) - printk(" VCPU_LR[%d]=%x\n", i, v->arch.gic.v2.lr[i]); - } -} - -static void hip04gic_eoi_irq(struct irq_desc *irqd) -{ - int irq = irqd->irq; - /* Lower the priority */ - writel_gicc(irq, GICC_EOIR); -} - -static void hip04gic_dir_irq(struct irq_desc *irqd) -{ - /* Deactivate */ - writel_gicc(irqd->irq, GICC_DIR); -} - -static unsigned int hip04gic_read_irq(void) -{ - return (readl_gicc(GICC_IAR) & GICC_IA_IRQ); -} - -/* - * needs to be called with a valid cpu_mask, ie each cpu in the mask has - * already called gic_cpu_init - */ -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 = 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); - /* Set edge / level */ - cfg = readl_gicd(GICD_ICFGR + (irq / 16) * 4); - edgebit = 2u << (2 * (irq % 16)); - if ( type & DT_IRQ_TYPE_LEVEL_MASK ) - cfg &= ~edgebit; - else if ( type & DT_IRQ_TYPE_EDGE_BOTH ) - cfg |= edgebit; - writel_gicd(cfg, GICD_ICFGR + (irq / 16) * 4); - - actual = readl_gicd(GICD_ICFGR + (irq / 16) * 4); - if ( ( cfg & edgebit ) ^ ( actual & edgebit ) ) - { - 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, - cfg & edgebit ? "Edge" : "Level", - actual & edgebit ? "Edge" : "Level"); - desc->arch.type = actual & edgebit ? - DT_IRQ_TYPE_EDGE_RISING : - DT_IRQ_TYPE_LEVEL_HIGH; - } - - /* Set target CPU mask (RAZ/WI on uniprocessor) */ - writew_gicd(mask, GICD_ITARGETSR + irq * 2); - /* Set priority */ - writeb_gicd(priority, GICD_IPRIORITYR + irq); - - spin_unlock(&gicv2.lock); -} - -static void __init hip04gic_dist_init(void) -{ - uint32_t type; - uint32_t cpumask; - uint32_t gic_cpus; - unsigned int nr_lines; - int i; - - cpumask = readl_gicd(GICD_ITARGETSR) & 0xffff; - cpumask |= cpumask << 16; - - /* Disable the distributor */ - writel_gicd(0, GICD_CTLR); - - type = readl_gicd(GICD_TYPER); - nr_lines = 32 * ((type & GICD_TYPE_LINES) + 1); - gic_cpus = 16; - printk("GIC-HIP04: %d lines, %d cpu%s%s (IID %8.8x).\n", - 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 < nr_lines; i += 16 ) - writel_gicd(0x0, GICD_ICFGR + (i / 16) * 4); - - /* Route all global IRQs to this CPU */ - for ( i = 32; i < nr_lines; i += 2 ) - writel_gicd(cpumask, GICD_ITARGETSR + (i / 2) * 4); - - /* Default priority for global interrupts */ - for ( i = 32; i < 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 < nr_lines; i += 32 ) - writel_gicd(~0x0, GICD_ICENABLER + (i / 32) * 4); - - /* Only 1020 interrupts are supported */ - gicv2_info.nr_lines = min(1020U, nr_lines); - - /* Turn on the distributor */ - writel_gicd(GICD_CTL_ENABLE, GICD_CTLR); -} - -static void hip04gic_cpu_init(void) -{ - int i; - - 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 - * be set up here with the other per-cpu state. */ - writel_gicd(0xffff0000, GICD_ICENABLER); /* Disable all PPI */ - writel_gicd(0x0000ffff, GICD_ISENABLER); /* Enable all SGI */ - - /* Set SGI priorities */ - for ( i = 0; i < 16; i += 4 ) - writel_gicd(GIC_PRI_IPI << 24 | GIC_PRI_IPI << 16 | - GIC_PRI_IPI << 8 | GIC_PRI_IPI, - GICD_IPRIORITYR + (i / 4) * 4); - - /* Set PPI priorities */ - for ( i = 16; i < 32; i += 4 ) - writel_gicd(GIC_PRI_IRQ << 24 | GIC_PRI_IRQ << 16 | - GIC_PRI_IRQ << 8 | GIC_PRI_IRQ, - GICD_IPRIORITYR + (i / 4) * 4); - - /* Local settings: interface controller */ - /* Don't mask by priority */ - writel_gicc(0xff, GICC_PMR); - /* Finest granularity of priority */ - writel_gicc(0x0, GICC_BPR); - /* Turn on delivery */ - writel_gicc(GICC_CTL_ENABLE|GICC_CTL_EOI, GICC_CTLR); -} - -static void hip04gic_cpu_disable(void) -{ - writel_gicc(0x0, GICC_CTLR); -} - -static void 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; -} - -static void hip04gic_hyp_disable(void) -{ - writel_gich(0, GICH_HCR); -} - -static int hip04gic_secondary_cpu_init(void) -{ - spin_lock(&gicv2.lock); - - hip04gic_cpu_init(); - hip04gic_hyp_init(); - - spin_unlock(&gicv2.lock); - - return 0; -} - -static void hip04gic_send_SGI(enum gic_sgi sgi, enum gic_sgi_mode irqmode, - const cpumask_t *cpu_mask) -{ - unsigned int mask = 0; - cpumask_t online_mask; - - switch ( irqmode ) - { - case SGI_TARGET_OTHERS: - writel_gicd(GICD_SGI_TARGET_OTHERS | sgi, GICD_SGIR); - break; - case SGI_TARGET_SELF: - writel_gicd(GICD_SGI_TARGET_SELF | sgi, GICD_SGIR); - break; - case SGI_TARGET_LIST: - cpumask_and(&online_mask, cpu_mask, &cpu_online_map); - mask = hip04gic_cpu_mask(&online_mask); - writel_gicd(GICD_SGI_TARGET_LIST | - (mask << HIP04_GICD_SGI_TARGET_SHIFT) | sgi, - GICD_SGIR); - break; - default: - BUG(); - } -} - -/* Shut down the per-CPU GIC interface */ -static void hip04gic_disable_interface(void) -{ - spin_lock(&gicv2.lock); - hip04gic_cpu_disable(); - hip04gic_hyp_disable(); - spin_unlock(&gicv2.lock); -} - -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 < 0); - - lr_reg = (((state & GICH_V2_LR_STATE_MASK) << GICH_V2_LR_STATE_SHIFT) | - ((GIC_PRI_TO_GUEST(p->priority) & GICH_V2_LR_PRIORITY_MASK) - << GICH_V2_LR_PRIORITY_SHIFT) | - ((p->irq & GICH_V2_LR_VIRTUAL_MASK) << GICH_V2_LR_VIRTUAL_SHIFT)); - - if ( p->desc != NULL ) - lr_reg |= GICH_V2_LR_HW | ((p->desc->irq & GICH_V2_LR_PHYSICAL_MASK ) - << GICH_V2_LR_PHYSICAL_SHIFT); - - writel_gich(lr_reg, HIP04_GICH_LR + lr * 4); -} - -static void hip04gic_clear_lr(int lr) -{ - writel_gich(0, HIP04_GICH_LR + lr * 4); -} - -static void hip04gic_read_lr(int lr, struct gic_lr *lr_reg) -{ - uint32_t lrv; - - 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; - lr_reg->state = (lrv >> GICH_V2_LR_STATE_SHIFT) & GICH_V2_LR_STATE_MASK; - lr_reg->hw_status = (lrv >> GICH_V2_LR_HW_SHIFT) & GICH_V2_LR_HW_MASK; - lr_reg->grp = (lrv >> GICH_V2_LR_GRP_SHIFT) & GICH_V2_LR_GRP_MASK; -} - -static void hip04gic_write_lr(int lr, const struct gic_lr *lr_reg) -{ - uint32_t lrv = 0; - - lrv = ( ((lr_reg->pirq & GICH_V2_LR_PHYSICAL_MASK) << GICH_V2_LR_PHYSICAL_SHIFT) | - ((lr_reg->virq & GICH_V2_LR_VIRTUAL_MASK) << GICH_V2_LR_VIRTUAL_SHIFT) | - ((uint32_t)(lr_reg->priority & GICH_V2_LR_PRIORITY_MASK) - << GICH_V2_LR_PRIORITY_SHIFT) | - ((uint32_t)(lr_reg->state & GICH_V2_LR_STATE_MASK) - << GICH_V2_LR_STATE_SHIFT) | - ((uint32_t)(lr_reg->hw_status & GICH_V2_LR_HW_MASK) - << GICH_V2_LR_HW_SHIFT) | - ((uint32_t)(lr_reg->grp & GICH_V2_LR_GRP_MASK) << GICH_V2_LR_GRP_SHIFT) ); - - writel_gich(lrv, HIP04_GICH_LR + lr * 4); -} - -static void hip04gic_hcr_status(uint32_t flag, bool_t status) -{ - uint32_t hcr = readl_gich(GICH_HCR); - - if ( status ) - hcr |= flag; - else - hcr &= (~flag); - - writel_gich(hcr, GICH_HCR); -} - -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 hip04gic_read_apr(int apr_reg) -{ - return readl_gich(HIP04_GICH_APR); -} - -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); - 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); -} - -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); - /* Disable routing */ - writel_gicd(1u << (irq % 32), GICD_ICENABLER + (irq / 32) * 4); - set_bit(_IRQ_DISABLED, &desc->status); - spin_unlock_irqrestore(&gicv2.lock, flags); -} - -static unsigned int hip04gic_irq_startup(struct irq_desc *desc) -{ - hip04gic_irq_enable(desc); - - return 0; -} - -static void hip04gic_irq_shutdown(struct irq_desc *desc) -{ - hip04gic_irq_disable(desc); -} - -static void hip04gic_irq_ack(struct irq_desc *desc) -{ - /* No ACK -- reading IAR has done this for us */ -} - -static void hip04gic_host_irq_end(struct irq_desc *desc) -{ - /* Lower the priority */ - hip04gic_eoi_irq(desc); - /* Deactivate */ - hip04gic_dir_irq(desc); -} - -static void hip04gic_guest_irq_end(struct irq_desc *desc) -{ - /* Lower the priority of the IRQ */ - hip04gic_eoi_irq(desc); - /* Deactivation happens in maintenance interrupt / via GICV */ -} - -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); - - mask = hip04gic_cpu_mask(cpu_mask); - - /* Set target CPU mask (RAZ/WI on uniprocessor) */ - writew_gicd(mask, GICD_ITARGETSR + desc->irq * 2); - - spin_unlock(&gicv2.lock); -} - -static int hip04gic_make_hwdom_dt_node(const struct domain *d, - const struct dt_device_node *gic, - void *fdt) -{ - const void *compatible; - u32 len; - const __be32 *regs; - int res = 0; - - /* - * Replace compatibility string with a standard one. - * dom0 will see a compatible GIC. This as GICC is compatible - * with standard one and GICD (emulated by Xen) is compatible - * to standard. Otherwise we should implement HIP04 GICD in - * the virtual GIC. - * This actually limit CPU number to 8 for dom0. - */ - compatible = DT_COMPAT_GIC_CORTEX_A15; - len = strlen((char*) compatible) + 1; - - res = fdt_property(fdt, "compatible", compatible, len); - if ( res ) - return res; - - /* - * DTB provides up to 4 regions to handle virtualization - * (in order GICD, GICC, GICH and GICV interfaces) - * however dom0 just needs GICD and GICC provided by Xen. - */ - regs = dt_get_property(gic, "reg", &len); - if ( !regs ) - { - dprintk(XENLOG_ERR, "Can't find reg property for the gic node\n"); - return -FDT_ERR_XEN(ENOENT); - } - - len = dt_cells_to_size(dt_n_addr_cells(gic) + dt_n_size_cells(gic)); - len *= 2; - - res = fdt_property(fdt, "reg", regs, len); - - return res; -} - -/* XXX different for level vs edge */ -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 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, -}; - -static int __init hip04gic_init(void) -{ - int res; - paddr_t hbase, dbase, cbase, csize, vbase; - const struct dt_device_node *node = gicv2_info.node; - - res = dt_device_get_address(node, 0, &dbase, NULL); - if ( res ) - panic("GIC-HIP04: Cannot find a valid address for the distributor"); - - res = dt_device_get_address(node, 1, &cbase, &csize); - if ( res ) - panic("GIC-HIP04: Cannot find a valid address for the CPU"); - - res = dt_device_get_address(node, 2, &hbase, NULL); - if ( res ) - panic("GIC-HIP04: Cannot find a valid address for the hypervisor"); - - res = dt_device_get_address(node, 3, &vbase, NULL); - if ( res ) - panic("GIC-HIP04: Cannot find a valid address for the virtual CPU"); - - res = platform_get_irq(node, 0); - if ( res < 0 ) - panic("GIC-HIP04: Cannot find the maintenance IRQ"); - gicv2_info.maintenance_irq = res; - - /* TODO: Add check on distributor, cpu size */ - - 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", - dbase, cbase, hbase, vbase, - gicv2_info.maintenance_irq); - - if ( (dbase & ~PAGE_MASK) || (cbase & ~PAGE_MASK) || - (hbase & ~PAGE_MASK) || (vbase & ~PAGE_MASK) ) - panic("GIC-HIP04 interfaces not page aligned"); - - gicv2.map_dbase = ioremap_nocache(dbase, PAGE_SIZE); - if ( !gicv2.map_dbase ) - panic("GIC-HIP04: Failed to ioremap for GIC distributor\n"); - - gicv2.map_cbase[0] = ioremap_nocache(cbase, PAGE_SIZE); - gicv2.map_cbase[1] = ioremap_nocache(cbase + PAGE_SIZE, PAGE_SIZE); - - if ( !gicv2.map_cbase[0] || !gicv2.map_cbase[1] ) - panic("GIC-HIP04: Failed to ioremap for GIC CPU interface\n"); - - gicv2.map_hbase = ioremap_nocache(hbase, PAGE_SIZE); - if ( !gicv2.map_hbase ) - panic("GIC-HIP04: Failed to ioremap for GIC Virtual interface\n"); - - vgic_v2_setup_hw(dbase, cbase, csize, vbase, 0); - - /* Global settings: interrupt distributor */ - spin_lock_init(&gicv2.lock); - spin_lock(&gicv2.lock); - - hip04gic_dist_init(); - hip04gic_cpu_init(); - hip04gic_hyp_init(); - - spin_unlock(&gicv2.lock); - - return 0; -} - -const static struct gic_hw_operations hip04gic_ops = { - .info = &gicv2_info, - .init = hip04gic_init, - .secondary_init = hip04gic_secondary_cpu_init, - .save_state = hip04gic_save_state, - .restore_state = hip04gic_restore_state, - .dump_state = hip04gic_dump_state, - .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_hwdom_dt_node = hip04gic_make_hwdom_dt_node, -}; - -/* Set up the GIC */ -static int __init hip04gic_preinit(struct dt_device_node *node, - const void *data) -{ - gicv2_info.hw_version = GIC_V2; - gicv2_info.node = node; - register_gic_ops(&hip04gic_ops); - dt_irq_xlate = gic_irq_xlate; - - return 0; -} - -static const struct dt_device_match hip04gic_dt_match[] __initconst = -{ - DT_MATCH_COMPATIBLE("hisilicon,hip04-intc"), - { /* sentinel */ }, -}; - -DT_DEVICE_START(hip04gic, "GIC-HIP04", DEVICE_GIC) - .dt_match = hip04gic_dt_match, - .init = hip04gic_preinit, -DT_DEVICE_END - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - */
This platform is no longer actively used, but it makes GICv2 development harder. Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org> ---