Skip to content

Commit 1939571

Browse files
committed
drivers: interrupt-controller: add Nuclei ECLIC driver
Add support for the ECLIC interrupt controller which is used with the Nuclei processor core. Signed-off-by: TOKITA Hiroshi <[email protected]>
1 parent 1f16638 commit 1939571

File tree

13 files changed

+270
-7
lines changed

13 files changed

+270
-7
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@
276276
/drivers/interrupt_controller/ @dcpleung @nashif
277277
/drivers/interrupt_controller/intc_gic.c @stephanosio
278278
/drivers/interrupt_controller/*esp32* @glaubermaroto
279+
/drivers/interrupt_controller/intc_nuclei_eclic.c @soburi
279280
/drivers/ipm/ipm_mhu* @karl-zh
280281
/drivers/ipm/Kconfig.nrfx @masz-nordic
281282
/drivers/ipm/Kconfig.nrfx_ipc_channel @masz-nordic

drivers/interrupt_controller/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ zephyr_library_sources_ifdef(CONFIG_INTC_ESP32 intc_esp32.c)
2626
zephyr_library_sources_ifdef(CONFIG_INTC_ESP32C3 intc_esp32c3.c)
2727
zephyr_library_sources_ifdef(CONFIG_SWERV_PIC intc_swerv_pic.c)
2828
zephyr_library_sources_ifdef(CONFIG_VEXRISCV_LITEX_IRQ intc_vexriscv_litex.c)
29+
zephyr_library_sources_ifdef(CONFIG_NUCLEI_ECLIC intc_nuclei_eclic.c)

drivers/interrupt_controller/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,6 @@ source "drivers/interrupt_controller/Kconfig.esp32c3"
7373

7474
source "drivers/interrupt_controller/Kconfig.xec"
7575

76+
source "drivers/interrupt_controller/Kconfig.eclic"
77+
7678
endmenu
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Nuclei ECLIC interrupt-controller configuration
2+
3+
# Copyright (c) 2021 Tokita, Hiroshi <[email protected]>
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
DT_COMPAT_NUCLEI_ECLIC = nuclei,eclic
7+
8+
config HAS_NUCLEI_ECLIC
9+
bool
10+
help
11+
Indicate that the platform has ECLIC.
12+
13+
config NUCLEI_ECLIC
14+
bool "Enhanced Core Local Interrupt Controller (ECLIC)"
15+
default $(dt_compat_enabled,$(DT_COMPAT_NUCLEI_ECLIC))
16+
depends on HAS_NUCLEI_ECLIC
17+
help
18+
Interrupt controller for Nuclei SoC core.
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
* Copyright (c) 2021 Tokita, Hiroshi <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @brief Driver for Nuclie's Extended Core Interrupt Controller
9+
*/
10+
11+
#include <kernel.h>
12+
#include <arch/cpu.h>
13+
#include <sys/util.h>
14+
#include <init.h>
15+
#include <soc.h>
16+
17+
#include <sw_isr_table.h>
18+
19+
union CLICCFG {
20+
struct {
21+
uint8_t _reserved0 : 1;
22+
/** number of interrupt level bits */
23+
uint8_t nlbits : 4;
24+
uint8_t _reserved1 : 2;
25+
uint8_t _reserved2 : 1;
26+
} b;
27+
uint8_t w;
28+
};
29+
30+
union CLICINFO {
31+
struct {
32+
/** number of max supported interrupts */
33+
uint32_t numint : 13;
34+
/** architecture version */
35+
uint32_t version : 8;
36+
/** supported bits in the clicintctl */
37+
uint32_t intctlbits : 4;
38+
uint32_t _reserved0 : 7;
39+
} b;
40+
uint32_t qw;
41+
};
42+
43+
union CLICMTH {
44+
uint8_t w;
45+
};
46+
47+
union CLICINTIP {
48+
struct {
49+
/** Interrupt Pending */
50+
uint8_t IP : 1;
51+
uint8_t reserved0 : 7;
52+
} b;
53+
uint8_t w;
54+
};
55+
56+
union CLICINTIE {
57+
struct {
58+
/** Interrupt Enabled */
59+
uint8_t IE : 1;
60+
uint8_t reserved0 : 7;
61+
} b;
62+
uint8_t w;
63+
};
64+
65+
union CLICINTATTR {
66+
struct {
67+
/** 0: non-vectored 1:vectored */
68+
uint8_t shv : 1;
69+
/** 0: level 1: rising edge 2: falling edge */
70+
uint8_t trg : 2;
71+
uint8_t reserved0 : 3;
72+
uint8_t reserved1 : 2;
73+
} b;
74+
uint8_t w;
75+
};
76+
77+
struct CLICCTRL {
78+
volatile union CLICINTIP INTIP;
79+
volatile union CLICINTIE INTIE;
80+
volatile union CLICINTATTR INTATTR;
81+
volatile uint8_t INTCTRL;
82+
};
83+
84+
/** ECLIC Mode mask for MTVT CSR Register */
85+
#define ECLIC_MODE_MTVEC_Msk 3U
86+
87+
/** CLIC INTATTR: TRIG Position */
88+
#define CLIC_INTATTR_TRIG_Pos 1U
89+
/** CLIC INTATTR: TRIG Mask */
90+
#define CLIC_INTATTR_TRIG_Msk (0x3UL << CLIC_INTATTR_TRIG_Pos)
91+
92+
#define ECLIC_CFG (*((volatile union CLICCFG *)(DT_REG_ADDR_BY_IDX(DT_NODELABEL(eclic), 0))))
93+
#define ECLIC_INFO (*((volatile union CLICINFO *)(DT_REG_ADDR_BY_IDX(DT_NODELABEL(eclic), 1))))
94+
#define ECLIC_MTH (*((volatile union CLICMTH *)(DT_REG_ADDR_BY_IDX(DT_NODELABEL(eclic), 2))))
95+
#define ECLIC_CTRL ((volatile struct CLICCTRL *)(DT_REG_ADDR_BY_IDX(DT_NODELABEL(eclic), 3)))
96+
#define ECLIC_CTRL_SIZE (DT_REG_SIZE_BY_IDX(DT_NODELABEL(eclic), 3))
97+
98+
#if CONFIG_3RD_LEVEL_INTERRUPTS
99+
#define INTERRUPT_LEVEL 2
100+
#elif CONFIG_2ND_LEVEL_INTERRUPTS
101+
#define INTERRUPT_LEVEL 1
102+
#else
103+
#define INTERRUPT_LEVEL 0
104+
#endif
105+
106+
static uint8_t nlbits;
107+
static uint8_t intctlbits;
108+
static uint8_t max_prio;
109+
static uint8_t max_level;
110+
static uint8_t intctrl_mask;
111+
112+
static inline uint8_t leftalign8(uint8_t val, uint8_t shift)
113+
{
114+
return (val << (8U - shift));
115+
}
116+
117+
static inline uint8_t mask8(uint8_t len)
118+
{
119+
return ((1 << len) - 1) & 0xFFFFU;
120+
}
121+
122+
/**
123+
* @brief Enable interrupt
124+
*/
125+
void nuclei_eclic_irq_enable(uint32_t irq)
126+
{
127+
ECLIC_CTRL[irq].INTIE.b.IE = 1;
128+
}
129+
130+
/**
131+
* @brief Disable interrupt
132+
*/
133+
void nuclei_eclic_irq_disable(uint32_t irq)
134+
{
135+
ECLIC_CTRL[irq].INTIE.b.IE = 0;
136+
}
137+
138+
/**
139+
* @brief Get enable status of interrupt
140+
*/
141+
int nuclei_eclic_irq_is_enabled(uint32_t irq)
142+
{
143+
return ECLIC_CTRL[irq].INTIE.b.IE;
144+
}
145+
146+
/**
147+
* @brief Set priority and level of interrupt
148+
*/
149+
void nuclei_eclic_irq_priority_set(uint32_t irq, uint32_t pri, uint32_t flags)
150+
{
151+
const uint8_t prio = leftalign8(MIN(pri, max_prio), intctlbits);
152+
const uint8_t level = leftalign8(MIN((irq_get_level(irq) - 1), max_level), nlbits);
153+
const uint8_t intctrl = (prio | level) | (~intctrl_mask);
154+
155+
ECLIC_CTRL[irq].INTCTRL = intctrl;
156+
157+
ECLIC_CTRL[irq].INTATTR.b.shv = 0;
158+
ECLIC_CTRL[irq].INTATTR.b.trg = (uint8_t)(flags & CLIC_INTATTR_TRIG_Msk);
159+
}
160+
161+
static int nuclei_eclic_init(const struct device *dev)
162+
{
163+
/* check hardware support required interrupt levels */
164+
__ASSERT_NO_MSG(ECLIC_INFO.b.intctlbits >= INTERRUPT_LEVEL);
165+
166+
ECLIC_MTH.w = 0;
167+
ECLIC_CFG.w = 0;
168+
ECLIC_CFG.b.nlbits = INTERRUPT_LEVEL;
169+
for (int i = 0; i < ECLIC_CTRL_SIZE; i++) {
170+
ECLIC_CTRL[i] = (struct CLICCTRL) { 0 };
171+
}
172+
173+
csr_write(mtvec, ((csr_read(mtvec) & 0xFFFFFFC0) | ECLIC_MODE_MTVEC_Msk));
174+
175+
nlbits = ECLIC_CFG.b.nlbits;
176+
intctlbits = ECLIC_INFO.b.intctlbits;
177+
max_prio = mask8(intctlbits - nlbits);
178+
max_level = mask8(nlbits);
179+
intctrl_mask = leftalign8(mask8(intctlbits), intctlbits);
180+
181+
return 0;
182+
}
183+
184+
SYS_INIT(nuclei_eclic_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright (c) 2021, Tokita, Hiroshi
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Nuclei ECLIC interrupt controller
5+
6+
compatible: "nuclei,eclic"
7+
8+
include: [interrupt-controller.yaml, base.yaml]
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
"#interrupt-cells":
15+
const: 2
16+
17+
interrupt-cells:
18+
- irq
19+
- priority

dts/riscv/gigadevice/gd32vf103.dtsi

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@
4040
clk-divider = <RISCV_MACHINE_TIMER_DIVIDER_4>;
4141
};
4242

