1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! Definitions for the Generic Interrupt Controller (GIC) registers.

use bitfield_struct::bitfield;
use core::ops::Range;
use open_enum::open_enum;

open_enum! {
    pub enum GicdRegister: u16 {
        CTLR = 0x0000,
        TYPER = 0x0004,
        IIDR = 0x0008,
        TYPER2 = 0x000c,
        STATUSR = 0x0010,
        SETSPI_NSR = 0x0040,
        CLRSPI_NSR = 0x0048,
        SETSPI_SR = 0x0050,
        CLRSPI_SR = 0x0058,
        IGROUPR0 = 0x0080,       // 0x80
        ISENABLER0 = 0x0100,     // 0x80
        ICENABLER0 = 0x0180,     // 0x80
        ISPENDR0 = 0x0200,       // 0x80
        ICPENDR0 = 0x0280,       // 0x80
        ISACTIVER0 = 0x0300,     // 0x80
        ICACTIVER0 = 0x0380,     // 0x80
        IPRIORITYR0 = 0x0400,    // 0x400
        ITARGETSR0 = 0x0800,     // 0x400
        ICFGR0 = 0x0c00,         // 0x100
        IGRPMODR0 = 0x0d00,      // 0x100
        NSACR0 = 0x0e00,         // 0x100
        SGIR = 0x0f00,
        CPENDSGIR0 = 0x0f10,     // 0x10
        SPENDSGIR0 = 0x0f20,     // 0x10
        INMIR0 = 0x0f80,         // 0x80
        IROUTER0 = 0x6000,       // 0x2000, skip first 0x100,
        PIDR2 = 0xffe8,
    }
}

impl GicdRegister {
    pub const IGROUPR: Range<u16> = Self::IGROUPR0.0..Self::IGROUPR0.0 + 0x80;
    pub const ISENABLER: Range<u16> = Self::ISENABLER0.0..Self::ISENABLER0.0 + 0x80;
    pub const ICENABLER: Range<u16> = Self::ICENABLER0.0..Self::ICENABLER0.0 + 0x80;
    pub const ISPENDR: Range<u16> = Self::ISPENDR0.0..Self::ISPENDR0.0 + 0x80;
    pub const ICPENDR: Range<u16> = Self::ICPENDR0.0..Self::ICPENDR0.0 + 0x80;
    pub const ISACTIVER: Range<u16> = Self::ISACTIVER0.0..Self::ISACTIVER0.0 + 0x80;
    pub const ICACTIVER: Range<u16> = Self::ICACTIVER0.0..Self::ICACTIVER0.0 + 0x80;
    pub const ICFGR: Range<u16> = Self::ICFGR0.0..Self::ICFGR0.0 + 0x100;
    pub const IPRIORITYR: Range<u16> = Self::IPRIORITYR0.0..Self::IPRIORITYR0.0 + 0x400;
    pub const IROUTER: Range<u16> = Self::IROUTER0.0..Self::IROUTER0.0 + 0x2000;
}

#[bitfield(u32)]
pub struct GicdTyper {
    #[bits(5)]
    pub it_lines_number: u8,
    #[bits(3)]
    pub cpu_number: u8,
    pub espi: bool,
    pub nmi: bool,
    pub security_extn: bool,
    #[bits(5)]
    pub num_lpis: u8,
    pub mbis: bool,
    pub lpis: bool,
    pub dvis: bool,
    #[bits(5)]
    pub id_bits: u8,
    pub a3v: bool,
    pub no1n: bool,
    pub rss: bool,
    #[bits(5)]
    pub espi_range: u8,
}

#[bitfield(u32)]
pub struct GicdTyper2 {
    #[bits(5)]
    pub vid: u8,
    #[bits(2)]
    _res5_6: u8,
    pub vil: bool,
    pub n_assgi_cap: bool,
    #[bits(23)]
    _res9_31: u32,
}

#[bitfield(u32)]
pub struct GicdCtlr {
    pub enable_grp0: bool,
    pub enable_grp1: bool,
    #[bits(2)]
    _res_2_3: u8,
    pub are: bool,
    _res_5: bool,
    pub ds: bool,
    pub e1nwf: bool,
    pub n_assgi_req: bool,
    #[bits(22)]
    _res_9_30: u32,
    pub rwp: bool,
}

open_enum! {
    pub enum GicrRdRegister: u16 {
        CTLR = 0x0000,
        IIDR = 0x0004,
        TYPER = 0x0008,     // 64 bit
        STATUSR = 0x0010,
        WAKER = 0x0014,
        MPAMIDR = 0x0018,
        PARTIDR = 0x001c,
        SETLPIR = 0x0040,   // 64 bit
        CLRLPIR = 0x0048,   // 64 bit
        PROPBASER = 0x0070, // 64 bit
        PENDBASER = 0x0078, // 64 bit
        INVLPIR = 0x00A0,   // 64 bit
        SYNCR = 0x00C0,     // 64 bit
        PIDR2 = 0xffe8,
    }
}

open_enum! {
    pub enum GicrSgiRegister: u16 {
        IGROUPR0 = 0x0080,
        ISENABLER0 = 0x0100,
        ICENABLER0 = 0x0180,
        ISPENDR0 = 0x0200,
        ICPENDR0 = 0x0280,
        ISACTIVER0 = 0x0300,
        ICACTIVER0 = 0x0380,
        IPRIORITYR0 = 0x0400, // 0x20
        ICFGR0 = 0x0c00,
        ICFGR1 = 0x0c04,
        IGRPMODR0 = 0x0d00,
    }
}

impl GicrSgiRegister {
    pub const IPRIORITYR: Range<u16> = Self::IPRIORITYR0.0..Self::IPRIORITYR0.0 + 0x20;
}

#[bitfield(u64)]
pub struct GicrTyper {
    pub plpis: bool,
    pub vlpis: bool,
    pub dirty: bool,
    pub direct_lpi: bool,
    pub last: bool,
    pub dpgs: bool,
    pub mpam: bool,
    pub rvpeid: bool,
    pub processor_number: u16,
    #[bits(2)]
    pub common_lpi_aff: u8,
    pub vsgi: bool,
    #[bits(5)]
    pub ppi_num: u8,
    pub aff0: u8,
    pub aff1: u8,
    pub aff2: u8,
    pub aff3: u8,
}

#[bitfield(u32)]
pub struct GicrCtlr {
    pub enable_lpis: bool,
    pub ces: bool,
    pub ir: bool,
    pub rwp: bool,
    #[bits(20)]
    _res_4_23: u32,
    pub dpg0: bool,
    pub dpg1ns: bool,
    pub dpg1s: bool,
    #[bits(4)]
    _res_27_30: u32,
    pub uwp: bool,
}

#[bitfield(u32)]
pub struct GicrWaker {
    /// Implementation defined.
    pub bit_0: bool,
    pub processor_sleep: bool,
    pub children_asleep: bool,
    #[bits(28)]
    _res_3_30: u32,
    /// Implementation defined.
    pub bit_31: bool,
}

#[bitfield(u64)]
pub struct GicrSgi {
    pub target_list: u16,
    pub aff1: u8,
    #[bits(4)]
    pub intid: u32,
    #[bits(4)]
    _res_28_31: u16,
    pub aff2: u8,
    pub irm: bool,
    #[bits(3)]
    _res_41_43: u8,
    #[bits(4)]
    pub rs: u8,
    pub aff3: u8,
    _res_56_63: u8,
}