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