feat(dsu): save/restore DSU PMU register
Adds driver support to preserve DSU PMU register values over a DSU
power cycle. This driver needs to be enabled by the platforms that
support DSU and also need it's PMU registers to be preserved
Change-Id: I7fc68a3d7d99ee369379aa5cd114fffc763fc0d2
Signed-off-by: Arvind Ram Prakash <arvind.ramprakash@arm.com>
diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h
index 73b2d76..d32ead4 100644
--- a/include/arch/aarch32/arch.h
+++ b/include/arch/aarch32/arch.h
@@ -795,7 +795,21 @@
/*******************************************************************************
* Definitions for DynamicIQ Shared Unit registers
******************************************************************************/
-#define CLUSTERPWRDN p15, 0, c15, c3, 6
+#define CLUSTERPWRDN p15, 0, c15, c3, 6
+#define CLUSTERPMCR p15, 0, c15, c5, 0
+#define CLUSTERPMCNTENSET p15, 0, c15, c5, 1
+#define CLUSTERPMCCNTR p15, 0, c15, c6, 0
+#define CLUSTERPMOVSSET p15, 0, c15, c5, 3
+#define CLUSTERPMOVSCLR p15, 0, c15, c5, 4
+#define CLUSTERPMSELR p15, 0, c15, c5, 5
+#define CLUSTERPMXEVTYPER p15, 0, c15, c6, 1
+#define CLUSTERPMXEVCNTR p15, 0, c15, c6, 2
+
+/* CLUSTERPMCR register definitions */
+#define CLUSTERPMCR_E_BIT BIT(0)
+#define CLUSTERPMCR_N_SHIFT U(11)
+#define CLUSTERPMCR_N_MASK U(0x1f)
+
/* CLUSTERPWRDN register definitions */
#define DSU_CLUSTER_PWR_OFF 0
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index 3244d3b..adc96ae 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, ARM Limited and Contributors. All rights reserved.
* Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -354,6 +354,14 @@
* DynamIQ Shared Unit power management
*/
DEFINE_COPROCR_RW_FUNCS(clusterpwrdn, CLUSTERPWRDN)
+DEFINE_COPROCR_RW_FUNCS(clusterpmcr, CLUSTERPMCR)
+DEFINE_COPROCR_RW_FUNCS(clusterpmcntenset, CLUSTERPMCNTENSET)
+DEFINE_COPROCR_RW_FUNCS(clusterpmccntr, CLUSTERPMCCNTR)
+DEFINE_COPROCR_RW_FUNCS(clusterpmovsset, CLUSTERPMOVSSET)
+DEFINE_COPROCR_RW_FUNCS(clusterpmovsclr, CLUSTERPMOVSCLR)
+DEFINE_COPROCR_RW_FUNCS(clusterpmselr, CLUSTERPMSELR)
+DEFINE_COPROCR_RW_FUNCS(clusterpmxevcntr, CLUSTERPMXEVCNTR)
+DEFINE_COPROCR_RW_FUNCS(clusterpmxevtyper, CLUSTERPMXEVTYPER)
/*
* RNDR is AArch64 only, so just provide a placeholder here to make the
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index ea9aa51..4eb54ed 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -1482,4 +1482,17 @@
/* alternative system register encoding for the "sb" speculation barrier */
#define SYSREG_SB S0_3_C3_C0_7
+#define CLUSTERPMCR_EL1 S3_0_C15_C5_0
+#define CLUSTERPMCNTENSET_EL1 S3_0_C15_C5_1
+#define CLUSTERPMCCNTR_EL1 S3_0_C15_C6_0
+#define CLUSTERPMOVSSET_EL1 S3_0_C15_C5_3
+#define CLUSTERPMOVSCLR_EL1 S3_0_C15_C5_4
+#define CLUSTERPMSELR_EL1 S3_0_C15_C5_5
+#define CLUSTERPMXEVTYPER_EL1 S3_0_C15_C6_1
+#define CLUSTERPMXEVCNTR_EL1 S3_0_C15_C6_2
+
+#define CLUSTERPMCR_E_BIT BIT(0)
+#define CLUSTERPMCR_N_SHIFT U(11)
+#define CLUSTERPMCR_N_MASK U(0x1f)
+
#endif /* ARCH_H */
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 57dbc06..59adc7c 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -663,8 +663,16 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el1, GCSPR_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el0, GCSPR_EL0)
-/* DynamIQ Shared Unit power management */
+/* DynamIQ Control registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmcr_el1, CLUSTERPMCR_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmcntenset_el1, CLUSTERPMCNTENSET_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmccntr_el1, CLUSTERPMCCNTR_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmovsset_el1, CLUSTERPMOVSSET_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmovsclr_el1, CLUSTERPMOVSCLR_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmselr_el1, CLUSTERPMSELR_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmxevcntr_el1, CLUSTERPMXEVCNTR_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmxevtyper_el1, CLUSTERPMXEVTYPER_EL1)
/* CPU Power/Performance Management registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(cpuppmcr_el3, CPUPPMCR_EL3)
@@ -827,8 +835,32 @@
#define read_cpacr() read_cpacr_el1()
#define write_cpacr(_v) write_cpacr_el1(_v)
-#define read_clusterpwrdn() read_clusterpwrdn_el1()
-#define write_clusterpwrdn(_v) write_clusterpwrdn_el1(_v)
+#define read_clusterpwrdn() read_clusterpwrdn_el1()
+#define write_clusterpwrdn(_v) write_clusterpwrdn_el1(_v)
+
+#define read_clusterpmcr() read_clusterpmcr_el1()
+#define write_clusterpmcr(_v) write_clusterpmcr_el1(_v)
+
+#define read_clusterpmcntenset() read_clusterpmcntenset_el1()
+#define write_clusterpmcntenset(_v) write_clusterpmcntenset_el1(_v)
+
+#define read_clusterpmccntr() read_clusterpmccntr_el1()
+#define write_clusterpmccntr(_v) write_clusterpmccntr_el1(_v)
+
+#define read_clusterpmovsset() read_clusterpmovsset_el1()
+#define write_clusterpmovsset(_v) write_clusterpmovsset_el1(_v)
+
+#define read_clusterpmovsclr() read_clusterpmovsclr_el1()
+#define write_clusterpmovsclr(_v) write_clusterpmovsclr_el1(_v)
+
+#define read_clusterpmselr() read_clusterpmselr_el1()
+#define write_clusterpmselr(_v) write_clusterpmselr_el1(_v)
+
+#define read_clusterpmxevcntr() read_clusterpmxevcntr_el1()
+#define write_clusterpmxevcntr(_v) write_clusterpmxevcntr_el1(_v)
+
+#define read_clusterpmxevtyper() read_clusterpmxevtyper_el1()
+#define write_clusterpmxevtyper(_v) write_clusterpmxevtyper_el1(_v)
#if ERRATA_SPECULATIVE_AT
/*
diff --git a/include/drivers/arm/css/dsu.h b/include/drivers/arm/css/dsu.h
new file mode 100644
index 0000000..4d7822b
--- /dev/null
+++ b/include/drivers/arm/css/dsu.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DSU_H
+#define DSU_H
+
+#define PMCR_N_MAX 0x1f
+
+#define save_pmu_reg(state, reg) state->reg = read_##reg()
+
+#define restore_pmu_reg(context, reg) write_##reg(context->reg)
+
+typedef struct cluster_pmu_state{
+ uint64_t clusterpmcr;
+ uint64_t clusterpmcntenset;
+ uint64_t clusterpmccntr;
+ uint64_t clusterpmovsset;
+ uint64_t clusterpmselr;
+ uint64_t clusterpmsevtyper;
+ uint64_t counter_val[PMCR_N_MAX];
+ uint64_t counter_type[PMCR_N_MAX];
+} cluster_pmu_state_t;
+
+static inline unsigned int read_cluster_eventctr_num(void)
+{
+ return ((read_clusterpmcr() >> CLUSTERPMCR_N_SHIFT) &
+ CLUSTERPMCR_N_MASK);
+}
+
+
+void save_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_context);
+
+void restore_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_context);
+
+void cluster_on_dsu_pmu_context_restore(void);
+
+void cluster_off_dsu_pmu_context_save(void);
+
+#endif /* DSU_H */