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,54 @@ 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+ if (clic_mode_detected ) {
122+ sbi_console_init ();
123+ sbi_printf ("VexRiscv: CLIC mode detected and enabled\n" );
124+ }
125+ }
126+
66127 return 0 ;
67128}
68129
@@ -78,6 +139,14 @@ static int vex_final_init(bool cold_boot)
78139
79140 fdt = fdt_get_address ();
80141 fdt_fixups (fdt );
142+
143+ /* Report interrupt controller mode */
144+ if (clic_mode_detected ) {
145+ sbi_printf ("VexRiscv: Running in CLIC mode with %d interrupts\n" ,
146+ clic .num_interrupts );
147+ } else {
148+ sbi_printf ("VexRiscv: Running in PLIC/CLINT mode\n" );
149+ }
81150
82151 return 0 ;
83152}
@@ -90,6 +159,55 @@ static int vex_console_init(void)
90159 return litex_uart_init (VEX_DEFAULT_UART_ADDR );
91160}
92161
162+ /* CLIC CSR addresses - these may vary by implementation */
163+ #define CSR_MCLICBASE 0x307 /* Base address for CLIC memory-mapped registers */
164+
165+ /*
166+ * Initialize CLIC for current HART
167+ */
168+ static int vex_clic_init (bool cold_boot )
169+ {
170+ u32 hartid = current_hartid ();
171+ unsigned long mtvec_val ;
172+
173+ if (cold_boot ) {
174+ /* Basic CLIC initialization */
175+ sbi_printf ("VexRiscv: Initializing CLIC at 0x%lx\n" , clic .addr );
176+
177+ /* Set CLIC mode in mtvec (mode = 3) */
178+ mtvec_val = csr_read (CSR_MTVEC );
179+ mtvec_val = (mtvec_val & ~0x3UL ) | 0x3UL ;
180+ csr_write (CSR_MTVEC , mtvec_val );
181+
182+ /* Verify CLIC mode is active */
183+ mtvec_val = csr_read (CSR_MTVEC );
184+ if ((mtvec_val & 0x3UL ) != 0x3UL ) {
185+ sbi_printf ("VexRiscv: WARNING: Failed to set CLIC mode in mtvec\n" );
186+ return -1 ;
187+ }
188+
189+ /* Clear all pending interrupts if accessible via MMIO */
190+ /* This would require memory-mapped access to CLIC registers */
191+ /* which depends on the specific implementation */
192+
193+ /* Set interrupt threshold to 0 to allow all interrupts */
194+ /* The exact CSR number for mintthresh varies by implementation */
195+ /* Some implementations use custom CSRs in the 0x7XX range */
196+ }
197+
198+ /* Per-hart CLIC configuration */
199+ sbi_printf ("VexRiscv: CLIC initialized for hart %d in mode 0x%lx\n" ,
200+ hartid , csr_read (CSR_MTVEC ) & 0x3 );
201+
202+ /* Enable machine interrupts */
203+ csr_set (CSR_MSTATUS , MSTATUS_MIE );
204+
205+ /* Enable all interrupt sources in MIE */
206+ csr_write (CSR_MIE , -1UL );
207+
208+ return 0 ;
209+ }
210+
93211/*
94212 * Initialize the vexRiscv interrupt controller for current HART.
95213 */
@@ -98,6 +216,12 @@ static int vex_irqchip_init(bool cold_boot)
98216 int rc ;
99217 u32 hartid = current_hartid ();
100218
219+ /* Use CLIC if detected, otherwise fall back to PLIC */
220+ if (clic_mode_detected ) {
221+ return vex_clic_init (cold_boot );
222+ }
223+
224+ /* Traditional PLIC initialization */
101225 if (cold_boot ) {
102226 rc = plic_cold_irqchip_init (& plic );
103227 if (rc )
0 commit comments