summaryrefslogtreecommitdiff
path: root/lib/utils/sys
diff options
context:
space:
mode:
authorAtish Patra <atish.patra@wdc.com>2019-06-19 00:54:03 +0300
committerAnup Patel <anup.patel@wdc.com>2019-06-19 07:18:56 +0300
commit793e5e1184f04012804914bd922e68536f3b68dd (patch)
treecb2ec2a81ed5e832de5c9c8a79dca17fce599af8 /lib/utils/sys
parent98aaf8317b74414afa78078bc056670f46c45f41 (diff)
downloadopensbi-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.c162
-rw-r--r--lib/utils/sys/objects.mk10
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