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)
239c537510SJingyi Wang #define GICD_CTLR_nASSGIreq (1U << 8)
2491a6c3ceSAndrew Jones #define GICD_CTLR_ARE_NS (1U << 4)
2591a6c3ceSAndrew Jones #define GICD_CTLR_ENABLE_G1A (1U << 1)
2691a6c3ceSAndrew Jones #define GICD_CTLR_ENABLE_G1 (1U << 0)
2791a6c3ceSAndrew Jones
289c537510SJingyi Wang #define GICD_TYPER2_nASSGIcap (1U << 8)
299c537510SJingyi Wang
3091a6c3ceSAndrew Jones /* Re-Distributor registers, offsets from RD_base */
3191a6c3ceSAndrew Jones #define GICR_TYPER 0x0008
3291a6c3ceSAndrew Jones
3391a6c3ceSAndrew Jones #define GICR_TYPER_LAST (1U << 4)
3491a6c3ceSAndrew Jones
3591a6c3ceSAndrew Jones /* Re-Distributor registers, offsets from SGI_base */
3691a6c3ceSAndrew Jones #define GICR_IGROUPR0 GICD_IGROUPR
3791a6c3ceSAndrew Jones #define GICR_ISENABLER0 GICD_ISENABLER
3808ae0906SAlexandru Elisei #define GICR_ICENABLER0 GICD_ICENABLER
39401c09eaSZenghui Yu #define GICR_ISPENDR0 GICD_ISPENDR
40401c09eaSZenghui Yu #define GICR_ICPENDR0 GICD_ICPENDR
41401c09eaSZenghui Yu #define GICR_ISACTIVER0 GICD_ISACTIVER
42401c09eaSZenghui Yu #define GICR_ICACTIVER0 GICD_ICACTIVER
4391a6c3ceSAndrew Jones #define GICR_IPRIORITYR0 GICD_IPRIORITYR
4491a6c3ceSAndrew Jones
45d24709d3SEric Auger #define GICR_PROPBASER 0x0070
46d24709d3SEric Auger #define GICR_PENDBASER 0x0078
47d24709d3SEric Auger #define GICR_CTLR GICD_CTLR
48d24709d3SEric Auger #define GICR_CTLR_ENABLE_LPIS (1UL << 0)
49d24709d3SEric Auger
502e2d471dSAndrew Jones #define ICC_SGI1R_AFFINITY_1_SHIFT 16
512e2d471dSAndrew Jones #define ICC_SGI1R_AFFINITY_2_SHIFT 32
522e2d471dSAndrew Jones #define ICC_SGI1R_AFFINITY_3_SHIFT 48
532e2d471dSAndrew Jones #define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \
542e2d471dSAndrew Jones (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT)
552e2d471dSAndrew Jones
5605d1bb91SEric Auger #define GICR_PENDBASER_PTZ BIT_ULL(62)
5705d1bb91SEric Auger
5805d1bb91SEric Auger #define LPI_PROP_GROUP1 (1 << 1)
5905d1bb91SEric Auger #define LPI_PROP_ENABLED (1 << 0)
6005d1bb91SEric Auger #define LPI_PROP_DEFAULT_PRIO 0xa0
6105d1bb91SEric Auger #define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | LPI_PROP_ENABLED)
6205d1bb91SEric Auger
6380374e12SEric Auger #define LPI_ID_BASE 8192
6480374e12SEric Auger #define LPI(lpi) ((lpi) + LPI_ID_BASE)
6580374e12SEric Auger #define LPI_OFFSET(intid) ((intid) - LPI_ID_BASE)
6680374e12SEric Auger
6791a6c3ceSAndrew Jones #include <asm/arch_gicv3.h>
6891a6c3ceSAndrew Jones
69*0cc3a351SSean Christopherson #ifndef __ASSEMBLER__
70dfc1fec2SAndrew Jones #include <cpumask.h>
7191a6c3ceSAndrew Jones #include <asm/setup.h>
7291a6c3ceSAndrew Jones #include <asm/processor.h>
7391a6c3ceSAndrew Jones #include <asm/delay.h>
7491a6c3ceSAndrew Jones #include <asm/smp.h>
7591a6c3ceSAndrew Jones #include <asm/io.h>
7691a6c3ceSAndrew Jones
77a5a2d35cSAndrew Jones #define GICV3_NR_REDISTS 8
78a5a2d35cSAndrew Jones
7991a6c3ceSAndrew Jones struct gicv3_data {
8091a6c3ceSAndrew Jones void *dist_base;
81a5a2d35cSAndrew Jones void *redist_bases[GICV3_NR_REDISTS];
8291a6c3ceSAndrew Jones void *redist_base[NR_CPUS];
8305d1bb91SEric Auger u8 *lpi_prop;
8405d1bb91SEric Auger void *lpi_pend[NR_CPUS];
8591a6c3ceSAndrew Jones unsigned int irq_nr;
8691a6c3ceSAndrew Jones };
8791a6c3ceSAndrew Jones extern struct gicv3_data gicv3_data;
8891a6c3ceSAndrew Jones
8991a6c3ceSAndrew Jones #define gicv3_dist_base() (gicv3_data.dist_base)
9091a6c3ceSAndrew Jones #define gicv3_redist_base() (gicv3_data.redist_base[smp_processor_id()])
9191a6c3ceSAndrew Jones #define gicv3_sgi_base() (gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
9291a6c3ceSAndrew Jones
9391a6c3ceSAndrew Jones extern int gicv3_init(void);
9491a6c3ceSAndrew Jones extern void gicv3_enable_defaults(void);
952e2d471dSAndrew Jones extern u32 gicv3_read_iar(void);
962e2d471dSAndrew Jones extern u32 gicv3_iar_irqnr(u32 iar);
972e2d471dSAndrew Jones extern void gicv3_write_eoir(u32 irqstat);
982e2d471dSAndrew Jones extern void gicv3_ipi_send_single(int irq, int cpu);
992e2d471dSAndrew Jones extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest);
10091a6c3ceSAndrew Jones extern void gicv3_set_redist_base(size_t stride);
10105d1bb91SEric Auger extern void gicv3_lpi_set_clr_pending(int rdist, int n, bool set);
10205d1bb91SEric Auger extern void gicv3_lpi_alloc_tables(void);
10380374e12SEric Auger extern void gicv3_lpi_rdist_enable(int redist);
10480374e12SEric Auger extern void gicv3_lpi_rdist_disable(int redist);
10591a6c3ceSAndrew Jones
gicv3_do_wait_for_rwp(void * base)10691a6c3ceSAndrew Jones static inline void gicv3_do_wait_for_rwp(void *base)
10791a6c3ceSAndrew Jones {
10891a6c3ceSAndrew Jones int count = 100000; /* 1s */
10991a6c3ceSAndrew Jones
11091a6c3ceSAndrew Jones while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
11191a6c3ceSAndrew Jones if (!--count) {
11291a6c3ceSAndrew Jones printf("GICv3: RWP timeout!\n");
11391a6c3ceSAndrew Jones abort();
11491a6c3ceSAndrew Jones }
11591a6c3ceSAndrew Jones cpu_relax();
11691a6c3ceSAndrew Jones udelay(10);
11791a6c3ceSAndrew Jones };
11891a6c3ceSAndrew Jones }
11991a6c3ceSAndrew Jones
gicv3_dist_wait_for_rwp(void)12091a6c3ceSAndrew Jones static inline void gicv3_dist_wait_for_rwp(void)
12191a6c3ceSAndrew Jones {
12291a6c3ceSAndrew Jones gicv3_do_wait_for_rwp(gicv3_dist_base());
12391a6c3ceSAndrew Jones }
12491a6c3ceSAndrew Jones
gicv3_redist_wait_for_uwp(void)12591a6c3ceSAndrew Jones static inline void gicv3_redist_wait_for_uwp(void)
12691a6c3ceSAndrew Jones {
12791a6c3ceSAndrew Jones /*
12891a6c3ceSAndrew Jones * We can build on gic_do_wait_for_rwp, which uses GICD_ registers
12991a6c3ceSAndrew Jones * because GICD_CTLR == GICR_CTLR and GICD_CTLR_RWP == GICR_CTLR_UWP
13091a6c3ceSAndrew Jones */
13191a6c3ceSAndrew Jones gicv3_do_wait_for_rwp(gicv3_redist_base());
13291a6c3ceSAndrew Jones }
13391a6c3ceSAndrew Jones
mpidr_compress(u64 mpidr)13491a6c3ceSAndrew Jones static inline u32 mpidr_compress(u64 mpidr)
13591a6c3ceSAndrew Jones {
13691a6c3ceSAndrew Jones u64 compressed = mpidr & MPIDR_HWID_BITMASK;
13791a6c3ceSAndrew Jones
13891a6c3ceSAndrew Jones compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
13991a6c3ceSAndrew Jones return compressed;
14091a6c3ceSAndrew Jones }
14191a6c3ceSAndrew Jones
mpidr_uncompress(u32 compressed)14291a6c3ceSAndrew Jones static inline u64 mpidr_uncompress(u32 compressed)
14391a6c3ceSAndrew Jones {
14491a6c3ceSAndrew Jones u64 mpidr = ((u64)compressed >> 24) << 32;
14591a6c3ceSAndrew Jones
14691a6c3ceSAndrew Jones mpidr |= compressed & MPIDR_HWID_BITMASK;
14791a6c3ceSAndrew Jones return mpidr;
14891a6c3ceSAndrew Jones }
14991a6c3ceSAndrew Jones
15005d1bb91SEric Auger #define gicv3_lpi_set_config(intid, value) ({ \
15105d1bb91SEric Auger gicv3_data.lpi_prop[LPI_OFFSET(intid)] = value; \
15205d1bb91SEric Auger })
15305d1bb91SEric Auger
15405d1bb91SEric Auger #define gicv3_lpi_get_config(intid) (gicv3_data.lpi_prop[LPI_OFFSET(intid)])
15505d1bb91SEric Auger
156*0cc3a351SSean Christopherson #endif /* !__ASSEMBLER__ */
15791a6c3ceSAndrew Jones #endif /* _ASMARM_GIC_V3_H_ */
158