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: 硬件GICR相关的处理。
14 */
15 #include "prt_gic_external.h"
16 #include "prt_gic_internal.h"
17 #include "prt_attr_external.h"
18
19 /* GICR_CTRL */
20 union GicrCtrl {
21 struct {
22 U32 enLpis : 1; // bit[0] LPIs中断使能控制寄存器
23 U32 res2 : 2; // bit[2:1]
24 U32 rwp : 1; // bit[3] 标识前面一次写GICR寄存器的配置信息是否生效
25 U32 res1 : 20; // bit[23:4]
26 U32 dpg0 : 1; // bit[24]
27 U32 dpg1ns : 1; // bit[25]
28 U32 dpg1s : 1; // bit[26]
29 U32 res0 : 4; // bit[30:27]
30 U32 uwp : 1; // bit[31] GICD对Upstream Write和Generate SGI是否可见
31 } bits;
32 U32 value;
33 };
34
35 /*
36 * 描述: 等待写寄存器操作生效
37 */
OsGicrWaitCfgWork(U32 coreId)38 OS_SEC_TEXT void OsGicrWaitCfgWork(U32 coreId)
39 {
40 union GicrCtrl gicrCtrl;
41 uintptr_t regAddr;
42
43 regAddr = GICR_CTRL_ADDR + (coreId * GICR_ADDR_OFFSET_PER_CORE);
44 do {
45 gicrCtrl.value = GIC_REG_READ(regAddr);
46 } while (gicrCtrl.bits.rwp == 1);
47 }
48
49 /*
50 * 描述: 获取PPI, SGI, NNSPI的使能状态, 调用者保证入参的有效性
51 */
OsGicrGetIntState(U32 coreId,U32 intId)52 OS_SEC_TEXT enum GicIntState OsGicrGetIntState(U32 coreId, U32 intId)
53 {
54 // 每个寄存器对应32个中断
55 return OsGicGetReg(GICR_ISENABLER0_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE,
56 GIC_IENABLE_INT_NUM, intId);
57 }
58
59 /*
60 * 描述: 使能PPI, SGI, NNSPI, 调用者保证入参的有效性
61 */
OsGicrEnableInt(U32 coreId,U32 intId)62 OS_SEC_TEXT void OsGicrEnableInt(U32 coreId, U32 intId)
63 {
64 // 每个寄存器对应32个中断,写1使能中断,写0无效
65 OsGicSetReg(GICR_ISENABLER0_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE,
66 GIC_IENABLE_INT_NUM, intId, 1);
67
68 OsGicrWaitCfgWork(coreId); // 确保操作生效
69 }
70
71 /*
72 * 描述: 去使能PPI, SGI, NNSPI, 调用者保证入参的有效性
73 */
OsGicrDisableInt(U32 coreId,U32 intId)74 OS_SEC_TEXT void OsGicrDisableInt(U32 coreId, U32 intId)
75 {
76 // 每个寄存器对应32个中断,写1去使能中断,写0无效
77 OsGicSetReg(GICR_ICENABLER0_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE,
78 GIC_IENABLE_INT_NUM, intId, 1);
79
80 OsGicrWaitCfgWork(coreId); // 确保操作生效
81 }
82
83 /*
84 * 描述: 设置SGI, PPI, NNSPI中断的优先级, 调用者保证入参的有效性
85 */
OsGicrSetPriority(U32 coreId,U32 intId,U32 priority)86 OS_SEC_L4_TEXT void OsGicrSetPriority(U32 coreId, U32 intId, U32 priority)
87 {
88 // 每个寄存器对应4个中断, 每8bit中的高4bit对应一个中断优先级
89 OsGicRmwReg(GICR_IPRIORITY_SGI_S_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE,
90 GIC_IPRIORITY_INT_NUM, intId, priority << GIC_IPRIORITY_HIGH_BIT);
91 }
92
93 /*
94 * 描述: 获取SGI, PPI, NNSPI中断的优先级, 调用者保证入参的有效性
95 */
OsGicrGetPriority(U32 coreId,U32 intId)96 OS_SEC_L2_TEXT U32 OsGicrGetPriority(U32 coreId, U32 intId)
97 {
98 U32 gicrPrio;
99
100 // 每个寄存器(32位)对应4个中断, 即每8bit对应1个中断
101 gicrPrio = OsGicGetReg(GICR_IPRIORITY_SGI_S_ADDR + coreId * GICR_ADDR_OFFSET_PER_CORE,
102 GIC_IPRIORITY_INT_NUM, intId);
103
104 return (gicrPrio >> GIC_IPRIORITY_HIGH_BIT); // 4: 每8bit中的高4bit对应一个中断的优先级, 低4bit预留。
105 }
106