xref: /rk3399_ARM-atf/include/drivers/arm/gicv5.h (revision 5f2f471011f8d75d8f1b33e8da150681db84940d)
1 /*
2  * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef GICV5_H
8 #define GICV5_H
9 
10 #ifndef __ASSEMBLER__
11 #include <stdbool.h>
12 #include <stdint.h>
13 
14 #include <lib/mmio.h>
15 #endif
16 
17 #include <lib/utils_def.h>
18 
19 /* Interrupt Domain definitions */
20 #define INTDMN_S				0
21 #define INTDMN_NS				1
22 #define INTDMN_EL3				2
23 #define INTDMN_RL				3
24 
25 /* Trigger modes */
26 #define TM_EDGE					0
27 #define TM_LEVEL				1
28 
29 /* Architected PPI numbers */
30 #define PPI_TRBIRQ				31
31 #define PPI_CNTP				30
32 #define PPI_CNTPS				29
33 #define PPI_CNTHV				28
34 #define PPI_CNTV				27
35 #define PPI_CNTHP				26
36 #define PPI_GICMNT				25
37 #define PPI_CTIIRQ				24
38 #define PPI_PMUIRQ				23
39 #define PPI_COMMIRQ				22
40 #define PPI_PMBIRQ				21
41 #define PPI_CNTHPS				20
42 #define PPI_CNTHVS				19
43 #define PPI_DB_NS				2
44 #define PPI_DB_RL				1
45 #define PPI_DB_S				0
46 
47 /* Register fields common to all IRI components.
48  * They have the same name and offset in every config frame */
49 #define IRI_AIDR_COMPONENT_SHIFT		8
50 #define IRI_AIDR_COMPONENT_WIDTH		4
51 #define IRI_AIDR_COMPONENT_IRS			0
52 #define IRI_AIDR_COMPONENT_ITS			1
53 #define IRI_AIDR_COMPONENT_IWB			2
54 #define IRI_AIDR_ARCH_MAJOR_SHIFT		4
55 #define IRI_AIDR_ARCH_MAJOR_WIDTH		4
56 #define IRI_AIDR_ARCH_MAJOR_V5			0
57 #define IRI_AIDR_ARCH_MINOR_SHIFT		0
58 #define IRI_AIDR_ARCH_MINOR_WIDTH		4
59 #define IRI_AIDR_ARCH_MINOR_P0			0
60 
61 /* IRS register fields */
62 #define IRS_IDR6_SPI_IRS_RANGE_SHIFT		0
63 #define IRS_IDR6_SPI_IRS_RANGE_WIDTH		24
64 #define IRS_IDR7_SPI_BASE_SHIFT			0
65 #define IRS_IDR7_SPI_BASE_WIDTH			24
66 
67 #define IRS_SPI_STATUSR_IDLE_BIT		BIT(0)
68 #define IRS_SPI_STATUSR_V_BIT			BIT(1)
69 
70 /* IWB register fields */
71 #define IWB_IDR0_DOMAINS_SHIFT			11
72 #define IWB_IDR0_DOMAINS_WIDTH			4
73 #define IWB_IDR0_IWRANGE_SHIFT			0
74 #define IWB_IDR0_IWRANGE_WIDTH			10
75 
76 #define IWB_CR0_IWBEN_BIT			BIT(0)
77 #define IWB_CR0_IDLE_BIT			BIT(1)
78 
79 #define IWB_WENABLE_STATUSR_IDLE_BIT		BIT(0)
80 #define IWB_WDOMAIN_STATUSR_IDLE_BIT		BIT(0)
81 
82 #define IWB_WDOMAINR_DOMAINX_MASK		0x3
83 
84 #ifndef __ASSEMBLER__
85 
86 #define _PPI_FIELD_SHIFT(_REG, _ppi_id)						\
87 	((_ppi_id % (ICC_PPI_##_REG##_COUNT)) * (64 / ICC_PPI_##_REG##_COUNT))
88 
89 #define write_icc_ppi_domainr(_var, _ppi_id, _value)				\
90 	do {									\
91 		_var |=  (uint64_t)_value << _PPI_FIELD_SHIFT(DOMAINR, _ppi_id);\
92 	} while (false)
93 
94 
95 #define DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset)				\
96 static inline void write_##_name(uintptr_t base, uint32_t val)			\
97 {										\
98 	mmio_write_32(base + _offset, val);					\
99 }
100 
101 #define DEFINE_GICV5_MMIO_READ_FUNC(_name, _offset)				\
102 static inline uint32_t read_##_name(uintptr_t base)				\
103 {										\
104 	return mmio_read_32(base + _offset);					\
105 }
106 
107 #define DEFINE_GICV5_MMIO_WRITE_INDEXED_FUNC(_name, _offset)			\
108 static inline void write_##_name(uintptr_t base, uint16_t index, uint32_t val)	\
109 {										\
110 	mmio_write_32(base + _offset + (index * sizeof(uint32_t)), val);	\
111 }
112 
113 #define DEFINE_GICV5_MMIO_READ_INDEXED_FUNC(_name, _offset)			\
114 static inline uint32_t read_##_name(uintptr_t base, uint16_t index)		\
115 {										\
116 	return mmio_read_32(base + _offset + (index * sizeof(uint32_t)));	\
117 }
118 
119 #define DEFINE_GICV5_MMIO_RW_FUNCS(_name, _offset)				\
120 	DEFINE_GICV5_MMIO_READ_FUNC(_name, _offset)				\
121 	DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset)
122 
123 #define DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(_name, _offset)			\
124 	DEFINE_GICV5_MMIO_READ_INDEXED_FUNC(_name, _offset)			\
125 	DEFINE_GICV5_MMIO_WRITE_INDEXED_FUNC(_name, _offset)
126 
127 DEFINE_GICV5_MMIO_READ_FUNC(iri_aidr,			0x44)
128 
129 DEFINE_GICV5_MMIO_READ_FUNC(iwb_idr0,			0x00)
130 DEFINE_GICV5_MMIO_RW_FUNCS( iwb_cr0,			0x80)
131 DEFINE_GICV5_MMIO_READ_FUNC(iwb_wenable_statusr,	0xc0)
132 DEFINE_GICV5_MMIO_READ_FUNC(iwb_wdomain_statusr,	0xc4)
133 DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wenabler,	0x2000)
134 DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wtmr,		0x4000)
135 DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wdomainr,	0x8000)
136 
137 DEFINE_GICV5_MMIO_READ_FUNC(irs_idr6,			0x0018)
138 DEFINE_GICV5_MMIO_READ_FUNC(irs_idr7,			0x001c)
139 DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_selr,		0x0108)
140 DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_domainr,		0x010c)
141 DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_cfgr,		0x0114)
142 DEFINE_GICV5_MMIO_READ_FUNC(irs_spi_statusr,		0x0118)
143 
144 #define WAIT_FOR_IDLE(base, reg, reg_up)					\
145 	do {									\
146 		while ((read_##reg(base) & reg_up##_IDLE_BIT) == 0U) {}		\
147 	} while (0)
148 
149 /* wait for IDLE but also check the V bit was set */
150 #define WAIT_FOR_VIDLE(base, reg, reg_up)					\
151 	do {									\
152 		uint32_t val;							\
153 		while (((val = read_##reg(base)) & reg_up##_IDLE_BIT) == 0U) {}	\
154 		assert((val & reg##_V_BIT) != 0U);				\
155 	} while (0)
156 
157 #define WAIT_FOR_VIDLE_IRS_SPI_STATUSR(base)					\
158 	WAIT_FOR_IDLE(base, irs_spi_statusr, IRS_SPI_STATUSR)
159 
160 #define WAIT_FOR_IDLE_IWB_WENABLE_STATUSR(base)					\
161 	WAIT_FOR_IDLE(base, iwb_wenable_statusr, IWB_WENABLE_STATUSR)
162 #define WAIT_FOR_IDLE_IWB_WDOMAIN_STATUSR(base)					\
163 	WAIT_FOR_IDLE(base, iwb_wdomain_statusr, IWB_WDOMAIN_STATUSR)
164 #define WAIT_FOR_IDLE_IWB_CR0(base)						\
165 	WAIT_FOR_IDLE(base, iwb_cr0, IWB_CR0)
166 
167 #define WIRE_PROP_DESC(_id, _domain, _tm) \
168 	{ \
169 		.id = (_id), \
170 		.domain = (_domain), \
171 		.tm = (_tm), \
172 	}
173 
174 struct gicv5_wire_props {
175 	/* continuous wire ID as seen by the attached component */
176 	uint32_t id;
177 	/* use the INTDMN_XYZ macros */
178 	uint8_t domain:2;
179 	/* use the TM_XYZ (eg. TM_EDGE) macros */
180 	uint8_t tm:1;
181 };
182 
183 /* to describe every IRS in the system */
184 struct gicv5_irs {
185 	/* mapped device nGnRnE by the platform*/
186 	uintptr_t el3_config_frame;
187 	struct gicv5_wire_props *spis;
188 	uint32_t num_spis;
189 };
190 
191 /*
192  * to describe every IWB in the system where EL3 is the MPPAS. IWBs that have
193  * another world as an MPPAS need not be included
194  */
195 struct gicv5_iwb {
196 	/* mapped device nGnRnE by the platform*/
197 	uintptr_t config_frame;
198 	struct gicv5_wire_props *wires;
199 	uint32_t num_wires;
200 };
201 
202 struct gicv5_driver_data {
203 	struct gicv5_irs *irss;
204 	struct gicv5_iwb *iwbs;
205 	uint32_t num_irss;
206 	uint32_t num_iwbs;
207 };
208 
209 extern const struct gicv5_driver_data plat_gicv5_driver_data;
210 
211 void gicv5_driver_init();
212 uint8_t gicv5_get_pending_interrupt_type(void);
213 bool gicv5_has_interrupt_type(unsigned int type);
214 void gicv5_enable_ppis();
215 #endif /* __ASSEMBLER__ */
216 #endif /* GICV5_H */
217