191a6c3ceSAndrew Jones /* 291a6c3ceSAndrew Jones * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h 391a6c3ceSAndrew Jones * 491a6c3ceSAndrew Jones * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 591a6c3ceSAndrew Jones * 691a6c3ceSAndrew Jones * This work is licensed under the terms of the GNU LGPL, version 2. 791a6c3ceSAndrew Jones */ 891a6c3ceSAndrew Jones #ifndef _ASMARM_GIC_V3_H_ 991a6c3ceSAndrew Jones #define _ASMARM_GIC_V3_H_ 1091a6c3ceSAndrew Jones 1191a6c3ceSAndrew Jones #ifndef _ASMARM_GIC_H_ 1291a6c3ceSAndrew Jones #error Do not directly include <asm/gic-v3.h>. Include <asm/gic.h> 1391a6c3ceSAndrew Jones #endif 1491a6c3ceSAndrew Jones 1591a6c3ceSAndrew Jones /* 1691a6c3ceSAndrew Jones * Distributor registers 1791a6c3ceSAndrew Jones * 1891a6c3ceSAndrew Jones * We expect to be run in Non-secure mode, thus we define the 1991a6c3ceSAndrew Jones * group1 enable bits with respect to that view. 2091a6c3ceSAndrew Jones */ 21d24709d3SEric Auger #define GICD_CTLR 0x0000 2291a6c3ceSAndrew Jones #define GICD_CTLR_RWP (1U << 31) 2391a6c3ceSAndrew Jones #define GICD_CTLR_ARE_NS (1U << 4) 2491a6c3ceSAndrew Jones #define GICD_CTLR_ENABLE_G1A (1U << 1) 2591a6c3ceSAndrew Jones #define GICD_CTLR_ENABLE_G1 (1U << 0) 2691a6c3ceSAndrew Jones 2791a6c3ceSAndrew Jones /* Re-Distributor registers, offsets from RD_base */ 2891a6c3ceSAndrew Jones #define GICR_TYPER 0x0008 2991a6c3ceSAndrew Jones 3091a6c3ceSAndrew Jones #define GICR_TYPER_LAST (1U << 4) 3191a6c3ceSAndrew Jones 3291a6c3ceSAndrew Jones /* Re-Distributor registers, offsets from SGI_base */ 3391a6c3ceSAndrew Jones #define GICR_IGROUPR0 GICD_IGROUPR 3491a6c3ceSAndrew Jones #define GICR_ISENABLER0 GICD_ISENABLER 3508ae0906SAlexandru Elisei #define GICR_ICENABLER0 GICD_ICENABLER 36401c09eaSZenghui Yu #define GICR_ISPENDR0 GICD_ISPENDR 37401c09eaSZenghui Yu #define GICR_ICPENDR0 GICD_ICPENDR 38401c09eaSZenghui Yu #define GICR_ISACTIVER0 GICD_ISACTIVER 39401c09eaSZenghui Yu #define GICR_ICACTIVER0 GICD_ICACTIVER 4091a6c3ceSAndrew Jones #define GICR_IPRIORITYR0 GICD_IPRIORITYR 4191a6c3ceSAndrew Jones 42d24709d3SEric Auger #define GICR_PROPBASER 0x0070 43d24709d3SEric Auger #define GICR_PENDBASER 0x0078 44d24709d3SEric Auger #define GICR_CTLR GICD_CTLR 45d24709d3SEric Auger #define GICR_CTLR_ENABLE_LPIS (1UL << 0) 46d24709d3SEric Auger 472e2d471dSAndrew Jones #define ICC_SGI1R_AFFINITY_1_SHIFT 16 482e2d471dSAndrew Jones #define ICC_SGI1R_AFFINITY_2_SHIFT 32 492e2d471dSAndrew Jones #define ICC_SGI1R_AFFINITY_3_SHIFT 48 502e2d471dSAndrew Jones #define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \ 512e2d471dSAndrew Jones (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) 522e2d471dSAndrew Jones 5305d1bb91SEric Auger #define GICR_PENDBASER_PTZ BIT_ULL(62) 5405d1bb91SEric Auger 5505d1bb91SEric Auger #define LPI_PROP_GROUP1 (1 << 1) 5605d1bb91SEric Auger #define LPI_PROP_ENABLED (1 << 0) 5705d1bb91SEric Auger #define LPI_PROP_DEFAULT_PRIO 0xa0 5805d1bb91SEric Auger #define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | LPI_PROP_ENABLED) 5905d1bb91SEric Auger 60*80374e12SEric Auger #define LPI_ID_BASE 8192 61*80374e12SEric Auger #define LPI(lpi) ((lpi) + LPI_ID_BASE) 62*80374e12SEric Auger #define LPI_OFFSET(intid) ((intid) - LPI_ID_BASE) 63*80374e12SEric Auger 6491a6c3ceSAndrew Jones #include <asm/arch_gicv3.h> 6591a6c3ceSAndrew Jones 6691a6c3ceSAndrew Jones #ifndef __ASSEMBLY__ 6791a6c3ceSAndrew Jones #include <asm/setup.h> 6891a6c3ceSAndrew Jones #include <asm/processor.h> 6991a6c3ceSAndrew Jones #include <asm/delay.h> 702e2d471dSAndrew Jones #include <asm/cpumask.h> 7191a6c3ceSAndrew Jones #include <asm/smp.h> 7291a6c3ceSAndrew Jones #include <asm/io.h> 7391a6c3ceSAndrew Jones 74a5a2d35cSAndrew Jones #define GICV3_NR_REDISTS 8 75a5a2d35cSAndrew Jones 7691a6c3ceSAndrew Jones struct gicv3_data { 7791a6c3ceSAndrew Jones void *dist_base; 78a5a2d35cSAndrew Jones void *redist_bases[GICV3_NR_REDISTS]; 7991a6c3ceSAndrew Jones void *redist_base[NR_CPUS]; 8005d1bb91SEric Auger u8 *lpi_prop; 8105d1bb91SEric Auger void *lpi_pend[NR_CPUS]; 8291a6c3ceSAndrew Jones unsigned int irq_nr; 8391a6c3ceSAndrew Jones }; 8491a6c3ceSAndrew Jones extern struct gicv3_data gicv3_data; 8591a6c3ceSAndrew Jones 8691a6c3ceSAndrew Jones #define gicv3_dist_base() (gicv3_data.dist_base) 8791a6c3ceSAndrew Jones #define gicv3_redist_base() (gicv3_data.redist_base[smp_processor_id()]) 8891a6c3ceSAndrew Jones #define gicv3_sgi_base() (gicv3_data.redist_base[smp_processor_id()] + SZ_64K) 8991a6c3ceSAndrew Jones 9091a6c3ceSAndrew Jones extern int gicv3_init(void); 9191a6c3ceSAndrew Jones extern void gicv3_enable_defaults(void); 922e2d471dSAndrew Jones extern u32 gicv3_read_iar(void); 932e2d471dSAndrew Jones extern u32 gicv3_iar_irqnr(u32 iar); 942e2d471dSAndrew Jones extern void gicv3_write_eoir(u32 irqstat); 952e2d471dSAndrew Jones extern void gicv3_ipi_send_single(int irq, int cpu); 962e2d471dSAndrew Jones extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest); 9791a6c3ceSAndrew Jones extern void gicv3_set_redist_base(size_t stride); 9805d1bb91SEric Auger extern void gicv3_lpi_set_clr_pending(int rdist, int n, bool set); 9905d1bb91SEric Auger extern void gicv3_lpi_alloc_tables(void); 100*80374e12SEric Auger extern void gicv3_lpi_rdist_enable(int redist); 101*80374e12SEric Auger extern void gicv3_lpi_rdist_disable(int redist); 10291a6c3ceSAndrew Jones 10391a6c3ceSAndrew Jones static inline void gicv3_do_wait_for_rwp(void *base) 10491a6c3ceSAndrew Jones { 10591a6c3ceSAndrew Jones int count = 100000; /* 1s */ 10691a6c3ceSAndrew Jones 10791a6c3ceSAndrew Jones while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) { 10891a6c3ceSAndrew Jones if (!--count) { 10991a6c3ceSAndrew Jones printf("GICv3: RWP timeout!\n"); 11091a6c3ceSAndrew Jones abort(); 11191a6c3ceSAndrew Jones } 11291a6c3ceSAndrew Jones cpu_relax(); 11391a6c3ceSAndrew Jones udelay(10); 11491a6c3ceSAndrew Jones }; 11591a6c3ceSAndrew Jones } 11691a6c3ceSAndrew Jones 11791a6c3ceSAndrew Jones static inline void gicv3_dist_wait_for_rwp(void) 11891a6c3ceSAndrew Jones { 11991a6c3ceSAndrew Jones gicv3_do_wait_for_rwp(gicv3_dist_base()); 12091a6c3ceSAndrew Jones } 12191a6c3ceSAndrew Jones 12291a6c3ceSAndrew Jones static inline void gicv3_redist_wait_for_uwp(void) 12391a6c3ceSAndrew Jones { 12491a6c3ceSAndrew Jones /* 12591a6c3ceSAndrew Jones * We can build on gic_do_wait_for_rwp, which uses GICD_ registers 12691a6c3ceSAndrew Jones * because GICD_CTLR == GICR_CTLR and GICD_CTLR_RWP == GICR_CTLR_UWP 12791a6c3ceSAndrew Jones */ 12891a6c3ceSAndrew Jones gicv3_do_wait_for_rwp(gicv3_redist_base()); 12991a6c3ceSAndrew Jones } 13091a6c3ceSAndrew Jones 13191a6c3ceSAndrew Jones static inline u32 mpidr_compress(u64 mpidr) 13291a6c3ceSAndrew Jones { 13391a6c3ceSAndrew Jones u64 compressed = mpidr & MPIDR_HWID_BITMASK; 13491a6c3ceSAndrew Jones 13591a6c3ceSAndrew Jones compressed = (((compressed >> 32) & 0xff) << 24) | compressed; 13691a6c3ceSAndrew Jones return compressed; 13791a6c3ceSAndrew Jones } 13891a6c3ceSAndrew Jones 13991a6c3ceSAndrew Jones static inline u64 mpidr_uncompress(u32 compressed) 14091a6c3ceSAndrew Jones { 14191a6c3ceSAndrew Jones u64 mpidr = ((u64)compressed >> 24) << 32; 14291a6c3ceSAndrew Jones 14391a6c3ceSAndrew Jones mpidr |= compressed & MPIDR_HWID_BITMASK; 14491a6c3ceSAndrew Jones return mpidr; 14591a6c3ceSAndrew Jones } 14691a6c3ceSAndrew Jones 14705d1bb91SEric Auger #define gicv3_lpi_set_config(intid, value) ({ \ 14805d1bb91SEric Auger gicv3_data.lpi_prop[LPI_OFFSET(intid)] = value; \ 14905d1bb91SEric Auger }) 15005d1bb91SEric Auger 15105d1bb91SEric Auger #define gicv3_lpi_get_config(intid) (gicv3_data.lpi_prop[LPI_OFFSET(intid)]) 15205d1bb91SEric Auger 15391a6c3ceSAndrew Jones #endif /* !__ASSEMBLY__ */ 15491a6c3ceSAndrew Jones #endif /* _ASMARM_GIC_V3_H_ */ 155