[PATCH 2/2] platform: add thead-c9xx specific platform-overrides
Heiko Stuebner
heiko at sntech.de
Thu Mar 31 18:08:39 PDT 2022
From: Guo Ren <guoren at linux.alibaba.com>
The PMU on T-Head C9xx SoCs works differently with additional
CSRs and needs additional vendor ecalls to function correctly
both for initializing and mapping events to counters.
Add a fdt-matched T-Head platform for this and
disable the SBI PMU extension for it.
Signed-off-by: Guo Ren <guoren at linux.alibaba.com>
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
lib/sbi/sbi_ecall_pmu.c | 7 +++
platform/generic/objects.mk | 1 +
platform/generic/platform.c | 2 +
platform/generic/thead_c9xx.c | 91 +++++++++++++++++++++++++++++++++++
4 files changed, 101 insertions(+)
create mode 100644 platform/generic/thead_c9xx.c
diff --git a/lib/sbi/sbi_ecall_pmu.c b/lib/sbi/sbi_ecall_pmu.c
index 9ee9e81..5f6f7c9 100644
--- a/lib/sbi/sbi_ecall_pmu.c
+++ b/lib/sbi/sbi_ecall_pmu.c
@@ -76,6 +76,13 @@ static int sbi_ecall_pmu_probe(unsigned long extid, unsigned long *out_val)
{
/* PMU extension is always enabled */
*out_val = 1;
+
+ /* Some T-Head socs have a non-spec PMU */
+ if (csr_read(CSR_MVENDORID) == 0x5b7 &&
+ csr_read(CSR_MARCHID) == 0 &&
+ csr_read(CSR_MIMPID) == 0)
+ *out_val = 0;
+
return 0;
}
diff --git a/platform/generic/objects.mk b/platform/generic/objects.mk
index cb15a18..0d6c228 100644
--- a/platform/generic/objects.mk
+++ b/platform/generic/objects.mk
@@ -10,3 +10,4 @@
platform-objs-y += platform.o
platform-objs-y += sifive_fu540.o
platform-objs-y += sifive_fu740.o
+platform-objs-y += thead_c9xx.o
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index f05da8e..1a797dc 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -25,10 +25,12 @@
extern const struct platform_override sifive_fu540;
extern const struct platform_override sifive_fu740;
+extern const struct platform_override thead_c9xx;
static const struct platform_override *special_platforms[] = {
&sifive_fu540,
&sifive_fu740,
+ &thead_c9xx,
};
static const struct platform_override *generic_plat = NULL;
diff --git a/platform/generic/thead_c9xx.c b/platform/generic/thead_c9xx.c
new file mode 100644
index 0000000..782d4e7
--- /dev/null
+++ b/platform/generic/thead_c9xx.c
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Heiko Stuebner <heiko at sntech.de>
+ *
+ * Authors:
+ * Heiko Stuebner <heiko at sntech.de>
+ */
+
+#include <platform_override.h>
+#include <sbi/sbi_const.h>
+#include <sbi/sbi_trap.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/fdt/fdt_fixup.h>
+
+enum sbi_ext_thead_fid {
+ SBI_EXT_THEAD_PMU_INIT = 0,
+ SBI_EXT_THEAD_PMU_MAP,
+};
+
+#define CSR_MCOUNTERWEN 0x7c9
+
+static void thead_c9xx_pmu_init(void)
+{
+ unsigned long interrupts;
+
+ interrupts = csr_read(CSR_MIDELEG) | (1 << 17);
+ csr_write(CSR_MIDELEG, interrupts);
+
+ /* CSR_MCOUNTEREN has already been set in mstatus_init() */
+ csr_write(CSR_MCOUNTERWEN, 0xffffffff);
+ csr_write(CSR_MHPMEVENT3, 1);
+ csr_write(CSR_MHPMEVENT4, 2);
+ csr_write(CSR_MHPMEVENT5, 3);
+ csr_write(CSR_MHPMEVENT6, 4);
+ csr_write(CSR_MHPMEVENT7, 5);
+ csr_write(CSR_MHPMEVENT8, 6);
+ csr_write(CSR_MHPMEVENT9, 7);
+ csr_write(CSR_MHPMEVENT10, 8);
+ csr_write(CSR_MHPMEVENT11, 9);
+ csr_write(CSR_MHPMEVENT12, 10);
+ csr_write(CSR_MHPMEVENT13, 11);
+ csr_write(CSR_MHPMEVENT14, 12);
+ csr_write(CSR_MHPMEVENT15, 13);
+ csr_write(CSR_MHPMEVENT16, 14);
+ csr_write(CSR_MHPMEVENT17, 15);
+ csr_write(CSR_MHPMEVENT18, 16);
+ csr_write(CSR_MHPMEVENT19, 17);
+ csr_write(CSR_MHPMEVENT20, 18);
+ csr_write(CSR_MHPMEVENT21, 19);
+ csr_write(CSR_MHPMEVENT22, 20);
+ csr_write(CSR_MHPMEVENT23, 21);
+ csr_write(CSR_MHPMEVENT24, 22);
+ csr_write(CSR_MHPMEVENT25, 23);
+ csr_write(CSR_MHPMEVENT26, 24);
+ csr_write(CSR_MHPMEVENT27, 25);
+ csr_write(CSR_MHPMEVENT28, 26);
+}
+
+static void thead_c9xx_pmu_map(unsigned long idx, unsigned long event_id)
+{
+ if (idx >= 3 && idx <= 31)
+ csr_write_num(CSR_MHPMEVENT3 + idx - 3, event_id);
+}
+
+#include <sbi/sbi_console.h>
+static int thead_c9xx_vendor_ext_provider(long extid, long funcid,
+ const struct sbi_trap_regs *regs,
+ unsigned long *out_value,
+ struct sbi_trap_info *out_trap)
+{
+ switch (funcid) {
+ case SBI_EXT_THEAD_PMU_MAP:
+ thead_c9xx_pmu_map(regs->a0, regs->a1);
+ break;
+ case SBI_EXT_THEAD_PMU_INIT:
+ thead_c9xx_pmu_init();
+ break;
+ }
+ return 0;
+}
+
+static const struct fdt_match thead_c9xx_match[] = {
+ { .compatible = "allwinner,sun20i-d1" },
+ { },
+};
+
+const struct platform_override thead_c9xx = {
+ .match_table = thead_c9xx_match,
+ .vendor_ext_provider = thead_c9xx_vendor_ext_provider,
+};
--
2.35.1
More information about the opensbi
mailing list