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
34UINT32 g_intCount = 0;
35
36/* *
37 * @ingroup los_hwi
38 * Hardware interrupt form mapping handling function array.
39 */
40HWI_PROC_FUNC __attribute__((aligned(LOSCFG_ARCH_HWI_VECTOR_ALIGN))) g_hwiForm[OS_VECTOR_CNT] = {0};
41
42VOID *ArchGetHwiFrom(VOID)
43{
44    return g_hwiForm;
45}
46
47/* ****************************************************************************
48 Function    : HalHwiDefaultHandler
49 Description : default handler of the hardware interrupt
50 Input       : None
51 Output      : None
52 Return      : None
53 **************************************************************************** */
54VOID HalHwiDefaultHandler(VOID)
55{
56    PRINT_ERR("%s irqnum:%u\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_SYS_VECTOR_CNT) && (num <= OS_VECTOR_CNT);
75}
76
77UINT32 ArchIntTrigger(HWI_HANDLE_T hwiNum)
78{
79    if (!HwiNumValid(hwiNum)) {
80        return OS_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 OS_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 OS_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 OS_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 ArchIntCurIrqNum(VOID)
134{
135    HwiControllerOps *hwiOps = ArchIntOpsGet();
136    return hwiOps->getCurIrqNum();
137}
138
139#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
140
141/* *
142 * @ingroup los_hwi
143 * Hardware interrupt handler form mapping handling function array.
144 */
145HWI_HANDLER_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {{ (HWI_PROC_FUNC)0, (HWI_ARG_T)0 }};
146
147/* *
148 * @ingroup los_hwi
149 * Set interrupt vector table.
150 */
151VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector, VOID *arg)
152{
153    if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
154        g_hwiForm[num + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)HalInterrupt;
155        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pfnHandler = vector;
156        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT].pParm = arg;
157    }
158}
159
160#else
161/* *
162 * @ingroup los_hwi
163 * Hardware interrupt handler form mapping handling function array.
164 */
165HWI_PROC_FUNC g_hwiHandlerForm[OS_VECTOR_CNT] = {0};
166
167/* *
168 * @ingroup los_hwi
169 * Set interrupt vector table.
170 */
171VOID OsSetVector(UINT32 num, HWI_PROC_FUNC vector)
172{
173    if ((num + OS_SYS_VECTOR_CNT) < OS_VECTOR_CNT) {
174        g_hwiForm[num + OS_SYS_VECTOR_CNT] = HalInterrupt;
175        g_hwiHandlerForm[num + OS_SYS_VECTOR_CNT] = vector;
176    }
177}
178#endif
179
180/* ****************************************************************************
181 Function    : ArchHwiCreate
182 Description : create hardware interrupt
183 Input       : hwiNum   --- hwi num to create
184               hwiPrio  --- priority of the hwi
185               hwiMode  --- unused
186               hwiHandler --- hwi handler
187               irqParam --- param of the hwi handler
188 Output      : None
189 Return      : LOS_OK on success or error code on failure
190 **************************************************************************** */
191UINT32 ArchHwiCreate(HWI_HANDLE_T hwiNum,
192                     HWI_PRIOR_T hwiPrio,
193                     HWI_MODE_T hwiMode,
194                     HWI_PROC_FUNC hwiHandler,
195                     HwiIrqParam *irqParam)
196{
197    (VOID)hwiMode;
198    UINT32 intSave;
199
200    if (hwiHandler == NULL) {
201        return OS_ERRNO_HWI_PROC_FUNC_NULL;
202    }
203
204    if (hwiNum >= OS_HWI_MAX_NUM) {
205        return OS_ERRNO_HWI_NUM_INVALID;
206    }
207
208    if (g_hwiForm[hwiNum + OS_SYS_VECTOR_CNT] != (HWI_PROC_FUNC)HalHwiDefaultHandler) {
209        return OS_ERRNO_HWI_ALREADY_CREATED;
210    }
211
212    if (hwiPrio > OS_HWI_PRIO_LOWEST) {
213        return OS_ERRNO_HWI_PRIO_INVALID;
214    }
215
216    intSave = LOS_IntLock();
217#if (LOSCFG_PLATFORM_HWI_WITH_ARG == 1)
218    if (irqParam != NULL) {
219        OsSetVector(hwiNum, hwiHandler, irqParam->pDevId);
220    } else {
221        OsSetVector(hwiNum, hwiHandler, NULL);
222    }
223#else
224    (VOID)irqParam;
225    OsSetVector(hwiNum, hwiHandler);
226#endif
227
228    HwiControllerOps *hwiOps = ArchIntOpsGet();
229    if (hwiOps->createIrq == NULL) {
230        LOS_IntRestore(intSave);
231        return OS_ERRNO_HWI_OPS_FUNC_NULL;
232    }
233    hwiOps->createIrq(hwiNum, hwiPrio);
234
235    LOS_IntRestore(intSave);
236
237    return LOS_OK;
238}
239
240/* ****************************************************************************
241 Function    : ArchHwiDelete
242 Description : Delete hardware interrupt
243 Input       : hwiNum   --- hwi num to delete
244               irqParam --- param of the hwi handler
245 Output      : None
246 Return      : LOS_OK on success or error code on failure
247 **************************************************************************** */
248LITE_OS_SEC_TEXT_INIT UINT32 ArchHwiDelete(HWI_HANDLE_T hwiNum, HwiIrqParam *irqParam)
249{
250    (VOID)irqParam;
251    UINT32 intSave;
252
253    if (hwiNum >= OS_HWI_MAX_NUM) {
254        return OS_ERRNO_HWI_NUM_INVALID;
255    }
256
257    ArchIntDisable(hwiNum);
258
259    intSave = LOS_IntLock();
260
261    g_hwiForm[hwiNum + OS_SYS_VECTOR_CNT] = (HWI_PROC_FUNC)HalHwiDefaultHandler;
262
263    LOS_IntRestore(intSave);
264
265    return LOS_OK;
266}
267
268UINT32 ArchIsIntActive(VOID)
269{
270    return (g_intCount > 0);
271}
272