diff options
author | Atish Patra <atish.patra@wdc.com> | 2019-06-19 00:54:03 +0300 |
---|---|---|
committer | Anup Patel <anup.patel@wdc.com> | 2019-06-19 07:18:56 +0300 |
commit | 793e5e1184f04012804914bd922e68536f3b68dd (patch) | |
tree | cb2ec2a81ed5e832de5c9c8a79dca17fce599af8 /lib/utils/sys | |
parent | 98aaf8317b74414afa78078bc056670f46c45f41 (diff) | |
download | opensbi-793e5e1184f04012804914bd922e68536f3b68dd.tar.xz |
platform: Move platform common to lib/utils.
Currently, platform/common contains platform/non-platform specific
common minimal drivers and libraries. This is helpful is all platforms
are built within opensbi framework.
Move them to lib/utils so that any external platform code also can
reuse the minimalistic drivers or other common libraries.
This patch doesn't introduce any functional changes.
Signed-off-by: Atish Patra <atish.patra@wdc.com>
Acked-by: Anup Patel <anup.patel@wdc.com>
Diffstat (limited to 'lib/utils/sys')
-rw-r--r-- | lib/utils/sys/clint.c | 162 | ||||
-rw-r--r-- | lib/utils/sys/objects.mk | 10 |
2 files changed, 172 insertions, 0 deletions
diff --git a/lib/utils/sys/clint.c b/lib/utils/sys/clint.c new file mode 100644 index 0000000..055a513 --- /dev/null +++ b/lib/utils/sys/clint.c @@ -0,0 +1,162 @@ +/* + * 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_io.h> +#include <sbi/riscv_atomic.h> +#include <sbi/sbi_hart.h> +#include <sbi_utils/sys/clint.h> + +static u32 clint_ipi_hart_count; +static volatile void *clint_ipi_base; +static volatile u32 *clint_ipi; + +void clint_ipi_send(u32 target_hart) +{ + if (clint_ipi_hart_count <= target_hart) + return; + + /* Set CLINT IPI */ + writel(1, &clint_ipi[target_hart]); +} + +void clint_ipi_sync(u32 target_hart) +{ + u32 target_ipi, incoming_ipi; + u32 source_hart = sbi_current_hartid(); + + if (clint_ipi_hart_count <= target_hart) + return; + + /* Wait until target HART has handled IPI */ + incoming_ipi = 0; + while (1) { + target_ipi = readl(&clint_ipi[target_hart]); + if (!target_ipi) + break; + + incoming_ipi |= + atomic_raw_xchg_uint(&clint_ipi[source_hart], 0); + } + + if (incoming_ipi) + writel(incoming_ipi, &clint_ipi[source_hart]); +} + +void clint_ipi_clear(u32 target_hart) +{ + if (clint_ipi_hart_count <= target_hart) + return; + + /* Clear CLINT IPI */ + writel(0, &clint_ipi[target_hart]); +} + +int clint_warm_ipi_init(void) +{ + u32 hartid = sbi_current_hartid(); + + if (!clint_ipi_base) + return -1; + + /* Clear CLINT IPI */ + clint_ipi_clear(hartid); + + return 0; +} + +int clint_cold_ipi_init(unsigned long base, u32 hart_count) +{ + /* Figure-out CLINT IPI register address */ + clint_ipi_hart_count = hart_count; + clint_ipi_base = (void *)base; + clint_ipi = (u32 *)clint_ipi_base; + + 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; + +u64 clint_timer_value(void) +{ +#if __riscv_xlen == 64 + return readq_relaxed(clint_time_val); +#else + u64 tmp; + tmp = readl_relaxed((void *)clint_time_val + 0x04); + tmp <<= 32; + tmp |= readl_relaxed(clint_time_val); + return tmp; +#endif +} + +void clint_timer_event_stop(void) +{ + u32 target_hart = sbi_current_hartid(); + + if (clint_time_hart_count <= target_hart) + return; + + /* Clear CLINT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(-1ULL, &clint_time_cmp[target_hart]); +#else + writel_relaxed(-1UL, &clint_time_cmp[target_hart]); + writel_relaxed(-1UL, (void *)(&clint_time_cmp[target_hart]) + 0x04); +#endif +} + +void clint_timer_event_start(u64 next_event) +{ + u32 target_hart = sbi_current_hartid(); + + if (clint_time_hart_count <= target_hart) + return; + + /* Program CLINT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(next_event, &clint_time_cmp[target_hart]); +#else + u32 mask = -1UL; + writel_relaxed(next_event & mask, &clint_time_cmp[target_hart]); + writel_relaxed(next_event >> 32, + (void *)(&clint_time_cmp[target_hart]) + 0x04); +#endif +} + +int clint_warm_timer_init(void) +{ + u32 target_hart = sbi_current_hartid(); + + if (clint_time_hart_count <= target_hart || !clint_time_base) + return -1; + + /* Clear CLINT Time Compare */ +#if __riscv_xlen == 64 + writeq_relaxed(-1ULL, &clint_time_cmp[target_hart]); +#else + writel_relaxed(-1UL, &clint_time_cmp[target_hart]); + writel_relaxed(-1UL, (void *)(&clint_time_cmp[target_hart]) + 0x04); +#endif + + return 0; +} + +int clint_cold_timer_init(unsigned long base, u32 hart_count) +{ + /* 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); + + return 0; +} diff --git a/lib/utils/sys/objects.mk b/lib/utils/sys/objects.mk new file mode 100644 index 0000000..3c13b9b --- /dev/null +++ b/lib/utils/sys/objects.mk @@ -0,0 +1,10 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019 Western Digital Corporation or its affiliates. +# +# Authors: +# Anup Patel <anup.patel@wdc.com> +# + +libsbiutils-objs-$(PLATFORM_SYS_CLINT) += sys/clint.o |