43+
eclic: interrupt-controller@d2000000 {
44+
#interrupt-cells = <2>;
45+
compatible = "nuclei,eclic";
46+
interrupt-controller;
47+
reg = <0xd2000000 0x0001
48+
0xd2000004 0x0004
49+
0xd200000b 0x0001
50+
0xd2001000 0x1000>;
51+
label = "NUCLEI_ECLIC";
52+
};
53+
4354
fmc: flash-controller@40022000 {
4455
compatible = "gd,gd32-flash-controller";
4556
label = "FMC";

include/arch/riscv/arch.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,13 @@ void z_irq_spurious(const void *unused);
291291
Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
292292
arch_irq_priority_set(irq_p, priority_p); \
293293
}
294+
#elif defined(CONFIG_NUCLEI_ECLIC)
295+
void nuclei_eclic_irq_priority_set(unsigned int irq, unsigned int prio, unsigned int flags);
296+
#define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
297+
{ \
298+
Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
299+
nuclei_eclic_irq_priority_set(irq_p, priority_p, flags_p); \
300+
}
294301
#else
295302
#define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
296303
{ \

modules/hal_gigadevice/Kconfig

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,6 @@ config USE_GD32_DMA
106106
help
107107
Enable GD32 Direct Memory Access controller (DMA) HAL module driver
108108

109-
config USE_GD32_ECLIC
110-
bool
111-
help
112-
Enable GD32 Enhancement Core-Local Interrupt Controller (ECLIC) HAL
113-
module driver
114-
115109
config USE_GD32_ENET
116110
bool
117111
help

soc/riscv/riscv-privilege/common/soc_common.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ void riscv_plic_set_priority(uint32_t irq, uint32_t priority);
5050
int riscv_plic_get_irq(void);
5151
#endif
5252

53+
#if defined(CONFIG_NUCLEI_ECLIC)
54+
void nuclei_eclic_irq_enable(uint32_t irq);
55+
void nuclei_eclic_irq_disable(uint32_t irq);
56+
int nuclei_eclic_irq_is_enabled(uint32_t irq);
57+
void nuclei_eclic_set_priority(uint32_t irq, uint32_t priority);
58+
#endif
59+
5360
#endif /* !_ASMLANGUAGE */
5461

5562
#endif /* __SOC_COMMON_H_ */

0 commit comments

Comments
 (0)