1 /*
2 * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h
3 *
4 * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
5 *
6 * This work is licensed under the terms of the GNU LGPL, version 2.
7 */
8 #ifndef _ASMARM_GIC_V3_H_
9 #define _ASMARM_GIC_V3_H_
10
11 #ifndef _ASMARM_GIC_H_
12 #error Do not directly include <asm/gic-v3.h>. Include <asm/gic.h>
13 #endif
14
15 /*
16 * Distributor registers
17 *
18 * We expect to be run in Non-secure mode, thus we define the
19 * group1 enable bits with respect to that view.
20 */
21 #define GICD_CTLR 0x0000
22 #define GICD_CTLR_RWP (1U << 31)
23 #define GICD_CTLR_nASSGIreq (1U << 8)
24 #define GICD_CTLR_ARE_NS (1U << 4)
25 #define GICD_CTLR_ENABLE_G1A (1U << 1)
26 #define GICD_CTLR_ENABLE_G1 (1U << 0)
27
28 #define GICD_TYPER2_nASSGIcap (1U << 8)
29
30 /* Re-Distributor registers, offsets from RD_base */
31 #define GICR_TYPER 0x0008
32
33 #define GICR_TYPER_LAST (1U << 4)
34
35 /* Re-Distributor registers, offsets from SGI_base */
36 #define GICR_IGROUPR0 GICD_IGROUPR
37 #define GICR_ISENABLER0 GICD_ISENABLER
38 #define GICR_ICENABLER0 GICD_ICENABLER
39 #define GICR_ISPENDR0 GICD_ISPENDR
40 #define GICR_ICPENDR0 GICD_ICPENDR
41 #define GICR_ISACTIVER0 GICD_ISACTIVER
42 #define GICR_ICACTIVER0 GICD_ICACTIVER
43 #define GICR_IPRIORITYR0 GICD_IPRIORITYR
44
45 #define GICR_PROPBASER 0x0070
46 #define GICR_PENDBASER 0x0078
47 #define GICR_CTLR GICD_CTLR
48 #define GICR_CTLR_ENABLE_LPIS (1UL << 0)
49
50 #define ICC_SGI1R_AFFINITY_1_SHIFT 16
51 #define ICC_SGI1R_AFFINITY_2_SHIFT 32
52 #define ICC_SGI1R_AFFINITY_3_SHIFT 48
53 #define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \
54 (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT)
55
56 #define GICR_PENDBASER_PTZ BIT_ULL(62)
57
58 #define LPI_PROP_GROUP1 (1 << 1)
59 #define LPI_PROP_ENABLED (1 << 0)
60 #define LPI_PROP_DEFAULT_PRIO 0xa0
61 #define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | LPI_PROP_ENABLED)
62
63 #define LPI_ID_BASE 8192
64 #define LPI(lpi) ((lpi) + LPI_ID_BASE)
65 #define LPI_OFFSET(intid) ((intid) - LPI_ID_BASE)
66
67 #include <asm/arch_gicv3.h>
68
69 #ifndef __ASSEMBLER__
70 #include <cpumask.h>
71 #include <asm/setup.h>
72 #include <asm/processor.h>
73 #include <asm/delay.h>
74 #include <asm/smp.h>
75 #include <asm/io.h>
76
77 #define GICV3_NR_REDISTS 8
78
79 struct gicv3_data {
80 void *dist_base;
81 void *redist_bases[GICV3_NR_REDISTS];
82 void *redist_base[NR_CPUS];
83 u8 *lpi_prop;
84 void *lpi_pend[NR_CPUS];
85 unsigned int irq_nr;
86 };
87 extern struct gicv3_data gicv3_data;
88
89 #define gicv3_dist_base() (gicv3_data.dist_base)
90 #define gicv3_redist_base() (gicv3_data.redist_base[smp_processor_id()])
91 #define gicv3_sgi_base() (gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
92
93 extern int gicv3_init(void);
94 extern void gicv3_enable_defaults(void);
95 extern u32 gicv3_read_iar(void);
96 extern u32 gicv3_iar_irqnr(u32 iar);
97 extern void gicv3_write_eoir(u32 irqstat);
98 extern void gicv3_ipi_send_single(int irq, int cpu);
99 extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest);
100 extern void gicv3_set_redist_base(size_t stride);
101 extern void gicv3_lpi_set_clr_pending(int rdist, int n, bool set);
102 extern void gicv3_lpi_alloc_tables(void);
103 extern void gicv3_lpi_rdist_enable(int redist);
104 extern void gicv3_lpi_rdist_disable(int redist);
105
gicv3_do_wait_for_rwp(void * base)106 static inline void gicv3_do_wait_for_rwp(void *base)
107 {
108 int count = 100000; /* 1s */
109
110 while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
111 if (!--count) {
112 printf("GICv3: RWP timeout!\n");
113 abort();
114 }
115 cpu_relax();
116 udelay(10);
117 };
118 }
119
gicv3_dist_wait_for_rwp(void)120 static inline void gicv3_dist_wait_for_rwp(void)
121 {
122 gicv3_do_wait_for_rwp(gicv3_dist_base());
123 }
124
gicv3_redist_wait_for_uwp(void)125 static inline void gicv3_redist_wait_for_uwp(void)
126 {
127 /*
128 * We can build on gic_do_wait_for_rwp, which uses GICD_ registers
129 * because GICD_CTLR == GICR_CTLR and GICD_CTLR_RWP == GICR_CTLR_UWP
130 */
131 gicv3_do_wait_for_rwp(gicv3_redist_base());
132 }
133
mpidr_compress(u64 mpidr)134 static inline u32 mpidr_compress(u64 mpidr)
135 {
136 u64 compressed = mpidr & MPIDR_HWID_BITMASK;
137
138 compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
139 return compressed;
140 }
141
mpidr_uncompress(u32 compressed)142 static inline u64 mpidr_uncompress(u32 compressed)
143 {
144 u64 mpidr = ((u64)compressed >> 24) << 32;
145
146 mpidr |= compressed & MPIDR_HWID_BITMASK;
147 return mpidr;
148 }
149
150 #define gicv3_lpi_set_config(intid, value) ({ \
151 gicv3_data.lpi_prop[LPI_OFFSET(intid)] = value; \
152 })
153
154 #define gicv3_lpi_get_config(intid) (gicv3_data.lpi_prop[LPI_OFFSET(intid)])
155
156 #endif /* !__ASSEMBLER__ */
157 #endif /* _ASMARM_GIC_V3_H_ */
158