diff options
-rw-r--r-- | include/sbi_utils/sys/clint.h | 23 | ||||
-rw-r--r-- | lib/utils/ipi/fdt_ipi_clint.c | 10 | ||||
-rw-r--r-- | lib/utils/sys/clint.c | 142 | ||||
-rw-r--r-- | lib/utils/timer/fdt_timer_clint.c | 9 | ||||
-rw-r--r-- | platform/fpga/ariane/platform.c | 15 | ||||
-rw-r--r-- | platform/fpga/openpiton/platform.c | 20 | ||||
-rw-r--r-- | platform/kendryte/k210/platform.c | 13 | ||||
-rw-r--r-- | platform/nuclei/ux600/platform.c | 12 | ||||
-rw-r--r-- | platform/sifive/fu540/platform.c | 12 | ||||
-rw-r--r-- | platform/template/platform.c | 21 | ||||
-rw-r--r-- | platform/thead/c910/platform.c | 14 |
11 files changed, 203 insertions, 88 deletions
diff --git a/include/sbi_utils/sys/clint.h b/include/sbi_utils/sys/clint.h index a26f148..b07cf62 100644 --- a/include/sbi_utils/sys/clint.h +++ b/include/sbi_utils/sys/clint.h @@ -12,13 +12,30 @@ #include <sbi/sbi_types.h> +struct clint_data { + /* Public details */ + unsigned long addr; + u32 first_hartid; + u32 hart_count; + bool has_64bit_mmio; + /* Private details (initialized and used by CLINT library)*/ + u32 *ipi; + struct clint_data *time_delta_reference; + unsigned long time_delta_computed; + u64 time_delta; + u64 *time_val; + u64 *time_cmp; + u64 (*time_rd)(volatile u64 *addr); + void (*time_wr)(u64 value, volatile u64 *addr); +}; + void clint_ipi_send(u32 target_hart); void clint_ipi_clear(u32 target_hart); int clint_warm_ipi_init(void); -int clint_cold_ipi_init(unsigned long base, u32 hart_count); +int clint_cold_ipi_init(struct clint_data *clint); u64 clint_timer_value(void); @@ -28,7 +45,7 @@ void clint_timer_event_start(u64 next_event); int clint_warm_timer_init(void); -int clint_cold_timer_init(unsigned long base, u32 hart_count, - bool has_64bit_mmio); +int clint_cold_timer_init(struct clint_data *clint, + struct clint_data *reference); #endif diff --git a/lib/utils/ipi/fdt_ipi_clint.c b/lib/utils/ipi/fdt_ipi_clint.c index 05b66c6..c4ac0df 100644 --- a/lib/utils/ipi/fdt_ipi_clint.c +++ b/lib/utils/ipi/fdt_ipi_clint.c @@ -11,6 +11,8 @@ #include <sbi_utils/ipi/fdt_ipi.h> #include <sbi_utils/sys/clint.h> +static struct clint_data clint_ipi; + static int ipi_clint_cold_init(void *fdt, int nodeoff, const struct fdt_match *match) { @@ -26,7 +28,13 @@ static int ipi_clint_cold_init(void *fdt, int nodeoff, if (rc) return rc; - return clint_cold_ipi_init(addr, max_hartid + 1); + /* TODO: We should figure-out CLINT has_64bit_mmio from DT node */ + clint_ipi.addr = addr; + clint_ipi.first_hartid = 0; + clint_ipi.hart_count = max_hartid + 1; + clint_ipi.has_64bit_mmio = TRUE; + + return clint_cold_ipi_init(&clint_ipi); } static const struct fdt_match ipi_clint_match[] = { diff --git a/lib/utils/sys/clint.c b/lib/utils/sys/clint.c index 22ba088..7a392aa 100644 --- a/lib/utils/sys/clint.c +++ b/lib/utils/sys/clint.c @@ -10,57 +10,70 @@ #include <sbi/riscv_asm.h> #include <sbi/riscv_atomic.h> #include <sbi/riscv_io.h> +#include <sbi/sbi_error.h> +#include <sbi/sbi_hartmask.h> #include <sbi_utils/sys/clint.h> -static u32 clint_ipi_hart_count; -static volatile void *clint_ipi_base; -static volatile u32 *clint_ipi; +#define CLINT_IPI_OFF 0 +#define CLINT_TIME_CMP_OFF 0x4000 +#define CLINT_TIME_VAL_OFF 0xbff8 + +static struct clint_data *clint_ipi_hartid2data[SBI_HARTMASK_MAX_BITS]; void clint_ipi_send(u32 target_hart) { - if (clint_ipi_hart_count <= target_hart) + struct clint_data *clint; + + if (SBI_HARTMASK_MAX_BITS <= target_hart) + return; + clint = clint_ipi_hartid2data[target_hart]; + if (!clint) return; /* Set CLINT IPI */ - writel(1, &clint_ipi[target_hart]); + writel(1, &clint->ipi[target_hart - clint->first_hartid]); } void clint_ipi_clear(u32 target_hart) { - if (clint_ipi_hart_count <= target_hart) + struct clint_data *clint; + + if (SBI_HARTMASK_MAX_BITS <= target_hart) + return; + clint = clint_ipi_hartid2data[target_hart]; + if (!clint) return; /* Clear CLINT IPI */ - writel(0, &clint_ipi[target_hart]); + writel(0, &clint->ipi[target_hart - clint->first_hartid]); } int clint_warm_ipi_init(void) { - u32 hartid = current_hartid(); - - if (!clint_ipi_base) - return -1; - - /* Clear CLINT IPI */ - clint_ipi_clear(hartid); + /* Clear CLINT IPI for current HART */ + clint_ipi_clear(current_hartid()); return 0; } -int clint_cold_ipi_init(unsigned long base, u32 hart_count) +int clint_cold_ipi_init(struct clint_data *clint) { - /* Figure-out CLINT IPI register address */ - clint_ipi_hart_count = hart_count; - clint_ipi_base = (void *)base; - clint_ipi = (u32 *)clint_ipi_base; + u32 i; + + if (!clint) + return SBI_EINVAL; + + /* Initialize private data */ + clint->ipi = (void *)clint->addr; + + /* Update IPI hartid table */ + for (i = 0; i < clint->hart_count; i++) + clint_ipi_hartid2data[clint->first_hartid + i] = clint; return 0; } -static u32 clint_time_hart_count; -static volatile void *clint_time_base; -static volatile u64 *clint_time_val; -static volatile u64 *clint_time_cmp; +static struct clint_data *clint_timer_hartid2data[SBI_HARTMASK_MAX_BITS]; #if __riscv_xlen != 32 static u64 clint_time_rd64(volatile u64 *addr) @@ -94,66 +107,97 @@ static void clint_time_wr32(u64 value, volatile u64 *addr) writel_relaxed(value >> 32, (void *)(addr) + 0x04); } -static u64 (*clint_time_rd)(volatile u64 *addr) = clint_time_rd32; -static void (*clint_time_wr)(u64 value, volatile u64 *addr) = clint_time_wr32; - u64 clint_timer_value(void) { + struct clint_data *clint = clint_timer_hartid2data[current_hartid()]; + /* Read CLINT Time Value */ - return clint_time_rd(clint_time_val); + return clint->time_rd(clint->time_val) + clint->time_delta; } void clint_timer_event_stop(void) { u32 target_hart = current_hartid(); - - if (clint_time_hart_count <= target_hart) - return; + struct clint_data *clint = clint_timer_hartid2data[target_hart]; /* Clear CLINT Time Compare */ - clint_time_wr(-1ULL, &clint_time_cmp[target_hart]); + clint->time_wr(-1ULL, + &clint->time_cmp[target_hart - clint->first_hartid]); } void clint_timer_event_start(u64 next_event) { u32 target_hart = current_hartid(); - - if (clint_time_hart_count <= target_hart) - return; + struct clint_data *clint = clint_timer_hartid2data[target_hart]; /* Program CLINT Time Compare */ - clint_time_wr(next_event, &clint_time_cmp[target_hart]); + clint->time_wr(next_event - clint->time_delta, + &clint->time_cmp[target_hart - clint->first_hartid]); } int clint_warm_timer_init(void) { + u64 v1, v2, mv; u32 target_hart = current_hartid(); - - if (clint_time_hart_count <= target_hart || !clint_time_base) - return -1; + struct clint_data *reference; + struct clint_data *clint = clint_timer_hartid2data[target_hart]; + + if (!clint) + return SBI_ENODEV; + + /* + * Compute delta if reference available + * + * We deliberately compute time_delta in warm init so that time_delta + * is computed on a HART which is going to use given CLINT. We use + * atomic flag timer_delta_computed to ensure that only one HART does + * time_delta computation. + */ + if (clint->time_delta_reference) { + reference = clint->time_delta_reference; + if (!atomic_raw_xchg_ulong(&clint->time_delta_computed, 1)) { + v1 = clint->time_rd(clint->time_val); + mv = reference->time_rd(reference->time_val); + v2 = clint->time_rd(clint->time_val); + clint->time_delta = mv - ((v1 / 2) + (v2 / 2)); + } + } /* Clear CLINT Time Compare */ - clint_time_wr(-1ULL, &clint_time_cmp[target_hart]); + clint->time_wr(-1ULL, + &clint->time_cmp[target_hart - clint->first_hartid]); return 0; } -int clint_cold_timer_init(unsigned long base, u32 hart_count, - bool has_64bit_mmio) +int clint_cold_timer_init(struct clint_data *clint, + struct clint_data *reference) { - /* Figure-out CLINT Time register address */ - clint_time_hart_count = hart_count; - clint_time_base = (void *)base; - clint_time_val = (u64 *)(clint_time_base + 0xbff8); - clint_time_cmp = (u64 *)(clint_time_base + 0x4000); + u32 i; + + if (!clint) + return SBI_EINVAL; + + /* Initialize private data */ + clint->time_delta_reference = reference; + clint->time_delta_computed = 0; + clint->time_delta = 0; + clint->time_val = (u64 *)((void *)clint->addr + CLINT_TIME_VAL_OFF); + clint->time_cmp = (u64 *)((void *)clint->addr + CLINT_TIME_CMP_OFF); + clint->time_rd = clint_time_rd32; + clint->time_wr = clint_time_wr32; /* Override read/write accessors for 64bit MMIO */ #if __riscv_xlen != 32 - if (has_64bit_mmio) { - clint_time_rd = clint_time_rd64; - clint_time_wr = clint_time_wr64; + if (clint->has_64bit_mmio) { + clint->time_rd = clint_time_rd64; + clint->time_wr = clint_time_wr64; } #endif + /* Update timer hartid table */ + for (i = 0; i < clint->hart_count; i++) + clint_timer_hartid2data[clint->first_hartid + i] = clint; + return 0; } diff --git a/lib/utils/timer/fdt_timer_clint.c b/lib/utils/timer/fdt_timer_clint.c index 6aa6929..2f5f283 100644 --- a/lib/utils/timer/fdt_timer_clint.c +++ b/lib/utils/timer/fdt_timer_clint.c @@ -11,6 +11,8 @@ #include <sbi_utils/timer/fdt_timer.h> #include <sbi_utils/sys/clint.h> +static struct clint_data clint_timer; + static int timer_clint_cold_init(void *fdt, int nodeoff, const struct fdt_match *match) { @@ -27,7 +29,12 @@ static int timer_clint_cold_init(void *fdt, int nodeoff, return rc; /* TODO: We should figure-out CLINT has_64bit_mmio from DT node */ - return clint_cold_timer_init(addr, max_hartid + 1, TRUE); + clint_timer.addr = addr; + clint_timer.first_hartid = 0; + clint_timer.hart_count = max_hartid + 1; + clint_timer.has_64bit_mmio = TRUE; + + return clint_cold_timer_init(&clint_timer, NULL); } static const struct fdt_match timer_clint_match[] = { diff --git a/platform/fpga/ariane/platform.c b/platform/fpga/ariane/platform.c index 275f2ce..a4d437e 100644 --- a/platform/fpga/ariane/platform.c +++ b/platform/fpga/ariane/platform.c @@ -24,13 +24,20 @@ #define ARIANE_PLIC_ADDR 0xc000000 #define ARIANE_PLIC_NUM_SOURCES 3 #define ARIANE_HART_COUNT 1 -#define ARIANE_CLINT_ADDR 0x2000000 +#define ARIANE_CLINT_ADDR 0x2000000 static struct plic_data plic = { .addr = ARIANE_PLIC_ADDR, .num_src = ARIANE_PLIC_NUM_SOURCES, }; +static struct clint_data clint = { + .addr = ARIANE_CLINT_ADDR, + .first_hartid = 0, + .hart_count = ARIANE_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + /* * Ariane platform early initialization. */ @@ -116,8 +123,7 @@ static int ariane_ipi_init(bool cold_boot) int ret; if (cold_boot) { - ret = clint_cold_ipi_init(ARIANE_CLINT_ADDR, - ARIANE_HART_COUNT); + ret = clint_cold_ipi_init(&clint); if (ret) return ret; } @@ -133,8 +139,7 @@ static int ariane_timer_init(bool cold_boot) int ret; if (cold_boot) { - ret = clint_cold_timer_init(ARIANE_CLINT_ADDR, - ARIANE_HART_COUNT, TRUE); + ret = clint_cold_timer_init(&clint, NULL); if (ret) return ret; } diff --git a/platform/fpga/openpiton/platform.c b/platform/fpga/openpiton/platform.c index e56ee51..095004d 100644 --- a/platform/fpga/openpiton/platform.c +++ b/platform/fpga/openpiton/platform.c @@ -35,7 +35,13 @@ static struct plic_data plic = { .addr = OPENPITON_DEFAULT_PLIC_ADDR, .num_src = OPENPITON_DEFAULT_PLIC_NUM_SOURCES, }; -static unsigned long clint_addr = OPENPITON_DEFAULT_CLINT_ADDR; + +static struct clint_data clint = { + .addr = OPENPITON_DEFAULT_CLINT_ADDR, + .first_hartid = 0, + .hart_count = OPENPITON_DEFAULT_HART_COUNT, + .has_64bit_mmio = TRUE, +}; /* * OpenPiton platform early initialization. @@ -45,7 +51,7 @@ static int openpiton_early_init(bool cold_boot) void *fdt; struct platform_uart_data uart_data; struct plic_data plic_data; - unsigned long clint_data; + unsigned long clint_addr; int rc; if (!cold_boot) @@ -60,9 +66,9 @@ static int openpiton_early_init(bool cold_boot) if (!rc) plic = plic_data; - rc = fdt_parse_compat_addr(fdt, &clint_data, "riscv,clint0"); + rc = fdt_parse_compat_addr(fdt, &clint_addr, "riscv,clint0"); if (!rc) - clint_addr = clint_data; + clint.addr = clint_addr; return 0; } @@ -143,8 +149,7 @@ static int openpiton_ipi_init(bool cold_boot) int ret; if (cold_boot) { - ret = clint_cold_ipi_init(clint_addr, - OPENPITON_DEFAULT_HART_COUNT); + ret = clint_cold_ipi_init(&clint); if (ret) return ret; } @@ -160,8 +165,7 @@ static int openpiton_timer_init(bool cold_boot) int ret; if (cold_boot) { - ret = clint_cold_timer_init(clint_addr, - OPENPITON_DEFAULT_HART_COUNT, TRUE); + ret = clint_cold_timer_init(&clint, NULL); if (ret) return ret; } diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c index db2186a..ef0f18f 100644 --- a/platform/kendryte/k210/platform.c +++ b/platform/kendryte/k210/platform.c @@ -22,6 +22,13 @@ static struct plic_data plic = { .num_src = K210_PLIC_NUM_SOURCES, }; +static struct clint_data clint = { + .addr = K210_CLINT_BASE_ADDR, + .first_hartid = 0, + .hart_count = K210_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + static u32 k210_get_clk_freq(void) { u32 clksel0, pll0; @@ -76,8 +83,7 @@ static int k210_ipi_init(bool cold_boot) int rc; if (cold_boot) { - rc = clint_cold_ipi_init(K210_CLINT_BASE_ADDR, - K210_HART_COUNT); + rc = clint_cold_ipi_init(&clint); if (rc) return rc; } @@ -90,8 +96,7 @@ static int k210_timer_init(bool cold_boot) int rc; if (cold_boot) { - rc = clint_cold_timer_init(K210_CLINT_BASE_ADDR, - K210_HART_COUNT, TRUE); + rc = clint_cold_timer_init(&clint, NULL); if (rc) return rc; } diff --git a/platform/nuclei/ux600/platform.c b/platform/nuclei/ux600/platform.c index f999c99..ad4ba2b 100644 --- a/platform/nuclei/ux600/platform.c +++ b/platform/nuclei/ux600/platform.c @@ -48,6 +48,13 @@ static struct plic_data plic = { .num_src = UX600_PLIC_NUM_SOURCES, }; +static struct clint_data clint = { + .addr = UX600_CLINT_TIMER_ADDR, + .first_hartid = 0, + .hart_count = UX600_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + static void ux600_modify_dt(void *fdt) { fdt_fixups(fdt); @@ -92,7 +99,7 @@ static int ux600_ipi_init(bool cold_boot) int rc; if (cold_boot) { - rc = clint_cold_ipi_init(UX600_CLINT_TIMER_ADDR, UX600_HART_COUNT); + rc = clint_cold_ipi_init(&clint); if (rc) return rc; } @@ -105,8 +112,7 @@ static int ux600_timer_init(bool cold_boot) int rc; if (cold_boot) { - rc = clint_cold_timer_init(UX600_CLINT_TIMER_ADDR, - UX600_HART_COUNT, TRUE); + rc = clint_cold_timer_init(&clint, NULL); if (rc) return rc; } diff --git a/platform/sifive/fu540/platform.c b/platform/sifive/fu540/platform.c index 7a62fc3..48d887f 100644 --- a/platform/sifive/fu540/platform.c +++ b/platform/sifive/fu540/platform.c @@ -51,6 +51,13 @@ static struct plic_data plic = { .num_src = FU540_PLIC_NUM_SOURCES, }; +static struct clint_data clint = { + .addr = FU540_CLINT_ADDR, + .first_hartid = 0, + .hart_count = FU540_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + static void fu540_modify_dt(void *fdt) { fdt_cpu_fixup(fdt); @@ -107,7 +114,7 @@ static int fu540_ipi_init(bool cold_boot) int rc; if (cold_boot) { - rc = clint_cold_ipi_init(FU540_CLINT_ADDR, FU540_HART_COUNT); + rc = clint_cold_ipi_init(&clint); if (rc) return rc; } @@ -125,8 +132,7 @@ static int fu540_timer_init(bool cold_boot) int rc; if (cold_boot) { - rc = clint_cold_timer_init(FU540_CLINT_ADDR, - FU540_HART_COUNT, TRUE); + rc = clint_cold_timer_init(&clint, NULL); if (rc) return rc; } diff --git a/platform/template/platform.c b/platform/template/platform.c index c845380..9cd750e 100644 --- a/platform/template/platform.c +++ b/platform/template/platform.c @@ -17,10 +17,10 @@ #include <sbi_utils/serial/uart8250.h> #include <sbi_utils/sys/clint.h> -#define PLATFORM_PLIC_ADDR 0xc000000 -#define PLATFORM_PLIC_NUM_SOURCES 128 -#define PLATFORM_HART_COUNT 4 -#define PLATFORM_CLINT_ADDR 0x2000000 +#define PLATFORM_PLIC_ADDR 0xc000000 +#define PLATFORM_PLIC_NUM_SOURCES 128 +#define PLATFORM_HART_COUNT 4 +#define PLATFORM_CLINT_ADDR 0x2000000 #define PLATFORM_UART_ADDR 0x09000000 #define PLATFORM_UART_INPUT_FREQ 10000000 #define PLATFORM_UART_BAUDRATE 115200 @@ -30,6 +30,13 @@ static struct plic_data plic = { .num_src = PLATFORM_PLIC_NUM_SOURCES, }; +static struct clint_data clint = { + .addr = PLATFORM_CLINT_ADDR, + .first_hartid = 0, + .hart_count = PLATFORM_HART_COUNT, + .has_64bit_mmio = TRUE, +}; + /* * Platform early initialization. */ @@ -100,8 +107,7 @@ static int platform_ipi_init(bool cold_boot) /* Example if the generic CLINT driver is used */ if (cold_boot) { - ret = clint_cold_ipi_init(PLATFORM_CLINT_ADDR, - PLATFORM_HART_COUNT); + ret = clint_cold_ipi_init(&clint, NULL); if (ret) return ret; } @@ -136,8 +142,7 @@ static int platform_timer_init(bool cold_boot) /* Example if the generic CLINT driver is used */ if (cold_boot) { - ret = clint_cold_timer_init(PLATFORM_CLINT_ADDR, - PLATFORM_HART_COUNT, TRUE); + ret = clint_cold_timer_init(&clint); if (ret) return ret; } diff --git a/platform/thead/c910/platform.c b/platform/thead/c910/platform.c index 82f910a..df7658a 100644 --- a/platform/thead/c910/platform.c +++ b/platform/thead/c910/platform.c @@ -15,6 +15,13 @@ static struct c910_regs_struct c910_regs; +static struct clint_data clint = { + .addr = 0, /* Updated at cold boot time */ + .first_hartid = 0, + .hart_count = C910_HART_COUNT, + .has_64bit_mmio = FALSE, +}; + static int c910_early_init(bool cold_boot) { if (cold_boot) { @@ -78,7 +85,8 @@ static int c910_ipi_init(bool cold_boot) int rc; if (cold_boot) { - rc = clint_cold_ipi_init(c910_regs.clint_base_addr, C910_HART_COUNT); + clint.addr = c910_regs.clint_base_addr; + rc = clint_cold_ipi_init(&clint); if (rc) return rc; } @@ -91,8 +99,8 @@ static int c910_timer_init(bool cold_boot) int ret; if (cold_boot) { - ret = clint_cold_timer_init(c910_regs.clint_base_addr, - C910_HART_COUNT, FALSE); + clint.addr = c910_regs.clint_base_addr; + ret = clint_cold_timer_init(&clint, NULL); if (ret) return ret; } |