blob: 786d0bbd6d677aab2b604bd89b53a7b421757d6c [file] [log] [blame]
Boyan Karatotev8cef63d2025-01-07 11:26:56 +00001/*
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
Boyan Karatotev13b62812024-11-20 14:02:32 +00009
10#ifndef __ASSEMBLER__
11#include <stdbool.h>
12#include <stdint.h>
Boyan Karatotevdfb37a22024-12-09 14:29:33 +000013
14#include <lib/mmio.h>
Boyan Karatotev13b62812024-11-20 14:02:32 +000015#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
Boyan Karatotev82b228b2024-12-09 14:26:37 +000029/* 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
Boyan Karatotev4db6bf92025-02-05 11:20:13 +000047/* 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
Boyan Karatotevdfb37a22024-12-09 14:29:33 +000061/* 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
Boyan Karatotev71799202024-12-09 16:22:34 +000070/* 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
Boyan Karatotev13b62812024-11-20 14:02:32 +000084#ifndef __ASSEMBLER__
85
Boyan Karatotev82b228b2024-12-09 14:26:37 +000086#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
Boyan Karatotevdfb37a22024-12-09 14:29:33 +000094
95#define DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset) \
96static 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) \
102static inline uint32_t read_##_name(uintptr_t base) \
103{ \
104 return mmio_read_32(base + _offset); \
105}
106
Boyan Karatotev71799202024-12-09 16:22:34 +0000107#define DEFINE_GICV5_MMIO_WRITE_INDEXED_FUNC(_name, _offset) \
108static 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) \
114static 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
Boyan Karatotevdfb37a22024-12-09 14:29:33 +0000119#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
Boyan Karatotev71799202024-12-09 16:22:34 +0000123#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
Boyan Karatotev4db6bf92025-02-05 11:20:13 +0000127DEFINE_GICV5_MMIO_READ_FUNC(iri_aidr, 0x44)
128
Boyan Karatotev71799202024-12-09 16:22:34 +0000129DEFINE_GICV5_MMIO_READ_FUNC(iwb_idr0, 0x00)
130DEFINE_GICV5_MMIO_RW_FUNCS( iwb_cr0, 0x80)
131DEFINE_GICV5_MMIO_READ_FUNC(iwb_wenable_statusr, 0xc0)
132DEFINE_GICV5_MMIO_READ_FUNC(iwb_wdomain_statusr, 0xc4)
133DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wenabler, 0x2000)
134DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wtmr, 0x4000)
135DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wdomainr, 0x6000)
136
Boyan Karatotevdfb37a22024-12-09 14:29:33 +0000137DEFINE_GICV5_MMIO_READ_FUNC(irs_idr6, 0x0018)
138DEFINE_GICV5_MMIO_READ_FUNC(irs_idr7, 0x001c)
139DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_selr, 0x0108)
140DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_domainr, 0x010c)
141DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_cfgr, 0x0114)
142DEFINE_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
Boyan Karatotev71799202024-12-09 16:22:34 +0000160#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
Boyan Karatotevdfb37a22024-12-09 14:29:33 +0000167struct gicv5_wire_props {
168 /* continuous wire ID as seen by the attached component */
169 uint32_t id;
170 /* use the INTDMN_XYZ macros */
171 uint8_t domain:2;
172 /* use the TM_XYZ (eg. TM_EDGE) macros */
173 uint8_t tm:1;
174};
175
176/* to describe every IRS in the system */
177struct gicv5_irs {
178 /* mapped device nGnRnE by the platform*/
179 uintptr_t el3_config_frame;
180 struct gicv5_wire_props *spis;
181 uint32_t num_spis;
182};
183
Boyan Karatotev71799202024-12-09 16:22:34 +0000184/*
185 * to describe every IWB in the system where EL3 is the MPPAS. IWBs that have
186 * another world as an MPPAS need not be included
187 */
188struct gicv5_iwb {
189 /* mapped device nGnRnE by the platform*/
190 uintptr_t config_frame;
191 struct gicv5_wire_props *wires;
192 uint32_t num_wires;
193};
194
Boyan Karatotev13b62812024-11-20 14:02:32 +0000195struct gicv5_driver_data {
Boyan Karatotevdfb37a22024-12-09 14:29:33 +0000196 struct gicv5_irs *irss;
Boyan Karatotev71799202024-12-09 16:22:34 +0000197 struct gicv5_iwb *iwbs;
Boyan Karatotevdfb37a22024-12-09 14:29:33 +0000198 uint32_t num_irss;
Boyan Karatotev71799202024-12-09 16:22:34 +0000199 uint32_t num_iwbs;
Boyan Karatotev13b62812024-11-20 14:02:32 +0000200};
201
202extern const struct gicv5_driver_data plat_gicv5_driver_data;
203
204void gicv5_driver_init();
205uint8_t gicv5_get_pending_interrupt_type(void);
206bool gicv5_has_interrupt_type(unsigned int type);
Boyan Karatotev82b228b2024-12-09 14:26:37 +0000207void gicv5_enable_ppis();
Boyan Karatotev13b62812024-11-20 14:02:32 +0000208#endif /* __ASSEMBLER__ */
Boyan Karatotev8cef63d2025-01-07 11:26:56 +0000209#endif /* GICV5_H */