diff options
-rw-r--r-- | platform/generic/platform.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/platform/generic/platform.c b/platform/generic/platform.c index 79d5230..0787d10 100644 --- a/platform/generic/platform.c +++ b/platform/generic/platform.c @@ -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, |