hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*
 * GIC Initialization Routines.
 *
 * (C) Copyright 2013
 * David Feng <fenghua@phytium.com.cn>
 *
 * SPDX-License-Identifier:    GPL-2.0+
 */
 
#include <asm-offsets.h>
#include <config.h>
#include <linux/linkage.h>
#include <asm/gic.h>
#include <asm/macro.h>
 
 
/*************************************************************************
 *
 * void gic_init_secure(DistributorBase);
 *
 * Initialize secure copy of GIC at EL3.
 *
 *************************************************************************/
ENTRY(gic_init_secure)
   /*
    * Initialize Distributor
    * x0: Distributor Base
    */
#if defined(CONFIG_GICV3)
   mov    w9, #0x37        /* EnableGrp0 | EnableGrp1NS */
                   /* EnableGrp1S | ARE_S | ARE_NS */
   str    w9, [x0, GICD_CTLR]    /* Secure GICD_CTLR */
   ldr    w9, [x0, GICD_TYPER]
   and    w10, w9, #0x1f        /* ITLinesNumber */
   cbz    w10, 1f            /* No SPIs */
   add    x11, x0, (GICD_IGROUPRn + 4)
   add    x12, x0, (GICD_IGROUPMODRn + 4)
   mov    w9, #~0
0:    str    w9, [x11], #0x4
   str    wzr, [x12], #0x4    /* Config SPIs as Group1NS */
   sub    w10, w10, #0x1
   cbnz    w10, 0b
#elif defined(CONFIG_GICV2)
   mov    w9, #0x3        /* EnableGrp0 | EnableGrp1 */
   str    w9, [x0, GICD_CTLR]    /* Secure GICD_CTLR */
   ldr    w9, [x0, GICD_TYPER]
   and    w10, w9, #0x1f        /* ITLinesNumber */
   cbz    w10, 1f            /* No SPIs */
   add    x11, x0, GICD_IGROUPRn
   mov    w9, #~0            /* Config SPIs as Grp1 */
   str    w9, [x11], #0x4
