1111#include <sbi/sbi_const.h>
1212#include <sbi/sbi_hart.h>
1313#include <sbi/sbi_platform.h>
14+ #include <sbi/sbi_console.h>
1415#include <sbi_utils/fdt/fdt_helper.h>
1516#include <sbi_utils/fdt/fdt_fixup.h>
1617#include <sbi_utils/ipi/aclint_mswi.h>
2425#define VEX_DEFAULT_PLIC_ADDR 0xf0c00000
2526#define VEX_DEFAULT_PLIC_NUM_SOURCES 4
2627#define VEX_DEFAULT_CLINT_ADDR 0xF0010000
28+ #define VEX_DEFAULT_CLIC_ADDR 0xf0d00000 /* Default CLIC base address */
2729#define VEX_DEFAULT_ACLINT_MTIMER_FREQ 100000000
2830#define VEX_DEFAULT_ACLINT_MSWI_ADDR \
2931 (VEX_DEFAULT_CLINT_ADDR + CLINT_MSWI_OFFSET)
3335
3436/* clang-format on */
3537
38+ /* CLIC mode detection flag */
39+ static bool clic_mode_detected = false;
40+
41+ /* Simple CLIC initialization structure */
42+ struct clic_data {
43+ unsigned long addr ;
44+ u32 num_interrupts ;
45+ u32 num_harts ;
46+ };
47+
48+ static struct clic_data clic = {
49+ .addr = VEX_DEFAULT_CLIC_ADDR ,
50+ .num_interrupts = 64 ,
51+ .num_harts = VEX_DEFAULT_HART_COUNT ,
52+ };
53+
3654static struct plic_data plic = {
3755 .addr = VEX_DEFAULT_PLIC_ADDR ,
3856 .num_src = VEX_DEFAULT_PLIC_NUM_SOURCES ,
@@ -58,11 +76,49 @@ static struct aclint_mtimer_data mtimer = {
5876 .has_64bit_mmio = true,
5977};
6078
79+ /*
80+ * Detect if CLIC is present and configured
81+ */
82+ static bool vex_detect_clic (void )
83+ {
84+ unsigned long mtvec , mtvec_orig ;
85+ bool clic_supported = false;
86+
87+ /* Save original mtvec */
88+ mtvec_orig = csr_read (CSR_MTVEC );
89+
90+ /* Try to set CLIC mode (mode = 3) in mtvec.mode bits [1:0] */
91+ mtvec = (mtvec_orig & ~0x3UL ) | 0x3UL ;
92+ csr_write (CSR_MTVEC , mtvec );
93+
94+ /* Read back to see if CLIC mode stuck */
95+ mtvec = csr_read (CSR_MTVEC );
96+
97+ /* Check if mode bits are 3 (CLIC mode) */
98+ if ((mtvec & 0x3UL ) == 0x3UL ) {
99+ clic_supported = true;
100+ /* Keep CLIC mode active */
101+ sbi_printf ("VexRiscv: CLIC hardware detected (mtvec.mode=3 supported)\n" );
102+ } else {
103+ /* Restore original mode */
104+ csr_write (CSR_MTVEC , mtvec_orig );
105+ sbi_printf ("VexRiscv: No CLIC support detected (mtvec.mode=%ld)\n" ,
106+ mtvec & 0x3UL );
107+ }
108+
109+ return clic_supported ;
110+ }
111+
61112/*
62113 * VexRiscv platform early initialization.
63114 */
64115static int vex_early_init (bool cold_boot )
65116{
117+ if (cold_boot ) {
118+ /* Detect if CLIC mode is available */
119+ clic_mode_detected = vex_detect_clic ();
120+ }
121+
66122 return 0 ;
67123}
68124
@@ -78,6 +134,14 @@ static int vex_final_init(bool cold_boot)
78134
79135 fdt = fdt_get_address ();
80136 fdt_fixups (fdt );
137+
138+ /* Report interrupt controller mode */
139+ if (clic_mode_detected ) {
140+ sbi_printf ("VexRiscv: Running in CLIC mode with %d interrupts\n" ,
141+ clic .num_interrupts );
142+ } else {
143+ sbi_printf ("VexRiscv: Running in PLIC/CLINT mode\n" );
144+ }
81145
82146 return 0 ;
83147}
@@ -90,6 +154,55 @@ static int vex_console_init(void)
90154 return litex_uart_init (VEX_DEFAULT_UART_ADDR );
91155}
92156
157+ /* CLIC CSR addresses - these may vary by implementation */
158+ #define CSR_MCLICBASE 0x307 /* Base address for CLIC memory-mapped registers */
159+
160+ /*
161+ * Initialize CLIC for current HART
162+ */
163+ static int vex_clic_init (bool cold_boot )
164+ {
165+ u32 hartid = current_hartid ();
166+ unsigned long mtvec_val ;
167+
168+ if (cold_boot ) {
169+ /* Basic CLIC initialization */
170+ sbi_printf ("VexRiscv: Initializing CLIC at 0x%lx\n" , clic .addr );
171+
172+ /* Set CLIC mode in mtvec (mode = 3) */
173+ mtvec_val = csr_read (CSR_MTVEC );
174+ mtvec_val = (mtvec_val & ~0x3UL ) | 0x3UL ;
175+ csr_write (CSR_MTVEC , mtvec_val );
176+
177+ /* Verify CLIC mode is active */
178+ mtvec_val = csr_read (CSR_MTVEC );
179+ if ((mtvec_val & 0x3UL ) != 0x3UL ) {
180+ sbi_printf ("VexRiscv: WARNING: Failed to set CLIC mode in mtvec\n" );
181+ return -1 ;
182+ }
183+
184+ /* Clear all pending interrupts if accessible via MMIO */
185+ /* This would require memory-mapped access to CLIC registers */
186+ /* which depends on the specific implementation */
187+
188+ /* Set interrupt threshold to 0 to allow all interrupts */
189+ /* The exact CSR number for mintthresh varies by implementation */
190+ /* Some implementations use custom CSRs in the 0x7XX range */
191+ }
192+
193+ /* Per-hart CLIC configuration */
194+ sbi_printf ("VexRiscv: CLIC initialized for hart %d in mode 0x%lx\n" ,
195+ hartid , csr_read (CSR_MTVEC ) & 0x3 );
196+
197+ /* Enable machine interrupts */
198+ csr_set (CSR_MSTATUS , MSTATUS_MIE );
199+
200+ /* Enable all interrupt sources in MIE */
201+ csr_write (CSR_MIE , -1UL );
202+
203+ return 0 ;
204+ }
205+
93206/*
94207 * Initialize the vexRiscv interrupt controller for current HART.
95208 */
@@ -98,6 +211,12 @@ static int vex_irqchip_init(bool cold_boot)
98211 int rc ;
99212 u32 hartid = current_hartid ();
100213
214+ /* Use CLIC if detected, otherwise fall back to PLIC */
215+ if (clic_mode_detected ) {
216+ return vex_clic_init (cold_boot );
217+ }
218+
219+ /* Traditional PLIC initialization */
101220 if (cold_boot ) {
102221 rc = plic_cold_irqchip_init (& plic );
103222 if (rc )
0 commit comments