Skip to content

Commit 4480d9e

Browse files
committed
Add support for clic
1 parent 84c6dc1 commit 4480d9e

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

platform/litex/vexriscv/platform.c

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
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>
@@ -24,6 +25,7 @@
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)
@@ -33,6 +35,22 @@
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+
3654
static 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
*/
64115
static 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

Comments
 (0)