diff --git a/platform/generic/include/xuantie/xuantie_link.h b/platform/generic/include/xuantie/xuantie_link.h index 02b113f8..ebce8c64 100644 --- a/platform/generic/include/xuantie/xuantie_link.h +++ b/platform/generic/include/xuantie/xuantie_link.h @@ -28,6 +28,11 @@ #define XUANTIE_LINK_PMU_HPCPINTPEND 0x5e8 #define XUANTIE_LINK_PMU_VENDOR_N_IMP_ID 0x600 // XL300 +#define XUANTIE_LINK_PMU_NUM_COUNTERS 6 +#define XUANTIE_LINK_PMU_CNT_BITMAP GENMASK_ULL(XUANTIE_LINK_PMU_NUM_COUNTERS - 1, 0) +#define XUANTIE_LINK_PMU_AUTHCR_AUTH BIT_ULL(40) +#define XUANTIE_LINK_PMU_AUTHCR_INTPEND BIT_ULL(32) + /* HPCP dev type */ #define XUANTIE_LINK_DEV_TYPE_XL100 100 #define XUANTIE_LINK_DEV_TYPE_XL200 200 diff --git a/platform/generic/xuantie/xuantie_link.c b/platform/generic/xuantie/xuantie_link.c index 89c86ac9..0093b7e9 100644 --- a/platform/generic/xuantie/xuantie_link.c +++ b/platform/generic/xuantie/xuantie_link.c @@ -12,29 +12,48 @@ int xuantie_link_pmu_device_init(void) { #if __riscv_xlen == 64 - int nodeoffset, rc, dev_type; - uint64_t addr; + static const struct { + const char *compat; + int dev_type; + } pmu_match[] = { + { "xuantie,xl100-pmu", XUANTIE_LINK_DEV_TYPE_XL100 }, + { "xuantie,xl200-pmu", XUANTIE_LINK_DEV_TYPE_XL200 }, + { "xuantie,xl300-pmu", XUANTIE_LINK_DEV_TYPE_XL300 }, + }; void *fdt = fdt_get_address_rw(); + bool found = false; + unsigned int i; - if ((nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "xuantie,xl100-pmu")) > 0) - dev_type = XUANTIE_LINK_DEV_TYPE_XL100; - else if ((nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "xuantie,xl200-pmu")) > 0) - dev_type = XUANTIE_LINK_DEV_TYPE_XL200; - else if ((nodeoffset = fdt_node_offset_by_compatible(fdt, -1, "xuantie,xl300-pmu")) > 0) - dev_type = XUANTIE_LINK_DEV_TYPE_XL300; - else + if (!fdt) return SBI_ENODEV; - rc = fdt_get_node_addr_size(fdt, nodeoffset, 0, &addr, NULL); - if (rc) - return SBI_ENODEV; + for (i = 0; i < array_size(pmu_match); i++) { + int nodeoffset = -1; + + while ((nodeoffset = fdt_node_offset_by_compatible( + fdt, nodeoffset, pmu_match[i].compat)) >= 0) { + uint64_t addr; + + if (!fdt_node_is_enabled(fdt, nodeoffset)) + continue; + if (fdt_get_node_addr_size(fdt, nodeoffset, 0, &addr, NULL)) + continue; - if (dev_type == XUANTIE_LINK_DEV_TYPE_XL300) - writeq(BIT_ULL(40) | BIT_ULL(32) | 0x3f, (void *)addr + XUANTIE_LINK_PMU_HPCPHAUTHCR); - writeq(0x3f, (void *)addr + XUANTIE_LINK_PMU_HPCPMAUTHCR); - writeq(0x3f, (void *)addr + XUANTIE_LINK_PMU_HPCPSAUTHCR); - writeq(0x1, (void *)addr + XUANTIE_LINK_PMU_L3MAUTHCR); - writeq(0x0, (void *)addr + XUANTIE_LINK_PMU_HPCPINHIBIT); + if (pmu_match[i].dev_type == XUANTIE_LINK_DEV_TYPE_XL300) + writeq(XUANTIE_LINK_PMU_AUTHCR_AUTH | + XUANTIE_LINK_PMU_AUTHCR_INTPEND | + XUANTIE_LINK_PMU_CNT_BITMAP, + (void *)addr + XUANTIE_LINK_PMU_HPCPHAUTHCR); + writeq(XUANTIE_LINK_PMU_CNT_BITMAP, (void *)addr + XUANTIE_LINK_PMU_HPCPMAUTHCR); + writeq(XUANTIE_LINK_PMU_CNT_BITMAP, (void *)addr + XUANTIE_LINK_PMU_HPCPSAUTHCR); + writeq(0x1, (void *)addr + XUANTIE_LINK_PMU_L3MAUTHCR); + writeq(XUANTIE_LINK_PMU_CNT_BITMAP, (void *)addr + XUANTIE_LINK_PMU_HPCPINHIBIT); + found = true; + } + } + + if (!found) + return SBI_ENODEV; #endif return SBI_OK; }