From 1f84ec2ac22eaa866d7750f5d7941eb8711fadfc Mon Sep 17 00:00:00 2001 From: Xianbin Zhu Date: Thu, 25 Sep 2025 17:48:55 +0800 Subject: [PATCH] platform: generic: spacemit: add K1 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 Signed-off-by: Troy Mitchell Signed-off-by: Xianbin Zhu Reviewed-by: Anup Patel Link: https://lore.kernel.org/all/15169E392597D319+aOcKujCl8mz4XK4L@kernel.org/ [1] Link: https://lore.kernel.org/r/20250925-smt-k1-8-cores-v3-1-0885a8a70f8e@linux.spacemit.com Signed-off-by: Anup Patel --- platform/generic/Kconfig | 4 + platform/generic/include/spacemit/k1.h | 98 +++++++++++++++++++++ platform/generic/spacemit/k1.c | 113 +++++++++++++++++++++++++ 3 files changed, 215 insertions(+) create mode 100644 platform/generic/include/spacemit/k1.h create mode 100644 platform/generic/spacemit/k1.c diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig index 4b9bcfc6..89c5bb3c 100644 --- a/platform/generic/Kconfig +++ b/platform/generic/Kconfig @@ -83,6 +83,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 00000000..bd666346 --- /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 00000000..5430bbe8 --- /dev/null +++ b/platform/generic/spacemit/k1.c @@ -0,0 +1,113 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 SpacemiT + * Authors: + * Xianbin Zhu + * Troy Mitchell + */ + +#include +#include +#include +#include + +/* 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 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.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, +};