1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-11-18
13 * Description: 硬件GICD相关的处理。
14 */
15 #include "prt_gic_external.h"
16 #include "prt_gic_internal.h"
17 #include "prt_attr_external.h"
18
19 /* GICD_ROUTER */
20 union GicdRouter {
21 struct {
22 U64 af0 : 2; // bit[1:0]
23 U64 res1 : 6; // bit[7:2]
24 U64 af1 : 2; // bit[9:8]
25 U64 res0 : 21; // bit[30:10]
26 U64 mode : 1; // bit[31]
27 U64 res2 : 32; // bit[32~63]
28 } bits;
29 U64 value;
30 };
31
32 /* GICD_CTRL */
33 union GicdCtrl {
34 struct {
35 U32 enG0S : 1; // bit[0] Enable Secure Group0 interrupt, Group0安全中断使能
36 U32 enG1Ns : 1; // bit[1] Enable Non-Secure Group1 interrupt, Group1非安全中断使能
37 U32 enG1S : 1; // bit[2] Enable Secure Group1 interrupt, Group1安全中断使能
38 U32 res1 : 1; // bit[3]
39 U32 areS : 1; // bit[4] Affinity Routing Eanble(for Secure)
40 U32 areNs : 1; // bit[5] 非安全状态下的关联路由使能
41 U32 ds : 1; // bit[6] Disable Security,当DS置1时,非安全操作可以访问Group0的配置寄存器
42 U32 res0 : 24; // bit[30:7]
43 U32 rwp : 1; // bit[31] 标识前面一次写GICD_CTLR寄存器的配置信息是否生效,0表示已生效
44 } bits;
45 U32 value;
46 };
47
48 /*
49 * 描述: 等待寄存器配置成功
50 */
OsGicdWaitCfgWork(void)51 OS_SEC_TEXT void OsGicdWaitCfgWork(void)
52 {
53 union GicdCtrl gicdCtrl;
54
55 do {
56 gicdCtrl.value = GIC_REG_READ(GICD_CTLR_S_ADDR);
57 } while (gicdCtrl.bits.rwp == 1);
58 }
59
60 /*
61 * 描述: 获取SPI中断的使能状态, 调用者保证入参的有效性
62 */
OsGicdGetIntState(U32 intId)63 OS_SEC_TEXT enum GicIntState OsGicdGetIntState(U32 intId)
64 {
65 // 每个寄存器对应32个中断
66 return OsGicGetReg(GICD_ISENABLER0_ADDR, GIC_IENABLE_INT_NUM, intId);
67 }
68
69 /*
70 * 描述: 使能SPI中断, 调用者保证入参的有效性
71 */
OsGicdEnableInt(U32 intId)72 OS_SEC_TEXT void OsGicdEnableInt(U32 intId)
73 {
74 // 每个寄存器对应32个中断,写1使能中断,写0无效
75 OsGicSetReg(GICD_ISENABLER0_ADDR, GIC_IENABLE_INT_NUM, intId, 1);
76
77 OsGicdWaitCfgWork();
78 }
79
80 /*
81 * 描述: 去使能SPI中断, 调用者保证入参的有效性
82 */
OsGicdDisableInt(U32 intId)83 OS_SEC_TEXT void OsGicdDisableInt(U32 intId)
84 {
85 // 每个寄存器对应32个中断,写1去使能中断,写0无效
86 OsGicSetReg(GICD_ICENABLER0_ADDR, GIC_IENABLE_INT_NUM, intId, 1);
87
88 OsGicdWaitCfgWork();
89 }
90
91 /*
92 * 描述: 设置SPI中断的优先级, 调用者保证入参的有效性
93 */
OsGicdSetPriority(U32 intId,U32 priority)94 OS_SEC_L4_TEXT void OsGicdSetPriority(U32 intId, U32 priority)
95 {
96 // 每个寄存器对应4个中断, 每8bit中的高4bit对应一个中断优先级
97 OsGicRmwReg(GICD_SGI_IPRIORITY_S_ADDR, GIC_IPRIORITY_INT_NUM, intId, priority << GIC_IPRIORITY_HIGH_BIT);
98 }
99
100 /*
101 * 描述: 获取SPI中断的优先级, 调用者保证入参的有效性
102 */
OsGicdGetPriority(U32 intId)103 OS_SEC_L4_TEXT U32 OsGicdGetPriority(U32 intId)
104 {
105 U32 priority;
106
107 // 每个寄存器对应4个中断
108 priority = OsGicGetReg(GICD_SGI_IPRIORITY_S_ADDR, GIC_IPRIORITY_INT_NUM, intId);
109
110 return priority >> GIC_IPRIORITY_HIGH_BIT; // 每8bit中的高4bit对应一个中断的优先级, 低4bit预留。
111 }
112
113 /*
114 * 描述: 配置SPI中断的目标核, 调用者保证入参的有效性
115 */
OsGicdCfgTargetId(U32 intId,U32 targetId)116 OS_SEC_TEXT void OsGicdCfgTargetId(U32 intId, U32 targetId)
117 {
118 union GicdRouter gicdRouter;
119 uintptr_t addr;
120
121 addr = OsGicGetRouterAddr(intId);
122 gicdRouter.value = GIC_REG_READ(addr);
123
124 /* 当前仅支持1-1模式 */
125 gicdRouter.bits.mode = 0x0;
126 if (g_gicCoreMap.bits.mt == 0) {
127 /* single-thread 模式下,核号取AFF0 */
128 gicdRouter.bits.af1 = 0;
129 gicdRouter.bits.af0 = targetId;
130 } else {
131 /* muti-thread 模式下,核号取AFF1 */
132 gicdRouter.bits.af0 = 0;
133 gicdRouter.bits.af1 = targetId;
134 }
135
136 GIC_REG_WRITE(addr, gicdRouter.value);
137 }
138