@@ -16,6 +16,7 @@
#include <sbi_utils/fdt/fdt_domain.h>
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/fdt/fdt_pmu.h>
#include <sbi_utils/irqchip/fdt_irqchip.h>
#include <sbi_utils/serial/fdt_serial.h>
#include <sbi_utils/timer/fdt_timer.h>
@@ -184,6 +185,33 @@ static u64 generic_tlbr_flush_limit(void)
return SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT;
}
+static int generic_pmu_init(void)
+{
+ return fdt_pmu_setup(sbi_scratch_thishart_arg1_ptr());
+}
+
+static uint64_t generic_pmu_xlate_to_mhpmevent(uint32_t event_idx,
+ uint64_t data)
+{
+ uint64_t evt_val = 0;
+
+ /* data is valid only for raw events and is equal to event selector */
+ if (event_idx == SBI_PMU_EVENT_RAW_IDX)
+ evt_val = data;
+ else {
+ /**
+ * Generic platform follows the SBI specification recommendation
+ * i.e. zero extended event_idx is used as mhpmevent value for
+ * hardware general/cache events if platform does't define one.
+ */
+ evt_val = fdt_pmu_get_select_value(event_idx);
+ if (!evt_val)
+ evt_val = (uint64_t)event_idx;
+ }
+
+ return evt_val;
+}
+
const struct sbi_platform_operations platform_ops = {
.early_init = generic_early_init,
.final_init = generic_final_init,
@@ -195,6 +223,8 @@ const struct sbi_platform_operations platform_ops = {
.irqchip_exit = fdt_irqchip_exit,
.ipi_init = fdt_ipi_init,
.ipi_exit = fdt_ipi_exit,
+ .pmu_init = generic_pmu_init,
+ .pmu_xlate_to_mhpmevent = generic_pmu_xlate_to_mhpmevent,
.get_tlbr_flush_limit = generic_tlbr_flush_limit,
.timer_init = fdt_timer_init,
.timer_exit = fdt_timer_exit,