0:    str    w9, [x11], #0x4
   sub    w10, w10, #0x1
   cbnz    w10, 0b
 
   ldr    x1, =GICC_BASE        /* GICC_CTLR */
   mov    w0, #3            /* EnableGrp0 | EnableGrp1 */
   str    w0, [x1]
 
   mov    w0, #1 << 7        /* allow NS access to GICC_PMR */
   str    w0, [x1, #4]        /* GICC_PMR */
#endif
1:
   ret
ENDPROC(gic_init_secure)
 
 
/*************************************************************************
 * For Gicv2:
 * void gic_init_secure_percpu(DistributorBase, CpuInterfaceBase);
 * For Gicv3:
 * void gic_init_secure_percpu(ReDistributorBase);
 *
 * Initialize secure copy of GIC at EL3.
 *
 *************************************************************************/
ENTRY(gic_init_secure_percpu)
#if defined(CONFIG_GICV3)
   /*
    * Initialize ReDistributor
    * x0: ReDistributor Base
    */
   mrs    x10, mpidr_el1
   lsr    x9, x10, #32
   bfi    x10, x9, #24, #8    /* w10 is aff3:aff2:aff1:aff0 */
   mov    x9, x0
1:    ldr    x11, [x9, GICR_TYPER]
   lsr    x11, x11, #32        /* w11 is aff3:aff2:aff1:aff0 */
   cmp    w10, w11
   b.eq    2f
   add    x9, x9, #(2 << 16)
   b    1b
 
   /* x9: ReDistributor Base Address of Current CPU */
2:    mov    w10, #~0x2
   ldr    w11, [x9, GICR_WAKER]
   and    w11, w11, w10        /* Clear ProcessorSleep */
   str    w11, [x9, GICR_WAKER]
   dsb    st
   isb
3:    ldr    w10, [x9, GICR_WAKER]
   tbnz    w10, #2, 3b        /* Wait Children be Alive */
 
   add    x10, x9, #(1 << 16)    /* SGI_Base */
   mov    w11, #~0
   str    w11, [x10, GICR_IGROUPRn]
   str    wzr, [x10, GICR_IGROUPMODRn]    /* SGIs|PPIs Group1NS */
   mov    w11, #0x1        /* Enable SGI 0 */
   str    w11, [x10, GICR_ISENABLERn]
 
#if CONFIG_IS_ENABLED(IRQ)
   /* Rockchip: check elx */
   switch_el x0, el3_sre, el2_sre, el1_sre
 
   /* Initialize Cpu Interface */
el3_sre:
   mrs    x10, ICC_SRE_EL3
   orr    x10, x10, #0xf        /* SRE & Disable IRQ/FIQ Bypass & */
                   /* Allow EL2 access to ICC_SRE_EL2 */
   msr    ICC_SRE_EL3, x10
   isb
 
el2_sre:
   mrs    x10, ICC_SRE_EL2
   orr    x10, x10, #0xf        /* SRE & Disable IRQ/FIQ Bypass & */
                   /* Allow EL1 access to ICC_SRE_EL1 */
   msr    ICC_SRE_EL2, x10
   isb
 
el1_sre:
   mrs    x0, CurrentEL        /* check currentEL */
   cmp    x0, 0xC
   b.ne    el1_ctlr        /* currentEL != EL3 */
 
el3_ctlr:
   mov    x10, #0x3        /* EnableGrp1NS | EnableGrp1S */
   msr    ICC_IGRPEN1_EL3, x10
   isb
 
   msr    ICC_CTLR_EL3, xzr
   isb
 
el1_ctlr:
   mov    x10, #0x3        /* EnableGrp1NS | EnableGrp1S */
   msr    ICC_IGRPEN1_EL1, x10
   isb
 
   msr    ICC_CTLR_EL1, xzr    /* NonSecure ICC_CTLR_EL1 */
   isb
 
   mov    x10, #0xf0        /* Non-Secure access to ICC_PMR_EL1 */
   msr    ICC_PMR_EL1, x10
   isb
#else
   /* Initialize Cpu Interface */
   mrs    x10, ICC_SRE_EL3
   orr    x10, x10, #0xf        /* SRE & Disable IRQ/FIQ Bypass & */
                   /* Allow EL2 access to ICC_SRE_EL2 */
   msr    ICC_SRE_EL3, x10
   isb
 
   mrs    x10, ICC_SRE_EL2
   orr    x10, x10, #0xf        /* SRE & Disable IRQ/FIQ Bypass & */
                   /* Allow EL1 access to ICC_SRE_EL1 */
   msr    ICC_SRE_EL2, x10
   isb
 
   mov    x10, #0x3        /* EnableGrp1NS | EnableGrp1S */
   msr    ICC_IGRPEN1_EL3, x10
   isb
 
   msr    ICC_CTLR_EL3, xzr
   isb
 
   msr    ICC_CTLR_EL1, xzr    /* NonSecure ICC_CTLR_EL1 */
   isb
 
   mov    x10, #0x1 << 7        /* Non-Secure access to ICC_PMR_EL1 */
   msr    ICC_PMR_EL1, x10
   isb
#endif
 
#elif defined(CONFIG_GICV2)
   /*
    * Initialize SGIs and PPIs
    * x0: Distributor Base
    * x1: Cpu Interface Base
    */
   mov    w9, #~0            /* Config SGIs and PPIs as Grp1 */
   str    w9, [x0, GICD_IGROUPRn]    /* GICD_IGROUPR0 */
   mov    w9, #0x1        /* Enable SGI 0 */
   str    w9, [x0, GICD_ISENABLERn]
 
   /* Initialize Cpu Interface */
   mov    w9, #0x1e7        /* Disable IRQ/FIQ Bypass & */
                   /* Enable Ack Group1 Interrupt & */
                   /* EnableGrp0 & EnableGrp1 */
   str    w9, [x1, GICC_CTLR]    /* Secure GICC_CTLR */
 
   mov    w9, #0x1 << 7        /* Non-Secure access to GICC_PMR */
   str    w9, [x1, GICC_PMR]
#endif
   ret
ENDPROC(gic_init_secure_percpu)
 
 
/*************************************************************************
 * For Gicv2:
 * void gic_kick_secondary_cpus(DistributorBase);
 * For Gicv3:
 * void gic_kick_secondary_cpus(void);
 *
 *************************************************************************/
ENTRY(gic_kick_secondary_cpus)
#if defined(CONFIG_GICV3)
   mov    x9, #(1 << 40)
   msr    ICC_ASGI1R_EL1, x9
   isb
#elif defined(CONFIG_GICV2)
   mov    w9, #0x8000
   movk    w9, #0x100, lsl #16
   str    w9, [x0, GICD_SGIR]
#endif
   ret
ENDPROC(gic_kick_secondary_cpus)
 
 
/*************************************************************************
 * For Gicv2:
 * void gic_wait_for_interrupt(CpuInterfaceBase);
 * For Gicv3:
 * void gic_wait_for_interrupt(void);
 *
 * Wait for SGI 0 from master.
 *
 *************************************************************************/
ENTRY(gic_wait_for_interrupt)
#if defined(CONFIG_GICV3)
   gic_wait_for_interrupt_m x9
#elif defined(CONFIG_GICV2)
   gic_wait_for_interrupt_m x0, w9
#endif
   ret
ENDPROC(gic_wait_for_interrupt)