[PATCH 3/6] platform: andes: Add Andes custom PMU support

Yu Chien Peter Lin peterlin at andestech.com
Wed Sep 6 02:40:48 PDT 2023


Before the ratification of Sscofpmf, the Andes PMU extension was
designed to support the sampling and filtering of hardware performance
counters, compatible with the current SBI PMU extension and Linux perf
driver.

This patch implements the PMU extension platform callback and PMU device
callbacks to update the corresponding custom CSRs.

Signed-off-by: Yu Chien Peter Lin <peterlin at andestech.com>
Reviewed-by: Leo Yu-Chi Liang <ycliang at andestech.com>
---
 platform/generic/andes/Kconfig             |  4 +
 platform/generic/andes/andes_pmu.c         | 85 ++++++++++++++++++++++
 platform/generic/andes/objects.mk          |  1 +
 platform/generic/include/andes/andes_pmu.h | 12 +++
 4 files changed, 102 insertions(+)
 create mode 100644 platform/generic/andes/andes_pmu.c
 create mode 100644 platform/generic/include/andes/andes_pmu.h

diff --git a/platform/generic/andes/Kconfig b/platform/generic/andes/Kconfig
index a91fb9c..056327b 100644
--- a/platform/generic/andes/Kconfig
+++ b/platform/generic/andes/Kconfig
@@ -7,3 +7,7 @@ config ANDES45_PMA
 config ANDES_SBI
 	bool "Andes SBI support"
 	default n
+
+config ANDES_PMU
+	bool "Andes PMU support"
+	default n
diff --git a/platform/generic/andes/andes_pmu.c b/platform/generic/andes/andes_pmu.c
new file mode 100644
index 0000000..d2574c7
--- /dev/null
+++ b/platform/generic/andes/andes_pmu.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2022 Andes Technology Corporation
+ *
+ */
+#include <andes/andes45.h>
+#include <andes/andes_pmu.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_pmu.h>
+#include <sbi/sbi_scratch.h>
+
+static void andes_hw_counter_enable_irq(uint32_t ctr_idx)
+{
+	unsigned long mip_val;
+
+	if (ctr_idx >= SBI_PMU_HW_CTR_MAX)
+		return;
+
+	mip_val = csr_read(CSR_MIP);
+	if (!(mip_val & MIP_PMOVI))
+		csr_clear(CSR_MCOUNTEROVF, BIT(ctr_idx));
+
+	csr_set(CSR_MCOUNTERINTEN, BIT(ctr_idx));
+}
+
+static void andes_hw_counter_disable_irq(uint32_t ctr_idx)
+{
+	csr_clear(CSR_MCOUNTERINTEN, BIT(ctr_idx));
+}
+
+static void andes_hw_counter_filter_mode(unsigned long flags, int ctr_idx)
+{
+	if (!flags) {
+		csr_write(CSR_MCOUNTERMASK_S, 0);
+		csr_write(CSR_MCOUNTERMASK_U, 0);
+	}
+	if (flags & SBI_PMU_CFG_FLAG_SET_UINH) {
+		csr_clear(CSR_MCOUNTERMASK_S, BIT(ctr_idx));
+		csr_set(CSR_MCOUNTERMASK_U, BIT(ctr_idx));
+	}
+	if (flags & SBI_PMU_CFG_FLAG_SET_SINH) {
+		csr_set(CSR_MCOUNTERMASK_S, BIT(ctr_idx));
+		csr_clear(CSR_MCOUNTERMASK_U, BIT(ctr_idx));
+	}
+}
+
+static struct sbi_pmu_device andes_pmu = {
+	.name = "andes_pmu",
+	.hw_counter_enable_irq  = andes_hw_counter_enable_irq,
+	.hw_counter_disable_irq = andes_hw_counter_disable_irq,
+	/*
+	 * In andes_pmu_extensions_init(), we set mslideleg[18] for each
+	 * hart instead of mideleg, so leave hw_counter_irq_bit() hook
+	 * unimplemented.
+	 */
+	.hw_counter_irq_bit     = NULL,
+	.hw_counter_filter_mode = andes_hw_counter_filter_mode
+};
+
+int andes_pmu_extensions_init(const struct fdt_match *match,
+			      struct sbi_hart_features *hfeatures)
+{
+	if (andes_pmu()) {
+		/*
+		 * It is not rational for a hardware to support
+		 * both Andes PMU and standard Sscofpmf, as they
+		 * serve the same purpose.
+		 */
+		if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
+					   SBI_HART_EXT_SSCOFPMF))
+			ebreak();
+
+		/* Machine counter write enable */
+		csr_write(CSR_MCOUNTERWEN, 0xfffffffd);
+		/* disable HPM counter in M-mode */
+		csr_write(CSR_MCOUNTERMASK_M, 0xfffffffd);
+		/* delegate S-mode local interrupt to S-mode */
+		csr_write(CSR_MSLIDELEG, MIP_PMOVI);
+
+		sbi_pmu_set_device(&andes_pmu);
+	}
+
+	return 0;
+}
diff --git a/platform/generic/andes/objects.mk b/platform/generic/andes/objects.mk
index e8f86ea..6a8c66c 100644
--- a/platform/generic/andes/objects.mk
+++ b/platform/generic/andes/objects.mk
@@ -7,3 +7,4 @@ platform-objs-$(CONFIG_PLATFORM_ANDES_AE350) += andes/ae350.o andes/sleep.o
 
 platform-objs-$(CONFIG_ANDES45_PMA) += andes/andes45-pma.o
 platform-objs-$(CONFIG_ANDES_SBI) += andes/andes_sbi.o
+platform-objs-$(CONFIG_ANDES_PMU) += andes/andes_pmu.o
diff --git a/platform/generic/include/andes/andes_pmu.h b/platform/generic/include/andes/andes_pmu.h
new file mode 100644
index 0000000..8a2e136
--- /dev/null
+++ b/platform/generic/include/andes/andes_pmu.h
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: BSD-2-Clause
+
+#ifndef _RISCV_ANDES_PMU_H
+#define _RISCV_ANDES_PMU_H
+
+#include <sbi/sbi_hart.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+
+int andes_pmu_extensions_init(const struct fdt_match *match,
+			      struct sbi_hart_features *hfeatures);
+
+#endif /* _RISCV_ANDES_PMU_H */
-- 
2.34.1




More information about the opensbi mailing list