• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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