[PATCH v3 1/3] platform: generic: spacemit: add K1
Troy Mitchell
troy.mitchell at linux.spacemit.com
Thu Sep 25 02:48:55 PDT 2025
From: Xianbin Zhu <xianbin.zhu at linux.spacemit.com>
Add initial platform support for the SpacemiT K1 SoC, including
early/final init hooks, cold boot handling, and CCI-550 snoop/DVM
enablement.
Co-authored-by: Troy Mitchell <troy.mitchell at linux.spacemit.com>
Signed-off-by: Troy Mitchell <troy.mitchell at linux.spacemit.com>
Signed-off-by: Xianbin Zhu <xianbin.zhu at linux.spacemit.com>
---
platform/generic/Kconfig | 4 ++
platform/generic/include/spacemit/k1.h | 98 +++++++++++++++++++++++++++
platform/generic/spacemit/k1.c | 119 +++++++++++++++++++++++++++++++++
3 files changed, 221 insertions(+)
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 7559a4bd8ccfcf7e0e7366141f632f5f5e13bd98..d0835126287ef080a44e30140b49c022695efd17 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -76,6 +76,10 @@ config PLATFORM_MIPS_P8700
bool "MIPS P8700 support"
default n
+config PLATFORM_SPACEMIT_K1
+ bool "Spacemit K1 support"
+ default n
+
source "$(OPENSBI_SRC_DIR)/platform/generic/andes/Kconfig"
source "$(OPENSBI_SRC_DIR)/platform/generic/thead/Kconfig"
diff --git a/platform/generic/include/spacemit/k1.h b/platform/generic/include/spacemit/k1.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd666346564698e04e69029de73eae863ac45d19
--- /dev/null
+++ b/platform/generic/include/spacemit/k1.h
@@ -0,0 +1,98 @@
+#ifndef __RISCV_SPACEMIT_K1_H__
+#define __RISCV_SPACEMIT_K1_H__
+
+#define CSR_MSETUP 0x7c0
+#define CSR_MHCR 0x7c1
+#define CSR_MRAOP 0x7c2
+#define CSR_MHINT 0x7c5
+#define CSR_ML2SETUP 0x7f0
+
+/* decache enable */
+#define MSETUP_DE BIT(0)
+/* icache enable */
+#define MSETUP_IE BIT(1)
+/* branch prediction enable */
+#define MSETUP_BPE BIT(4)
+/* prefetch functionality enable */
+#define MSETUP_PFE BIT(5)
+/* misaligned memory access enable */
+#define MSETUP_MME BIT(6)
+/* ECC enable */
+#define MSETUP_ECCE BIT(16)
+
+/* icache invalidation */
+#define MRAOP_ICACHE_INVALID GENMASK(1, 0)
+
+#define PMU_AP_BASE 0xd4282800
+
+#define PMU_AP_CORE0_WAKEUP_OFFSET (PMU_AP_BASE + 0x12c)
+#define PMU_AP_CORE4_WAKEUP_OFFSET (PMU_AP_BASE + 0x324)
+#define PMU_AP_CLUSTER0_WAKEUP_OFFSET(index) (PMU_AP_CORE0_WAKEUP_OFFSET + index * 4)
+#define PMU_AP_CLUSTER1_WAKEUP_OFFSET(index) (PMU_AP_CORE4_WAKEUP_OFFSET + index * 4)
+
+#define PMU_AP_CORE0_IDLE_CFG_OFFSET (PMU_AP_BASE + 0x124)
+#define PMU_AP_CORE4_IDLE_CFG_OFFSET (PMU_AP_BASE + 0x304)
+#define PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(index) (PMU_AP_CORE0_IDLE_CFG_OFFSET + index * 4)
+#define PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(index) (PMU_AP_CORE4_IDLE_CFG_OFFSET + index * 4)
+
+#define PMU_AP_CORE0_WAKEUP PMU_AP_CLUSTER0_WAKEUP_OFFSET(0)
+#define PMU_AP_CORE1_WAKEUP PMU_AP_CLUSTER0_WAKEUP_OFFSET(1)
+#define PMU_AP_CORE2_WAKEUP PMU_AP_CLUSTER0_WAKEUP_OFFSET(2)
+#define PMU_AP_CORE3_WAKEUP PMU_AP_CLUSTER0_WAKEUP_OFFSET(3)
+#define PMU_AP_CORE4_WAKEUP PMU_AP_CLUSTER1_WAKEUP_OFFSET(0)
+#define PMU_AP_CORE5_WAKEUP PMU_AP_CLUSTER1_WAKEUP_OFFSET(1)
+#define PMU_AP_CORE6_WAKEUP PMU_AP_CLUSTER1_WAKEUP_OFFSET(2)
+#define PMU_AP_CORE7_WAKEUP PMU_AP_CLUSTER1_WAKEUP_OFFSET(3)
+
+#define PMU_AP_CORE0_IDLE_CFG PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(0)
+#define PMU_AP_CORE1_IDLE_CFG PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(1)
+#define PMU_AP_CORE2_IDLE_CFG PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(2)
+#define PMU_AP_CORE3_IDLE_CFG PMU_AP_CLUSTER0_IDLE_CFG_OFFSET(3)
+#define PMU_AP_CORE4_IDLE_CFG PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(0)
+#define PMU_AP_CORE5_IDLE_CFG PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(1)
+#define PMU_AP_CORE6_IDLE_CFG PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(2)
+#define PMU_AP_CORE7_IDLE_CFG PMU_AP_CLUSTER1_IDLE_CFG_OFFSET(3)
+
+/* power down */
+#define PMU_AP_IDLE_PWRDWN BIT(0)
+/* sram power down */
+#define PMU_AP_IDLE_SRAM_PWRDWN BIT(1)
+/* enable wake up the memory controller */
+#define PMU_AP_IDLE_WAKE_MCE BIT(3)
+/* disable memory controller software req */
+#define PMU_AP_IDLE_MC_SW_REQ BIT(4)
+
+#define PMU_AP_IDLE_PWRDOWN_MASK (PMU_AP_IDLE_PWRDWN | PMU_AP_IDLE_SRAM_PWRDWN | \
+ PMU_AP_IDLE_WAKE_MCE | PMU_AP_IDLE_MC_SW_REQ)
+/* cci */
+#define C0_RVBADDR_LO_ADDR 0xd4282db0
+#define C0_RVBADDR_HI_ADDR 0xd4282db4
+#define C1_RVBADDR_LO_ADDR 0xd4282eb0
+#define C1_RVBADDR_HI_ADDR 0xd4282c04
+
+#define CCI_550_PLATFORM_CCI_ADDR 0xd8500000
+
+/* relative to cci base */
+#define CCI_550_STATUS 0x000c
+/* status register bits */
+#define CCI_550_STATUS_CHANGE_PENDING BIT(0)
+
+/* slave interface registers */
+#define CCI_550_SLAVE_IFACE0_OFFSET 0x1000
+#define CCI_550_SLAVE_IFACE_OFFSET(idx) (CCI_550_SLAVE_IFACE0_OFFSET + ((0x1000) * (idx)))
+
+/* relative to slave interface base */
+#define CCI_550_SNOOP_CTRL 0x0000
+/* snoop control register bits */
+#define CCI_550_SNOOP_CTRL_ENABLE_SNOOPS BIT(0)
+#define CCI_550_SNOOP_CTRL_ENABLE_DVMS BIT(1)
+
+/* clusters and CPU mapping */
+#define PLATFORM_MAX_CPUS 8
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
+#define CPU_TO_CLUSTER(cpu) ((cpu) / PLATFORM_MAX_CPUS_PER_CLUSTER)
+
+#define PLAT_CCI_CLUSTER0_IFACE_IX 0
+#define PLAT_CCI_CLUSTER1_IFACE_IX 1
+
+#endif
diff --git a/platform/generic/spacemit/k1.c b/platform/generic/spacemit/k1.c
new file mode 100644
index 0000000000000000000000000000000000000000..296365e9c4a7993a3a3560d17aeeeda71520c2b6
--- /dev/null
+++ b/platform/generic/spacemit/k1.c
@@ -0,0 +1,119 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SpacemiT
+ * Authors:
+ * Xianbin Zhu <xianbin.zhu at linux.spacemit.com>
+ * Troy Mitchell <troy.mitchell at linux.spacemit.com>
+ */
+
+#include <platform_override.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_hsm.h>
+#include <spacemit/k1.h>
+
+/* only use 0-1 cluster in SpacemiT K1 */
+static const int cci_map[] = {
+ PLAT_CCI_CLUSTER0_IFACE_IX,
+ PLAT_CCI_CLUSTER1_IFACE_IX,
+};
+
+static void cci_enable_snoop_dvm_reqs(unsigned int master_id)
+{
+ int slave_if_id = cci_map[master_id];
+
+ /*
+ * Enable Snoops and DVM messages, no need for Read/Modify/Write as
+ * rest of bits are write ignore
+ */
+ writel(CCI_550_SNOOP_CTRL_ENABLE_DVMS | CCI_550_SNOOP_CTRL_ENABLE_SNOOPS,
+ (void *)(u64)CCI_550_PLATFORM_CCI_ADDR +
+ CCI_550_SLAVE_IFACE_OFFSET(slave_if_id) + CCI_550_SNOOP_CTRL);
+
+ /*
+ * Wait for the completion of the write to the Snoop Control Register
+ * before testing the change_pending bit
+ */
+ mb();
+
+ /* Wait for the dust to settle down */
+ while ((readl((void *)(u64)CCI_550_PLATFORM_CCI_ADDR + CCI_550_STATUS) &
+ CCI_550_STATUS_CHANGE_PENDING))
+ ;
+}
+
+static void spacemit_k1_pre_init(void)
+{
+ unsigned int clusterid, cluster_enabled = 0;
+ struct sbi_scratch *scratch;
+ int i;
+
+ scratch = sbi_scratch_thishart_ptr();
+
+ writel(scratch->warmboot_addr, (unsigned int *)C0_RVBADDR_LO_ADDR);
+ writel(scratch->warmboot_addr >> 32, (unsigned int *)C0_RVBADDR_HI_ADDR);
+
+ writel(scratch->warmboot_addr, (unsigned int *)C1_RVBADDR_LO_ADDR);
+ writel(scratch->warmboot_addr >> 32, (unsigned int *)C1_RVBADDR_HI_ADDR);
+
+ for (i = 0; i < PLATFORM_MAX_CPUS; i++) {
+ clusterid = CPU_TO_CLUSTER(i);
+
+ if (!(cluster_enabled & (1 << clusterid))) {
+ cluster_enabled |= 1 << clusterid;
+ cci_enable_snoop_dvm_reqs(clusterid);
+ }
+ }
+}
+
+/*
+ * Platform early initialization.
+ */
+static int spacemit_k1_early_init(bool cold_boot)
+{
+ int rc;
+
+ rc = generic_early_init(cold_boot);
+ if (rc)
+ return rc;
+
+ csr_set(CSR_MSETUP, MSETUP_DE | MSETUP_IE | MSETUP_BPE |
+ MSETUP_PFE | MSETUP_MME | MSETUP_ECCE);
+
+ if (cold_boot)
+ spacemit_k1_pre_init();
+
+ return 0;
+}
+
+static int spacemit_k1_final_init(bool cold_boot)
+{
+ return generic_final_init(cold_boot);
+}
+
+static bool spacemit_cold_boot_allowed(u32 hartid)
+{
+ csr_set(CSR_ML2SETUP, 1 << (hartid % PLATFORM_MAX_CPUS_PER_CLUSTER));
+
+ return !hartid;
+}
+
+static int spacemit_k1_platform_init(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ generic_platform_ops.early_init = spacemit_k1_early_init;
+ generic_platform_ops.final_init = spacemit_k1_final_init;
+ generic_platform_ops.cold_boot_allowed = spacemit_cold_boot_allowed;
+
+ return 0;
+}
+
+static const struct fdt_match spacemit_k1_match[] = {
+ { .compatible = "spacemit,k1" },
+ { /* sentinel */ }
+};
+
+const struct fdt_driver spacemit_k1 = {
+ .match_table = spacemit_k1_match,
+ .init = spacemit_k1_platform_init,
+};
--
2.51.0
More information about the opensbi
mailing list