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/* *
35 * @ingroup los_hwi
36 * Hardware interrupt form mapping handling function array.
37 */
38HWI_PROC_FUNC __attribute__((aligned(HWI_ALIGNSIZE))) g_hwiForm[OS_VECTOR_CNT] = {0};
39
40VOID *ArchGetHwiFrom(VOID)
41{
42    return g_hwiForm;
43}
44
45UINT32 volatile g_intCount = 0;
46
47/* ****************************************************************************
48 Function    : HalHwiDefaultHandler
49 Description : default handler of the hardware interrupt
50 Input       : None
51 Output      : None
52 Return      : None
53 **************************************************************************** */
54LITE_OS_SEC_TEXT_MINOR VOID HalHwiDefaultHandler(VOID)
55{
56    PRINT_ERR("%s irqnum:%x\n", __FUNCTION__, ArchIntCurIrqNum());
57    while (1) {}
58}
59
60WEAK VOID HalPreInterruptHandler(UINT32 arg)
61{
62    (VOID)arg;
63    return;
64}
65
66WEAK VOID HalAftInterruptHandler(UINT32 arg)
67{
68    (VOID)arg;
69    return;
70}
71
72STATIC UINT32 HwiNumValid(UINT32 num)
73{
74    return ((num) >= OS_USER_HWI_MIN) && ((num) <= OS_USER_HWI_MAX);
75}
76
77UINT32 ArchIntTrigger(HWI_HANDLE_T hwiNum)
78{
79    if (!HwiNumValid(hwiNum)) {
80        return LOS_ERRNO_HWI_NUM_INVALID;
81    }
82
83    HwiControllerOps *hwiOps = ArchIntOpsGet();
84    if (hwiOps->triggerIrq == NULL) {
85        return OS_ERRNO_HWI_OPS_FUNC_NULL;
86    }
87
88    return hwiOps->triggerIrq(hwiNum);
89}
90
91UINT32 ArchIntEnable(HWI_HANDLE_T hwiNum)
92{
93    if (!HwiNumValid(hwiNum)) {
94        return LOS_ERRNO_HWI_NUM_INVALID;
95    }
96
97    HwiControllerOps *hwiOps = ArchIntOpsGet();
98    if (hwiOps->enableIrq == NULL) {
99        return OS_ERRNO_HWI_OPS_FUNC_NULL;
100    }
101
102    return hwiOps->enableIrq(hwiNum);
103}
104
105UINT32 ArchIntDisable(HWI_HANDLE_T hwiNum)
106{
107    if (!HwiNumValid(hwiNum)) {
108        return LOS_ERRNO_HWI_NUM_INVALID;
109    }
110
111    HwiControllerOps *hwiOps = ArchIntOpsGet();
112    if (hwiOps->disableIrq == NULL) {
113        return OS_ERRNO_HWI_OPS_FUNC_NULL;
114    }
115
116    return hwiOps->disableIrq(hwiNum);
117}
118
119UINT32 ArchIntClear(HWI_HANDLE_T hwiNum)
120{
121    if (!HwiNumValid(hwiNum)) {
122        return LOS_ERRNO_HWI_NUM_INVALID;
123    }
124
125    HwiControllerOps *hwiOps = ArchIntOpsGet();
126    if (hwiOps->clearIrq == NULL) {
127        return OS_ERRNO_HWI_OPS_FUNC_NULL;
128    }
129
130    return hwiOps->clearIrq(hwiNum);
131}
132
133UINT32 ArchIntSetPriority(HWI_HANDLE_T hwiNum, HWI_PRIOR_T priority)
134{
135    if (!HwiNumValid(hwiNum)) {
136        return LOS_ERRNO_HWI_NUM_INVALID;
137    }
138
139    if (!HWI_PRI_VALID(priority)) {
140        return OS_ERRNO_HWI_PRIO_INVALID;
141    }
142
143    HwiControllerOps *hwiOps = ArchIntOpsGet();
144    if (hwiOps->setIrqPriority == NULL) {
145        return OS_ERRNO_HWI_OPS_FUNC_NULL;
146    }
147
148    return hwiOps->setIrqPriority(hwiNum, priority);
149}
150
151UINT32 ArchIntCurIrqNum(VOID)
152{
153    HwiControllerOps *hwiOps = ArchIntOpsGet();
154    return hwiOps->getCurIrqNum();
155}
156
157#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
158
159/* *
160 * @ingroup los_hwi
161 * Hardware interrupt handler form mapping handling function array.
162 */
163HWI_HANDLER_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {{ (HWI_PROC_FUNC)0, (HWI_ARG_T)0 }};
164
165/* *
166 * @ingroup los_hwi
167 * Set interrupt vector table.
168 */
169VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector, VOID *arg)
170{
171    if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
172        g_hwiForm[num + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)IrqEntry;
173        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pfnHandler = vector;
174        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pParm = arg;
175        ArchIntEnable(num);
176    }
177}
178#else
179/* *
180 * @ingroup los_hwi
181 * Hardware interrupt handler form mapping handling function array.
182 */
183HWI_PROC_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {0};
184
185/* *
186 * @ingroup los_hwi
187 * Set interrupt vector table.
188 */
189VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector)
190{
191    if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
192        g_hwiForm[num + OS_SYS_VECTOR_CNT] = IrqEntry;
193        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT] = vector;
194        ArchIntEnable(num);
195    }
196}
197#endif
198
199/* ****************************************************************************
200 Function    : ArchHwiCreate
201 Description : create hardware interrupt
202 Input       : hwiNum   --- hwi num to create
203               hwiPrio  --- priority of the hwi
204               hwiMode  --- unused
205               hwiHandler  --- hwi handler
206               irqParam --- param of the hwi handler
207 Output      : None
208 Return      : LOS_OK on success or error code on failure
209 **************************************************************************** */
210LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiCreate(HWI_HANDLE_T hwiNum, HWI_PRIOR_T hwiPrio,
211                                           HWI_MODE_T hwiMode, HWI_PROC_FUNC hwiHandler,
212                                           HwiIrqParam *irqParam)
213{
214    (VOID)hwiMode;
215    UINT32 intSave;
216
217    if (hwiHandler == NULL) {
218        return OS_ERRNO_HWI_PROC_FUNC_NULL;
219    }
220    if (hwiNum >= OS_HWI_MAX_NUM) {
221        return OS_ERRNO_HWI_NUM_INVALID;
222    }
223    if (g_hwiHandlerForm[hwiNum + OS_SYS_VECTOR_CNT] != 0) {
224        return OS_ERRNO_HWI_ALREADY_CREATED;
225    }
226    if (g_hwiHandlerForm[hwiNum + OS_SYS_VECTOR_CNT] != 0) {
227        return OS_ERRNO_HWI_ALREADY_CREATED;
228    }
229    if (hwiPrio > OS_HWI_PRIO_LOWEST) {
230        return OS_ERRNO_HWI_PRIO_INVALID;
231    }
232    intSave = LOS_IntLock();
233#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
234    if (irqParam != NULL) {
235        OsSetVector(hwiNum, hwiHandler, irqParam->pDevId);
236    } else {
237        OsSetVector(hwiNum, hwiHandler, NULL);
238    }
239#else
240    (VOID)irqParam;
241    OsSetVector(hwiNum, hwiHandler);
242#endif
243
244    HwiControllerOps *hwiOps = ArchIntOpsGet();
245    if (hwiOps->createIrq == NULL) {
246        LOS_IntRestore(intSave);
247        return OS_ERRNO_HWI_OPS_FUNC_NULL;
248    }
249    hwiOps->createIrq(hwiNum, hwiPrio);
250
251    LOS_IntRestore(intSave);
252
253    return LOS_OK;
254}
255
256/* ****************************************************************************
257 Function    : ArchHwiDelete
258 Description : Delete hardware interrupt
259 Input       : hwiNum   --- hwi num to delete
260               irqParam --- param of the hwi handler
261 Output      : None
262 Return      : LOS_OK on success or error code on failure
263 **************************************************************************** */
264LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiDelete(HWI_HANDLE_T hwiNum, HwiIrqParam *irqParam)
265{
266    (VOID)irqParam;
267    UINT32 intSave;
268
269    if (hwiNum >= OS_HWI_MAX_NUM) {
270        return OS_ERRNO_HWI_NUM_INVALID;
271    }
272
273    ArchIntDisable((IRQn_Type)hwiNum);
274
275    intSave = LOS_IntLock();
276    g_hwiHandlerForm[hwiNum + OS_SYS_VECTOR_CNT] = 0;
277    LOS_IntRestore(intSave);
278
279    return LOS_OK;
280}
281
282UINT32 ArchIsIntActive(VOID)
283{
284    return (g_intCount > 0);
285}
286