diff --git a/platform/generic/platform.c b/platform/generic/platform.c index da0c1af8..9eeb731d 100644 --- a/platform/generic/platform.c +++ b/platform/generic/platform.c @@ -184,7 +184,166 @@ static u64 generic_tlbr_flush_limit(void) return SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT; } +#include +#define CSR_MCOUNTERWEN 0x7c9 +static void sbi_thead_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 sbi_thead_pmu_map(unsigned long idx, unsigned long event_id) +{ + switch (idx) { + case 3: + csr_write(CSR_MHPMEVENT3, event_id); + break; + case 4: + csr_write(CSR_MHPMEVENT4, event_id); + break; + case 5: + csr_write(CSR_MHPMEVENT5, event_id); + break; + case 6: + csr_write(CSR_MHPMEVENT6, event_id); + break; + case 7: + csr_write(CSR_MHPMEVENT7, event_id); + break; + case 8: + csr_write(CSR_MHPMEVENT8, event_id); + break; + case 9: + csr_write(CSR_MHPMEVENT9, event_id); + break; + case 10: + csr_write(CSR_MHPMEVENT10, event_id); + break; + case 11: + csr_write(CSR_MHPMEVENT11, event_id); + break; + case 12: + csr_write(CSR_MHPMEVENT12, event_id); + break; + case 13: + csr_write(CSR_MHPMEVENT13, event_id); + break; + case 14: + csr_write(CSR_MHPMEVENT14, event_id); + break; + case 15: + csr_write(CSR_MHPMEVENT15, event_id); + break; + case 16: + csr_write(CSR_MHPMEVENT16, event_id); + break; + case 17: + csr_write(CSR_MHPMEVENT17, event_id); + break; + case 18: + csr_write(CSR_MHPMEVENT18, event_id); + break; + case 19: + csr_write(CSR_MHPMEVENT19, event_id); + break; + case 20: + csr_write(CSR_MHPMEVENT20, event_id); + break; + case 21: + csr_write(CSR_MHPMEVENT21, event_id); + break; + case 22: + csr_write(CSR_MHPMEVENT22, event_id); + break; + case 23: + csr_write(CSR_MHPMEVENT23, event_id); + break; + case 24: + csr_write(CSR_MHPMEVENT24, event_id); + break; + case 25: + csr_write(CSR_MHPMEVENT25, event_id); + break; + case 26: + csr_write(CSR_MHPMEVENT26, event_id); + break; + case 27: + csr_write(CSR_MHPMEVENT27, event_id); + break; + case 28: + csr_write(CSR_MHPMEVENT28, event_id); + break; + case 29: + csr_write(CSR_MHPMEVENT29, event_id); + break; + case 30: + csr_write(CSR_MHPMEVENT30, event_id); + break; + case 31: + csr_write(CSR_MHPMEVENT31, event_id); + break; + } +} + +static void sbi_thead_pmu_set(unsigned long type, unsigned long idx, unsigned long event_id) +{ + switch (type) { + case 2: + sbi_thead_pmu_map(idx, event_id); + break; + default: + sbi_thead_pmu_init(); + break; + } +} + +static int thead_vendor_ext_provider(long extid, long funcid, + const struct sbi_trap_regs *regs, unsigned long *out_value, + struct sbi_trap_info *out_trap) +{ + switch (extid) { + case 0x09000001: + sbi_thead_pmu_set(regs->a0, regs->a1, regs->a2); + break; + default: + while(1); + } + return 0; +} + const struct sbi_platform_operations platform_ops = { + .vendor_ext_provider = thead_vendor_ext_provider, .early_init = generic_early_init, .final_init = generic_final_init, .early_exit = generic_early_exit,