xref: /kvm-unit-tests/lib/arm/asm/gic-v3.h (revision 05d1bb91a1ff7f774d7ee15413e08324e58fd59a)
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 
53*05d1bb91SEric Auger #define GICR_PENDBASER_PTZ		BIT_ULL(62)
54*05d1bb91SEric Auger 
55*05d1bb91SEric Auger #define LPI_PROP_GROUP1			(1 << 1)
56*05d1bb91SEric Auger #define LPI_PROP_ENABLED		(1 << 0)
57*05d1bb91SEric Auger #define LPI_PROP_DEFAULT_PRIO		0xa0
58*05d1bb91SEric Auger #define LPI_PROP_DEFAULT		(LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | LPI_PROP_ENABLED)
59*05d1bb91SEric Auger 
6091a6c3ceSAndrew Jones #include <asm/arch_gicv3.h>
6191a6c3ceSAndrew Jones 
6291a6c3ceSAndrew Jones #ifndef __ASSEMBLY__
6391a6c3ceSAndrew Jones #include <asm/setup.h>
6491a6c3ceSAndrew Jones #include <asm/processor.h>
6591a6c3ceSAndrew Jones #include <asm/delay.h>
662e2d471dSAndrew Jones #include <asm/cpumask.h>
6791a6c3ceSAndrew Jones #include <asm/smp.h>
6891a6c3ceSAndrew Jones #include <asm/io.h>
6991a6c3ceSAndrew Jones 
70a5a2d35cSAndrew Jones #define GICV3_NR_REDISTS 8
71a5a2d35cSAndrew Jones 
7291a6c3ceSAndrew Jones struct gicv3_data {
7391a6c3ceSAndrew Jones 	void *dist_base;
74a5a2d35cSAndrew Jones 	void *redist_bases[GICV3_NR_REDISTS];
7591a6c3ceSAndrew Jones 	void *redist_base[NR_CPUS];
76*05d1bb91SEric Auger 	u8 *lpi_prop;
77*05d1bb91SEric Auger 	void *lpi_pend[NR_CPUS];
7891a6c3ceSAndrew Jones 	unsigned int irq_nr;
7991a6c3ceSAndrew Jones };
8091a6c3ceSAndrew Jones extern struct gicv3_data gicv3_data;
8191a6c3ceSAndrew Jones 
8291a6c3ceSAndrew Jones #define gicv3_dist_base()		(gicv3_data.dist_base)
8391a6c3ceSAndrew Jones #define gicv3_redist_base()		(gicv3_data.redist_base[smp_processor_id()])
8491a6c3ceSAndrew Jones #define gicv3_sgi_base()		(gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
8591a6c3ceSAndrew Jones 
8691a6c3ceSAndrew Jones extern int gicv3_init(void);
8791a6c3ceSAndrew Jones extern void gicv3_enable_defaults(void);
882e2d471dSAndrew Jones extern u32 gicv3_read_iar(void);
892e2d471dSAndrew Jones extern u32 gicv3_iar_irqnr(u32 iar);
902e2d471dSAndrew Jones extern void gicv3_write_eoir(u32 irqstat);
912e2d471dSAndrew Jones extern void gicv3_ipi_send_single(int irq, int cpu);
922e2d471dSAndrew Jones extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest);
9391a6c3ceSAndrew Jones extern void gicv3_set_redist_base(size_t stride);
94*05d1bb91SEric Auger extern void gicv3_lpi_set_clr_pending(int rdist, int n, bool set);
95*05d1bb91SEric Auger extern void gicv3_lpi_alloc_tables(void);
9691a6c3ceSAndrew Jones 
9791a6c3ceSAndrew Jones static inline void gicv3_do_wait_for_rwp(void *base)
9891a6c3ceSAndrew Jones {
9991a6c3ceSAndrew Jones 	int count = 100000;	/* 1s */
10091a6c3ceSAndrew Jones 
10191a6c3ceSAndrew Jones 	while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
10291a6c3ceSAndrew Jones 		if (!--count) {
10391a6c3ceSAndrew Jones 			printf("GICv3: RWP timeout!\n");
10491a6c3ceSAndrew Jones 			abort();
10591a6c3ceSAndrew Jones 		}
10691a6c3ceSAndrew Jones 		cpu_relax();
10791a6c3ceSAndrew Jones 		udelay(10);
10891a6c3ceSAndrew Jones 	};
10991a6c3ceSAndrew Jones }
11091a6c3ceSAndrew Jones 
11191a6c3ceSAndrew Jones static inline void gicv3_dist_wait_for_rwp(void)
11291a6c3ceSAndrew Jones {
11391a6c3ceSAndrew Jones 	gicv3_do_wait_for_rwp(gicv3_dist_base());
11491a6c3ceSAndrew Jones }
11591a6c3ceSAndrew Jones 
11691a6c3ceSAndrew Jones static inline void gicv3_redist_wait_for_uwp(void)
11791a6c3ceSAndrew Jones {
11891a6c3ceSAndrew Jones 	/*
11991a6c3ceSAndrew Jones 	 * We can build on gic_do_wait_for_rwp, which uses GICD_ registers
12091a6c3ceSAndrew Jones 	 * because GICD_CTLR == GICR_CTLR and GICD_CTLR_RWP == GICR_CTLR_UWP
12191a6c3ceSAndrew Jones 	 */
12291a6c3ceSAndrew Jones 	gicv3_do_wait_for_rwp(gicv3_redist_base());
12391a6c3ceSAndrew Jones }
12491a6c3ceSAndrew Jones 
12591a6c3ceSAndrew Jones static inline u32 mpidr_compress(u64 mpidr)
12691a6c3ceSAndrew Jones {
12791a6c3ceSAndrew Jones 	u64 compressed = mpidr & MPIDR_HWID_BITMASK;
12891a6c3ceSAndrew Jones 
12991a6c3ceSAndrew Jones 	compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
13091a6c3ceSAndrew Jones 	return compressed;
13191a6c3ceSAndrew Jones }
13291a6c3ceSAndrew Jones 
13391a6c3ceSAndrew Jones static inline u64 mpidr_uncompress(u32 compressed)
13491a6c3ceSAndrew Jones {
13591a6c3ceSAndrew Jones 	u64 mpidr = ((u64)compressed >> 24) << 32;
13691a6c3ceSAndrew Jones 
13791a6c3ceSAndrew Jones 	mpidr |= compressed & MPIDR_HWID_BITMASK;
13891a6c3ceSAndrew Jones 	return mpidr;
13991a6c3ceSAndrew Jones }
14091a6c3ceSAndrew Jones 
141*05d1bb91SEric Auger #define gicv3_lpi_set_config(intid, value) ({		\
142*05d1bb91SEric Auger 	gicv3_data.lpi_prop[LPI_OFFSET(intid)] = value;	\
143*05d1bb91SEric Auger })
144*05d1bb91SEric Auger 
145*05d1bb91SEric Auger #define gicv3_lpi_get_config(intid) (gicv3_data.lpi_prop[LPI_OFFSET(intid)])
146*05d1bb91SEric Auger 
14791a6c3ceSAndrew Jones #endif /* !__ASSEMBLY__ */
14891a6c3ceSAndrew Jones #endif /* _ASMARM_GIC_V3_H_ */
149