• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 
19 #include <stdio.h>
20 
21 #include <soc.h>
22 #include <target_config.h>
23 
24 #include <los_arch_interrupt.h>
25 #include <los_interrupt.h>
26 
27 #include <riscv_hal.h>
28 
29 #include <B91/plic.h>
30 
31 #define PLIC_IRQ_LIMIT 64
32 
33 typedef VOID (*HwiProcFunc)(VOID *arg);
34 
35 VOID default_irq_handler(VOID);
36 
37 STATIC HWI_HANDLE_FORM_S irq_handlers[PLIC_IRQ_LIMIT] = {
38     [0 ...(PLIC_IRQ_LIMIT - 1)] = {(HWI_PROC_FUNC)default_irq_handler, NULL, 0}};
39 
EnableIrq(UINT32 hwiNum)40 STATIC UINT32 EnableIrq(UINT32 hwiNum)
41 {
42     if (hwiNum > OS_HWI_MAX_NUM) {
43         return OS_ERRNO_HWI_NUM_INVALID;
44     }
45 
46     UINT32 intSave = LOS_IntLock();
47     if (hwiNum >= OS_RISCV_SYS_VECTOR_CNT) {
48         plic_interrupt_enable(hwiNum - OS_RISCV_SYS_VECTOR_CNT);
49         SET_CSR(mie, RISCV_MACH_EXT_IRQ);
50     } else {
51         UINT32 irq = hwiNum;
52         UINT32 mask = 1 << irq;
53         __asm__ volatile("csrs mie, %0" ::"r"(mask));
54     }
55 
56     LOS_IntRestore(intSave);
57     return LOS_OK;
58 }
59 
HalIrqEnable(UINT32 vector)60 VOID HalIrqEnable(UINT32 vector)
61 {
62     (VOID) EnableIrq(vector);
63 }
64 
DisableIrq(UINT32 hwiNum)65 STATIC UINT32 DisableIrq(UINT32 hwiNum)
66 {
67     if (hwiNum > OS_HWI_MAX_NUM) {
68         return OS_ERRNO_HWI_NUM_INVALID;
69     }
70 
71     UINT32 intSave = LOS_IntLock();
72     if (hwiNum >= OS_RISCV_SYS_VECTOR_CNT) {
73         plic_interrupt_disable(hwiNum - OS_RISCV_SYS_VECTOR_CNT);
74     } else {
75         UINT32 irq = hwiNum;
76         UINT32 mask = 1 << irq;
77         __asm__ volatile("csrc mie, %0" ::"r"(mask));
78     }
79 
80     LOS_IntRestore(intSave);
81     return LOS_OK;
82 }
83 
HalIrqDisable(UINT32 vector)84 VOID HalIrqDisable(UINT32 vector)
85 {
86     (VOID) DisableIrq(vector);
87 }
88 
HalSetLocalInterPri(UINT32 interPriNum,UINT16 prior)89 VOID HalSetLocalInterPri(UINT32 interPriNum, UINT16 prior)
90 {
91     plic_set_priority(interPriNum, prior);
92 }
93 
mext_irq_handler(void)94 _attribute_ram_code_ void mext_irq_handler(void)
95 {
96     unsigned int periph_irq = plic_interrupt_claim();
97 
98     HWI_HANDLE_FORM_S *hwiForm = &irq_handlers[periph_irq];
99     HwiProcFunc func = (HwiProcFunc)(hwiForm->pfnHook);
100     func(hwiForm->uwParam);
101 
102     plic_interrupt_complete(periph_irq); /* complete interrupt */
103 }
104 
B91IrqRegister(UINT32 irq_num,HWI_PROC_FUNC handler,HWI_ARG_T irqParam)105 UINT32 B91IrqRegister(UINT32 irq_num, HWI_PROC_FUNC handler, HWI_ARG_T irqParam)
106 {
107     if (irq_num >= PLIC_IRQ_LIMIT) {
108         return OS_ERRNO_HWI_NUM_INVALID;
109     }
110 
111     UINT32 intSave = LOS_IntLock();
112 
113     if (handler != NULL) {
114         irq_handlers[irq_num].pfnHook = handler;
115         irq_handlers[irq_num].uwParam = (VOID *)irqParam;
116     } else {
117         irq_handlers[irq_num].pfnHook = (HWI_PROC_FUNC)default_irq_handler;
118         irq_handlers[irq_num].uwParam = NULL;
119     }
120 
121     LOS_IntRestore(intSave);
122 
123     return LOS_OK;
124 }
125 
B91IrqInit(VOID)126 VOID B91IrqInit(VOID)
127 {
128     UINT32 ret = LOS_HwiCreate(RISCV_MACH_EXT_IRQ, OS_HWI_PRIO_LOWEST, 0, (HWI_PROC_FUNC)mext_irq_handler, 0);
129     if (ret != LOS_OK) {
130         printf("ret of LOS_HwiCreate(RISCV_MACH_EXT_IRQ) = %#x\r\n", ret);
131     }
132 
133     core_interrupt_enable();
134 }
135