[PATCH 2/2] platform: thead: restore platform CSR when suspend

Xiang W wxjstz at 126.com
Thu Dec 4 06:58:52 PST 2025


Some CSRs in Thead need to be backed up and restored during HART
suspend.

Signed-off-by: David Li <davidli.li at linux.alibaba.com>
Signed-off-by: Xiang W <wangxiang at iscas.ac.cn>
---
 .../generic/include/thead/c9xx_encoding.h     |  1 +
 platform/generic/thead/thead-generic.c        | 53 +++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/platform/generic/include/thead/c9xx_encoding.h b/platform/generic/include/thead/c9xx_encoding.h
index a45b171e..bcbd9e24 100644
--- a/platform/generic/include/thead/c9xx_encoding.h
+++ b/platform/generic/include/thead/c9xx_encoding.h
@@ -16,6 +16,7 @@
 #define THEAD_C9XX_CSR_MCOUNTEROF	0x7cb
 #define THEAD_C9XX_CSR_MHINT2		0x7cc
 #define THEAD_C9XX_CSR_MHINT3		0x7cd
+#define THEAD_C9XX_CSR_MHINT4		0x7ce
 #define THEAD_C9XX_CSR_MRADDR		0x7e0
 #define THEAD_C9XX_CSR_MEXSTATUS	0x7e1
 #define THEAD_C9XX_CSR_MNMICAUSE	0x7e2
diff --git a/platform/generic/thead/thead-generic.c b/platform/generic/thead/thead-generic.c
index ddb4f0bf..63e33849 100644
--- a/platform/generic/thead/thead-generic.c
+++ b/platform/generic/thead/thead-generic.c
@@ -7,6 +7,7 @@
  */
 
 #include <platform_override.h>
+#include <thead/c9xx_encoding.h>
 #include <thead/c9xx_errata.h>
 #include <thead/c9xx_pmu.h>
 #include <sbi/sbi_const.h>
@@ -15,10 +16,61 @@
 #include <sbi/sbi_string.h>
 #include <sbi_utils/fdt/fdt_helper.h>
 
+/* redefine CSR register */
+#define CSR_MXSTATUS	THEAD_C9XX_CSR_MXSTATUS
+#define CSR_MHCR	THEAD_C9XX_CSR_MHCR
+#define CSR_MCCR2	THEAD_C9XX_CSR_MCCR2
+#define CSR_MHINT	THEAD_C9XX_CSR_MHINT
+#define CSR_MHINT2_E	THEAD_C9XX_CSR_MHINT2
+#define CSR_MHINT4	THEAD_C9XX_CSR_MHINT4
+#define CSR_MSMPR	THEAD_C9XX_CSR_MSMPR
+#define CSR_SMPEN	CSR_MSMPR
+
 struct thead_generic_quirks {
 	u64	errata;
 };
 
+extern struct sbi_platform platform;
+
+static inline bool thead_has_hotplug(void)
+{
+	return platform.hart_count > 1;
+}
+
+static void thead_suspend_non_ret_save(unsigned long *data)
+{
+	data[0] = csr_read(CSR_SMPEN);
+	data[1] = csr_read(CSR_MCCR2);
+	data[2] = csr_read(CSR_MXSTATUS);
+	data[3] = csr_read(CSR_MHINT);
+	data[4] = csr_read(CSR_MHCR);
+	data[5] = csr_read(CSR_MHINT2_E);
+	data[6] = csr_read(CSR_MHINT4);
+}
+
+static void thead_suspend_non_ret_restore(unsigned long *data)
+{
+	csr_write(CSR_SMPEN, data[0]);
+	csr_write(CSR_MCCR2, data[1]);
+	csr_write(CSR_MXSTATUS, data[2]);
+	csr_write(CSR_MHINT, data[3]);
+	csr_write(CSR_MHCR, data[4]);
+	csr_write(CSR_MHINT2_E, data[5]);
+	csr_write(CSR_MHINT4, data[6]);
+}
+
+static int thead_nascent_init(void)
+{
+
+	if (thead_has_hotplug()) {
+		platform.suspend_backup_csr_count = 7;
+		generic_platform_ops.suspend_non_ret_save = thead_suspend_non_ret_save;
+		generic_platform_ops.suspend_non_ret_restore = thead_suspend_non_ret_restore;
+	}
+
+	return generic_nascent_init();
+}
+
 static int thead_tlb_flush_early_init(bool cold_boot)
 {
 	thead_register_tlb_flush_trap_handler();
@@ -44,6 +96,7 @@ static int thead_generic_platform_init(const void *fdt, int nodeoff,
 {
 	const struct thead_generic_quirks *quirks = match->data;
 
+	generic_platform_ops.nascent_init = thead_nascent_init;
 	if (quirks->errata & THEAD_QUIRK_ERRATA_TLB_FLUSH)
 		generic_platform_ops.early_init = thead_tlb_flush_early_init;
 	if (quirks->errata & THEAD_QUIRK_ERRATA_THEAD_PMU)
-- 
2.47.3




More information about the opensbi mailing list