1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <hi_isr.h>
20 #include <los_hwi.h>
21 #include <linux/workqueue.h>
22 #include <los_exc.h>
23 #ifndef HAVE_PCLINT_CHECK
24 #include "encoding.h"
25 #endif
26
27
28 #define IRQ_WORD_LOW 0
29 #define IRQ_WORD_HIGH 1
30 #define IRQ_WORD_NUM 2
31 #define low_32bit(u64_data) ((hi_u32)((u64_data) & 0xFFFFFFFF))
32 #define high_32bit(u64_data) ((hi_u32)((((u64_data) >> 32) & 0xFFFFFFFF) << 32))
33 #define INT_DISABLE_BITS_ALL 0x0
34
35 volatile hi_u32 g_flash_irq_mask[IRQ_WORD_NUM] = {0}; /* flash处理时屏蔽中断, MACHINE_TIMER_IRQ对应的
36 系统timer中断默认不屏蔽 */
37 volatile hi_u32 g_flash_irq_backup[IRQ_WORD_NUM] = {0}; /* flash屏蔽前中断备份 */
38 volatile hi_u64 g_irq_force_mask_in_flash = 0; /* 中断服务程序不在flash中,可在flash操作过程中中断执行 */
39 volatile hi_u64 g_irq_force_unmask_in_flash = 0;
40
41 hi_u8 g_irq_prio_backup[OS_HWI_MAX_NUM] = {0}; /* irq priority backup for irq_enable */
42
disable_int_in_flash(hi_void)43 hi_void disable_int_in_flash(hi_void)
44 {
45 hi_u32 current_val;
46 hi_u32 int_value;
47 hi_u32 need_mask;
48
49 int_value = LOS_IntLock();
50 need_mask = (g_flash_irq_mask[IRQ_WORD_LOW] | low_32bit(g_irq_force_mask_in_flash));
51 need_mask &= ~(low_32bit(g_irq_force_unmask_in_flash));
52 if (need_mask) {
53 g_flash_irq_backup[IRQ_WORD_LOW] = READ_CSR(mie);
54 current_val = g_flash_irq_backup[IRQ_WORD_LOW];
55 WRITE_CSR(mie, current_val & (~need_mask));
56 }
57 need_mask = (g_flash_irq_mask[IRQ_WORD_HIGH] | high_32bit(g_irq_force_mask_in_flash));
58 need_mask &= ~(high_32bit(g_irq_force_unmask_in_flash));
59 if (need_mask) {
60 g_flash_irq_backup[IRQ_WORD_HIGH] = READ_CUSTOM_CSR(LOCIEN0);
61 current_val = g_flash_irq_backup[IRQ_WORD_HIGH];
62 WRITE_CUSTOM_CSR_VAL(LOCIEN0, current_val & (~need_mask));
63 }
64 LOS_IntRestore(int_value);
65 }
66
enable_int_in_flash(hi_void)67 hi_void enable_int_in_flash(hi_void)
68 {
69 hi_u32 current_val;
70 hi_u32 int_value;
71 hi_u32 need_mask;
72
73 int_value = LOS_IntLock();
74 need_mask = (g_flash_irq_mask[IRQ_WORD_LOW] | low_32bit(g_irq_force_mask_in_flash));
75 need_mask &= ~(low_32bit(g_irq_force_unmask_in_flash));
76 if (need_mask) {
77 current_val = READ_CSR(mie);
78 WRITE_CSR(mie, current_val | g_flash_irq_backup[IRQ_WORD_LOW]);
79 }
80 need_mask = (g_flash_irq_mask[IRQ_WORD_HIGH] | high_32bit(g_irq_force_mask_in_flash));
81 need_mask &= ~(high_32bit(g_irq_force_unmask_in_flash));
82 if (need_mask) {
83 current_val = READ_CUSTOM_CSR(LOCIEN0);
84 WRITE_CUSTOM_CSR_VAL(LOCIEN0, current_val | g_flash_irq_backup[IRQ_WORD_HIGH]);
85 }
86 LOS_IntRestore(int_value);
87 }
88
disable_all_ints(hi_void)89 hi_void disable_all_ints(hi_void)
90 {
91 WRITE_CSR(mie, INT_DISABLE_BITS_ALL);
92 WRITE_CUSTOM_CSR_VAL(LOCIEN0, INT_DISABLE_BITS_ALL);
93 }
94
set_force_int_mask_in_flash(hi_u64 mask)95 hi_u64 set_force_int_mask_in_flash(hi_u64 mask)
96 {
97 hi_u32 int_value;
98 int_value = LOS_IntLock();
99 g_irq_force_mask_in_flash |= mask;
100 g_irq_force_unmask_in_flash &= ~mask;
101 LOS_IntRestore(int_value);
102 return g_irq_force_mask_in_flash;
103 }
104
set_force_int_unmask_in_flash(hi_u64 unmask)105 hi_u64 set_force_int_unmask_in_flash(hi_u64 unmask)
106 {
107 hi_u32 int_value;
108 int_value = LOS_IntLock();
109 g_irq_force_unmask_in_flash |= unmask;
110 g_irq_force_mask_in_flash &= ~unmask;
111 LOS_IntRestore(int_value);
112 return g_irq_force_unmask_in_flash;
113 }
114
hi_int_lock(hi_void)115 hi_u32 hi_int_lock(hi_void)
116 {
117 return LOS_IntLock();
118 }
119
hi_int_restore(hi_u32 int_value)120 hi_void hi_int_restore(hi_u32 int_value)
121 {
122 LOS_IntRestore(int_value);
123 }
124
hi_irq_enable(hi_u32 vector)125 hi_u32 hi_irq_enable(hi_u32 vector)
126 {
127 if (g_hook_osa.hi_irq_enable_hook != HI_NULL) {
128 return g_hook_osa.hi_irq_enable_hook(vector);
129 }
130
131 if (vector >= OS_HWI_MAX_NUM) {
132 return HI_ERR_ISR_INVALID_PARAM;
133 }
134 hi_u32 ret;
135
136 ret = LOS_AdapIrqEnable(vector, g_irq_prio_backup[vector]);
137 if (ret != LOS_OK) {
138 if (ret == OS_ERRNO_HWI_NOT_CREATED) {
139 return HI_ERR_ISR_NOT_CREATED;
140 } else {
141 return HI_ERR_ISR_ENABLE_IRQ_FAIL;
142 }
143 }
144 return HI_ERR_SUCCESS;
145 }
146
hi_irq_disable(hi_u32 vector)147 hi_void hi_irq_disable(hi_u32 vector)
148 {
149 if (g_hook_osa.hi_irq_disable_hook != HI_NULL) {
150 g_hook_osa.hi_irq_disable_hook(vector);
151 return;
152 }
153
154 if (vector >= OS_HWI_MAX_NUM) {
155 return;
156 }
157
158 LOS_AdapIrqDisable(vector);
159 }
160
set_mask(hi_u32 vector)161 hi_void set_mask(hi_u32 vector)
162 {
163 if (vector < OS_HIMIDEER_MIE_TOTAL_CNT) {
164 g_flash_irq_mask[IRQ_WORD_LOW] |= 1 << vector;
165 } else {
166 g_flash_irq_mask[IRQ_WORD_HIGH] |= 1 << (vector - OS_HIMIDEER_MIE_TOTAL_CNT);
167 }
168 }
reset_mask(hi_u32 vector)169 hi_void reset_mask(hi_u32 vector)
170 {
171 if (vector < OS_HIMIDEER_MIE_TOTAL_CNT) {
172 g_flash_irq_mask[IRQ_WORD_LOW] &= ~(hi_u32)(1 << vector);
173 } else {
174 g_flash_irq_mask[IRQ_WORD_HIGH] &= ~(hi_u32)(1 << (vector - OS_HIMIDEER_MIE_TOTAL_CNT));
175 }
176 }
177
hi_irq_request(hi_u32 vector,hi_u32 flags,irq_routine routine,uintptr_t param)178 hi_u32 hi_irq_request(hi_u32 vector, hi_u32 flags, irq_routine routine, uintptr_t param)
179 {
180 hi_u32 ret;
181 hi_u16 pri = flags & HI_IRQ_FLAG_PRI_MASK;
182
183 if (g_hook_osa.hi_irq_request_hook != HI_NULL) {
184 return g_hook_osa.hi_irq_request_hook(vector, flags, routine, param);
185 }
186
187 if ((routine == HI_NULL) || (vector >= OS_HWI_MAX_NUM) || (pri == 0)) {
188 return HI_ERR_ISR_INVALID_PARAM;
189 }
190 if ((flags & HI_IRQ_FLAG_NOT_IN_FLASH) &&
191 (((uintptr_t)routine >= HI_FLASH_BASE) && ((uintptr_t)routine < HI_FLASH_BASE + HI_FLASH_SIZE))) {
192 return HI_ERR_ISR_IRQ_ADDR_NOK;
193 }
194 if ((flags & HI_IRQ_FLAG_NOT_IN_FLASH) == 0) {
195 set_mask(vector);
196 }
197
198 g_irq_prio_backup[vector] = (hi_u8)pri;
199 ret = LOS_HwiCreate(vector, pri, 0, (HWI_PROC_FUNC)routine, param);
200 if (ret != LOS_OK) {
201 if (ret == OS_ERRNO_HWI_ALREADY_CREATED) {
202 return HI_ERR_ISR_ALREADY_CREATED;
203 } else {
204 return HI_ERR_ISR_REQ_IRQ_FAIL;
205 }
206 }
207
208 return HI_ERR_SUCCESS;
209 }
210
hi_irq_free(hi_u32 vector)211 hi_u32 hi_irq_free(hi_u32 vector)
212 {
213 hi_u32 ret;
214
215 if (g_hook_osa.hi_irq_free_hook != HI_NULL) {
216 return g_hook_osa.hi_irq_free_hook(vector);
217 }
218 /* los接口内判断了vector合法性 */
219 ret = LOS_HwiDelete(vector);
220 reset_mask(vector);
221 if (ret != LOS_OK) {
222 return HI_ERR_ISR_DEL_IRQ_FAIL;
223 }
224
225 return HI_ERR_SUCCESS;
226 }
227
hi_is_int_context(hi_void)228 hi_bool hi_is_int_context(hi_void)
229 {
230 if (g_hook_osa.hi_is_int_context_hook != HI_NULL) {
231 return g_hook_osa.hi_is_int_context_hook();
232 }
233
234 return (hi_bool)OS_INT_ACTIVE;
235 }
236