diff options
Diffstat (limited to 'lib/utils')
-rw-r--r-- | lib/utils/sys/clint.c | 256 | ||||
-rw-r--r-- | lib/utils/sys/objects.mk | 1 |
2 files changed, 0 insertions, 257 deletions
diff --git a/lib/utils/sys/clint.c b/lib/utils/sys/clint.c deleted file mode 100644 index e8c2bd9..0000000 --- a/lib/utils/sys/clint.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel <anup.patel@wdc.com> - */ - -#include <sbi/riscv_asm.h> -#include <sbi/riscv_atomic.h> -#include <sbi/riscv_io.h> -#include <sbi/sbi_domain.h> -#include <sbi/sbi_error.h> -#include <sbi/sbi_hartmask.h> -#include <sbi/sbi_ipi.h> -#include <sbi/sbi_timer.h> -#include <sbi_utils/sys/clint.h> - -#define CLINT_IPI_OFF 0 -#define CLINT_IPI_SIZE 0x4000 - -#define CLINT_TIME_CMP_OFF 0x4000 -#define CLINT_TIME_CMP_SIZE 0x4000 - -#define CLINT_TIME_VAL_OFF 0xbff8 -#define CLINT_TIME_VAL_SIZE 0x4000 - -static struct clint_data *clint_ipi_hartid2data[SBI_HARTMASK_MAX_BITS]; - -static void clint_ipi_send(u32 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 - clint->first_hartid]); -} - -static void clint_ipi_clear(u32 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 - clint->first_hartid]); -} - -static struct sbi_ipi_device clint_ipi = { - .name = "clint", - .ipi_send = clint_ipi_send, - .ipi_clear = clint_ipi_clear -}; - -int clint_warm_ipi_init(void) -{ - /* Clear CLINT IPI for current HART */ - clint_ipi_clear(current_hartid()); - - return 0; -} - -int clint_cold_ipi_init(struct clint_data *clint) -{ - u32 i; - int rc; - struct sbi_domain_memregion reg; - - 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; - - /* Add CLINT ipi region to the root domain */ - sbi_domain_memregion_init(clint->addr + CLINT_IPI_OFF, - CLINT_IPI_SIZE, - SBI_DOMAIN_MEMREGION_MMIO, ®); - rc = sbi_domain_root_add_memregion(®); - if (rc) - return rc; - - sbi_ipi_set_device(&clint_ipi); - - return 0; -} - -static struct clint_data *clint_timer_hartid2data[SBI_HARTMASK_MAX_BITS]; - -#if __riscv_xlen != 32 -static u64 clint_time_rd64(volatile u64 *addr) -{ - return readq_relaxed(addr); -} - -static void clint_time_wr64(u64 value, volatile u64 *addr) -{ - writeq_relaxed(value, addr); -} -#endif - -static u64 clint_time_rd32(volatile u64 *addr) -{ - u32 lo, hi; - - do { - hi = readl_relaxed((u32 *)addr + 1); - lo = readl_relaxed((u32 *)addr); - } while (hi != readl_relaxed((u32 *)addr + 1)); - - return ((u64)hi << 32) | (u64)lo; -} - -static void clint_time_wr32(u64 value, volatile u64 *addr) -{ - u32 mask = -1U; - - writel_relaxed(value & mask, (void *)(addr)); - writel_relaxed(value >> 32, (void *)(addr) + 0x04); -} - -static 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) + clint->time_delta; -} - -static void clint_timer_event_stop(void) -{ - u32 target_hart = current_hartid(); - struct clint_data *clint = clint_timer_hartid2data[target_hart]; - - /* Clear CLINT Time Compare */ - clint->time_wr(-1ULL, - &clint->time_cmp[target_hart - clint->first_hartid]); -} - -static void clint_timer_event_start(u64 next_event) -{ - u32 target_hart = current_hartid(); - struct clint_data *clint = clint_timer_hartid2data[target_hart]; - - /* Program CLINT Time Compare */ - clint->time_wr(next_event - clint->time_delta, - &clint->time_cmp[target_hart - clint->first_hartid]); -} - -static struct sbi_timer_device clint_timer = { - .name = "clint", - .timer_value = clint_timer_value, - .timer_event_start = clint_timer_event_start, - .timer_event_stop = clint_timer_event_stop -}; - -int clint_warm_timer_init(void) -{ - u64 v1, v2, mv; - u32 target_hart = current_hartid(); - 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->first_hartid]); - - return 0; -} - -int clint_cold_timer_init(struct clint_data *clint, - struct clint_data *reference) -{ - u32 i; - int rc; - struct sbi_domain_memregion reg; - - 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 (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; - - /* Add CLINT mtime region to the root domain */ - sbi_domain_memregion_init(clint->addr + CLINT_TIME_VAL_OFF, - CLINT_TIME_VAL_SIZE, - SBI_DOMAIN_MEMREGION_MMIO, ®); - rc = sbi_domain_root_add_memregion(®); - if (rc) - return rc; - - /* Add CLINT timecmp region to the root domain */ - sbi_domain_memregion_init(clint->addr + CLINT_TIME_CMP_OFF, - CLINT_TIME_CMP_SIZE, - SBI_DOMAIN_MEMREGION_MMIO, ®); - rc = sbi_domain_root_add_memregion(®); - if (rc) - return rc; - - sbi_timer_set_device(&clint_timer); - - return 0; -} diff --git a/lib/utils/sys/objects.mk b/lib/utils/sys/objects.mk index 7878ca8..06be322 100644 --- a/lib/utils/sys/objects.mk +++ b/lib/utils/sys/objects.mk @@ -7,6 +7,5 @@ # Anup Patel <anup.patel@wdc.com> # -libsbiutils-objs-y += sys/clint.o libsbiutils-objs-y += sys/htif.o libsbiutils-objs-y += sys/sifive_test.o |