/* * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h * * Copyright (C) 2016, Red Hat Inc, Andrew Jones * * This work is licensed under the terms of the GNU LGPL, version 2. */ #ifndef _ASMARM_GIC_V3_H_ #define _ASMARM_GIC_V3_H_ #ifndef _ASMARM_GIC_H_ #error Do not directly include . Include #endif /* * Distributor registers * * We expect to be run in Non-secure mode, thus we define the * group1 enable bits with respect to that view. */ #define GICD_CTLR_RWP (1U << 31) #define GICD_CTLR_ARE_NS (1U << 4) #define GICD_CTLR_ENABLE_G1A (1U << 1) #define GICD_CTLR_ENABLE_G1 (1U << 0) /* Re-Distributor registers, offsets from RD_base */ #define GICR_TYPER 0x0008 #define GICR_TYPER_LAST (1U << 4) /* Re-Distributor registers, offsets from SGI_base */ #define GICR_IGROUPR0 GICD_IGROUPR #define GICR_ISENABLER0 GICD_ISENABLER #define GICR_IPRIORITYR0 GICD_IPRIORITYR #define ICC_SGI1R_AFFINITY_1_SHIFT 16 #define ICC_SGI1R_AFFINITY_2_SHIFT 32 #define ICC_SGI1R_AFFINITY_3_SHIFT 48 #define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \ (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) #include #ifndef __ASSEMBLY__ #include #include #include #include #include #include struct gicv3_data { void *dist_base; void *redist_base[NR_CPUS]; unsigned int irq_nr; }; extern struct gicv3_data gicv3_data; #define gicv3_dist_base() (gicv3_data.dist_base) #define gicv3_redist_base() (gicv3_data.redist_base[smp_processor_id()]) #define gicv3_sgi_base() (gicv3_data.redist_base[smp_processor_id()] + SZ_64K) extern int gicv3_init(void); extern void gicv3_enable_defaults(void); extern u32 gicv3_read_iar(void); extern u32 gicv3_iar_irqnr(u32 iar); extern void gicv3_write_eoir(u32 irqstat); extern void gicv3_ipi_send_single(int irq, int cpu); extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest); extern void gicv3_set_redist_base(size_t stride); static inline void gicv3_do_wait_for_rwp(void *base) { int count = 100000; /* 1s */ while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) { if (!--count) { printf("GICv3: RWP timeout!\n"); abort(); } cpu_relax(); udelay(10); }; } static inline void gicv3_dist_wait_for_rwp(void) { gicv3_do_wait_for_rwp(gicv3_dist_base()); } static inline void gicv3_redist_wait_for_uwp(void) { /* * We can build on gic_do_wait_for_rwp, which uses GICD_ registers * because GICD_CTLR == GICR_CTLR and GICD_CTLR_RWP == GICR_CTLR_UWP */ gicv3_do_wait_for_rwp(gicv3_redist_base()); } static inline u32 mpidr_compress(u64 mpidr) { u64 compressed = mpidr & MPIDR_HWID_BITMASK; compressed = (((compressed >> 32) & 0xff) << 24) | compressed; return compressed; } static inline u64 mpidr_uncompress(u32 compressed) { u64 mpidr = ((u64)compressed >> 24) << 32; mpidr |= compressed & MPIDR_HWID_BITMASK; return mpidr; } #endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_H_ */