1/*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 *    conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 *    of conditions and the following disclaimer in the documentation and/or other materials
12 *    provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 *    to endorse or promote products derived from this software without specific prior written
16 *    permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "los_arch_interrupt.h"
32#include "los_debug.h"
33
34#ifdef __ICCARM__
35#pragma location = ".data.vector"
36#pragma data_alignment = LOSCFG_ARCH_HWI_VECTOR_ALIGN
37/* *
38 * @ingroup los_hwi
39 * Hardware interrupt form mapping handling function array.
40 */
41HWI_PROC_FUNC g_hwiForm[OS_VECTOR_CNT] = {0};
42#elif defined(__CC_ARM) || defined(__GNUC__)
43LITE_OS_SEC_VEC
44/* *
45 * @ingroup los_hwi
46 * Hardware interrupt form mapping handling function array.
47 */
48HWI_PROC_FUNC __attribute__((aligned(LOSCFG_ARCH_HWI_VECTOR_ALIGN))) g_hwiForm[OS_VECTOR_CNT] = {0};
49#endif
50
51VOID *ArchGetHwiFrom(VOID)
52{
53    return g_hwiForm;
54}
55
56UINT32 g_intCount = 0;
57
58/* ****************************************************************************
59 Function    : HalHwiDefaultHandler
60 Description : default handler of the hardware interrupt
61 Input       : None
62 Output      : None
63 Return      : None
64 **************************************************************************** */
65LITE_OS_SEC_TEXT_MINOR VOID HalHwiDefaultHandler(VOID)
66{
67    PRINT_ERR("%s irqnum:%u\n", __FUNCTION__, ArchIntCurIrqNum());
68    while (1) {}
69}
70
71WEAK VOID HalPreInterruptHandler(UINT32 arg)
72{
73    (VOID)arg;
74    return;
75}
76
77WEAK VOID HalAftInterruptHandler(UINT32 arg)
78{
79    (VOID)arg;
80    return;
81}
82
83#if (LOSCFG_DEBUG_TOOLS == 1)
84STATIC UINT32 g_hwiFormCnt[OS_HWI_MAX_NUM] = {0};
85STATIC CHAR *g_hwiFormName[OS_HWI_MAX_NUM] = {0};
86
87UINT32 OsGetHwiFormCnt(UINT32 index)
88{
89    return g_hwiFormCnt[index];
90}
91
92CHAR *OsGetHwiFormName(UINT32 index)
93{
94    return g_hwiFormName[index];
95}
96
97BOOL OsHwiIsCreated(UINT32 index)
98{
99    if (g_hwiForm[index] != (HWI_PROC_FUNC)HalHwiDefaultHandler) {
100        return TRUE;
101    }
102
103    return FALSE;
104}
105#endif
106
107#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
108
109/* *
110 * @ingroup los_hwi
111 * Hardware interrupt handler form mapping handling function array.
112 */
113HWI_HANDLER_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {{ (HWI_PROC_FUNC)0, (HWI_ARG_T)0 }};
114
115/* *
116 * @ingroup los_hwi
117 * Set interrupt vector table.
118 */
119VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector, VOID *arg)
120{
121    if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
122        g_hwiForm[num + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)HalInterrupt;
123        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pfnHandler = vector;
124        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pParm = arg;
125    }
126}
127#else
128/* *
129 * @ingroup los_hwi
130 * hardware interrupt handler form mapping handling function array.
131 */
132HWI_PROC_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {0};
133
134/* *
135 * @ingroup los_hwi
136 * Set interrupt vector table.
137 */
138VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector)
139{
140    if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
141        g_hwiForm[num + OS_SYS_VECTOR_CNT] = HalInterrupt;
142        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT] = vector;
143    }
144}
145#endif
146
147UINT32 ArchIntTrigger(HWI_HANDLE_T hwiNum)
148{
149    if (hwiNum >= OS_HWI_MAX_NUM) {
150        return OS_ERRNO_HWI_NUM_INVALID;
151    }
152
153    HwiControllerOps *hwiOps = ArchIntOpsGet();
154    if (hwiOps->triggerIrq == NULL) {
155        return OS_ERRNO_HWI_OPS_FUNC_NULL;
156    }
157
158    return hwiOps->triggerIrq(hwiNum);
159}
160
161UINT32 ArchIntEnable(HWI_HANDLE_T hwiNum)
162{
163    if (hwiNum >= OS_HWI_MAX_NUM) {
164        return OS_ERRNO_HWI_NUM_INVALID;
165    }
166
167    HwiControllerOps *hwiOps = ArchIntOpsGet();
168    if (hwiOps->enableIrq == NULL) {
169        return OS_ERRNO_HWI_OPS_FUNC_NULL;
170    }
171
172    return hwiOps->enableIrq(hwiNum);
173}
174
175UINT32 ArchIntDisable(HWI_HANDLE_T hwiNum)
176{
177    if (hwiNum >= OS_HWI_MAX_NUM) {
178        return OS_ERRNO_HWI_NUM_INVALID;
179    }
180
181    HwiControllerOps *hwiOps = ArchIntOpsGet();
182    if (hwiOps->disableIrq == NULL) {
183        return OS_ERRNO_HWI_OPS_FUNC_NULL;
184    }
185
186    return hwiOps->disableIrq(hwiNum);
187}
188
189UINT32 ArchIntClear(HWI_HANDLE_T hwiNum)
190{
191    if (hwiNum >= OS_HWI_MAX_NUM) {
192        return OS_ERRNO_HWI_NUM_INVALID;
193    }
194
195    HwiControllerOps *hwiOps = ArchIntOpsGet();
196    if (hwiOps->clearIrq == NULL) {
197        return OS_ERRNO_HWI_OPS_FUNC_NULL;
198    }
199
200    return hwiOps->clearIrq(hwiNum);
201}
202
203UINT32 ArchIntSetPriority(HWI_HANDLE_T hwiNum, HWI_PRIOR_T priority)
204{
205    if (hwiNum >= OS_HWI_MAX_NUM) {
206        return OS_ERRNO_HWI_NUM_INVALID;
207    }
208
209    if (priority > OS_HWI_PRIO_LOWEST) {
210        return OS_ERRNO_HWI_PRIO_INVALID;
211    }
212
213    HwiControllerOps *hwiOps = ArchIntOpsGet();
214    if (hwiOps->setIrqPriority == NULL) {
215        return OS_ERRNO_HWI_OPS_FUNC_NULL;
216    }
217
218    return hwiOps->setIrqPriority(hwiNum, priority);
219}
220
221UINT32 ArchIntCurIrqNum(VOID)
222{
223    HwiControllerOps *hwiOps = ArchIntOpsGet();
224    return hwiOps->getCurIrqNum();
225}
226
227/* ****************************************************************************
228 Function    : ArchHwiCreate
229 Description : create hardware interrupt
230 Input       : hwiNum   --- hwi num to create
231               hwiPrio  --- priority of the hwi
232               hwiMode  --- unused
233               hwiHandler --- hwi handler
234               irqParam --- param of the hwi handler
235 Output      : None
236 Return      : LOS_OK on success or error code on failure
237 **************************************************************************** */
238LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiCreate(HWI_HANDLE_T hwiNum, HWI_PRIOR_T hwiPrio,
239                                           HWI_MODE_T hwiMode, HWI_PROC_FUNC hwiHandler,
240                                           HwiIrqParam *irqParam)
241{
242    (VOID)hwiMode;
243    UINT32 intSave;
244
245    if (hwiHandler == NULL) {
246        return OS_ERRNO_HWI_PROC_FUNC_NULL;
247    }
248
249    if (hwiNum >= OS_HWI_MAX_NUM) {
250        return OS_ERRNO_HWI_NUM_INVALID;
251    }
252
253    if (g_hwiForm[hwiNum + OS_SYS_VECTOR_CNT] != (HWI_PROC_FUNC)HalHwiDefaultHandler) {
254        return OS_ERRNO_HWI_ALREADY_CREATED;
255    }
256
257    if (hwiPrio > OS_HWI_PRIO_LOWEST) {
258        return OS_ERRNO_HWI_PRIO_INVALID;
259    }
260
261    intSave = LOS_IntLock();
262
263#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
264    if (irqParam != NULL) {
265        OsSetVector(hwiNum, hwiHandler, irqParam->pDevId);
266    } else {
267        OsSetVector(hwiNum, hwiHandler, NULL);
268    }
269#else
270    (VOID)irqParam;
271    OsSetVector(hwiNum, hwiHandler);
272#endif
273
274#if (LOSCFG_DEBUG_TOOLS == 1)
275    if ((irqParam != NULL) && (irqParam->pName != NULL)) {
276        g_hwiFormName[hwiNum + OS_SYS_VECTOR_CNT] = (CHAR *)irqParam->pName;
277    }
278    g_hwiFormCnt[hwiNum + OS_SYS_VECTOR_CNT] = 0;
279#endif
280
281    HwiControllerOps *hwiOps = ArchIntOpsGet();
282    if (hwiOps->createIrq == NULL) {
283        LOS_IntRestore(intSave);
284        return OS_ERRNO_HWI_OPS_FUNC_NULL;
285    }
286    hwiOps->createIrq(hwiNum, hwiPrio);
287
288    LOS_IntRestore(intSave);
289
290    return LOS_OK;
291}
292
293/* ****************************************************************************
294 Function    : ArchHwiDelete
295 Description : Delete hardware interrupt
296 Input       : hwiNum   --- hwi num to delete
297               irqParam --- param of the hwi handler
298 Output      : None
299 Return      : LOS_OK on success or error code on failure
300 **************************************************************************** */
301LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiDelete(HWI_HANDLE_T hwiNum, HwiIrqParam *irqParam)
302{
303    (VOID)irqParam;
304    UINT32 intSave;
305
306    if (hwiNum >= OS_HWI_MAX_NUM) {
307        return OS_ERRNO_HWI_NUM_INVALID;
308    }
309
310    ArchIntDisable((IRQn_Type)hwiNum);
311
312    intSave = LOS_IntLock();
313
314    g_hwiForm[hwiNum + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)HalHwiDefaultHandler;
315
316    LOS_IntRestore(intSave);
317
318    return LOS_OK;
319}
320
321INLINE UINT32 ArchIsIntActive(VOID)
322{
323    return (g_intCount > 0);
324}
325