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