OpenSBI Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support
@ 2026-08-27  9:19 Troy Mitchell
  2026-08-27  9:19 ` [PATCH v3 1/5] lib: sbi: select expected trap handler per hart Troy Mitchell
                   ` (5 more replies)
  0 siblings, 6 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-08-27  9:19 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Troy Mitchell

SpacemiT K3 combines eight X100 harts and eight A100 harts in four
clusters. The two core types expose different ISA capabilities: X100
implements H and has a 256-bit VLEN, while A100 does not implement H and
has a 1024-bit VLEN. OpenSBI currently selects one expected-trap handler
from the cold-boot hart, so an X100 boot hart would make A100 access H-only
CSRs. Select that handler per hart; the remaining extension and vector
state used by OpenSBI is already maintained or queried per hart.

Only hart 0 is powered at reset. Add a start-only HSM backend which removes
the requested hart's core and cluster power-down votes and wakes it on
demand. Before common warm-boot code runs, each hart restores the PMA
attributes expected by later firmware, enables cache snooping and prefetch,
and enables H on X100. The cold-boot hart also programs the cluster reset
vectors and enables CCI-550 snoop and DVM requests before secondary harts
can start.

K1 shares the vendor cache CSRs, PMU fields, cluster sizing, and CCI-550
helper with K3. Factor only those definitions and helpers into common
SpacemiT files; K1 keeps its topology, boot flow, and HSM behavior. Two
independent K1 fixes clarify the cache operation name and move per-hart
setup out of cold_boot_allowed().

The K3 SDK still loads ESOS for RPMI reset, suspend, and MPXY services.
Secondary-hart startup does not depend on the ESOS HSM service: the K3 HSM
driver matches the root node first and uses the SoC PMU directly, following
the SDK firmware's direct wakeup path.

Runtime validation on a SpacemiT K3 COM260 used the SDK's split NOR
firmware layout. OpenSBI was flashed as fw_dynamic.itb, then loaded from
NOR by the SDK FSBL. OpenSBI built from this series selected the
spacemit-k3-hsm device and reported 16 harts. U-Boot and Linux 6.18.3
started, Linux detected SBI v3.0 and the HSM extension, and all 16 CPUs
came online.

The series has been build-tested with:

  - the RV64 generic default configuration
  - RV64 K1-only and K3-only configurations
  - the RV32 generic configuration, where SpacemiT platform objects are
    intentionally omitted
  - the K3 SDK split OpenSBI and U-Boot packaging flow

The public K3 SDK v1.0.7 components needed to reproduce the firmware build
are pinned at:

  manifests:
    https://github.com/spacemit-com/manifests
    6d767b42fdbd759dc9511b8a13523c3de42aaa5a
  scripts:
    https://github.com/spacemit-com/scripts
    96418825a37a1cf07d3275c13d9d3329934224f0
  U-Boot:
    https://github.com/spacemit-com/uboot-2022.10
    676971d3a61f2583dfd53d8f7dfbc9607cea74b7
  ESOS and esos-lite:
    https://github.com/spacemit-com/esos
    eaf9afd83b27583b9bcafe0153028b32219518f5
    https://github.com/spacemit-com/esos-lite
    df4b2665cd4f3af563538cb41ba85c85dd39de7c

The kernel and root filesystem are independent of this firmware build.
Any board-compatible kernel and root filesystem may be used, so neither is
pinned here. EDK II is not used in this fastboot path.

Before building U-Boot, update UART0 in
bsp-src/uboot-2022.10/arch/riscv/dts/k3.dtsi. This DT is passed to OpenSBI:

  uart0: uart@d4017000 {
          ...
          compatible = "spacemit,k1-uart", "intel,xscale-uart",
                       "ns16550";
          ...
  };

The compatible order makes OpenSBI select UART_CAP_UUE and preserve
UART_IER_UUE (bit 6); matching only "ns16550" writes 0x00 to UART_IER and
stops serial output. Build U-Boot and use the FSBL, bootinfo, and U-Boot
FIT produced by the same SDK build:

  K3_SDK_DIR=/path/to/k3-sdk
  make -C "$K3_SDK_DIR" uboot

This produces the following files under output/k3/images:

  FSBL.bin
  bootinfo_spinor.bin
  u-boot.itb

Build OpenSBI at the address used by the SDK, then wrap fw_dynamic.bin in
the SDK's standalone OpenSBI FIT:

  make O=build-k3 CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=generic \
       PLATFORM_RISCV_ISA=rv64gc FW_TEXT_START=0x100000000
  FW_DIR="$PWD/build-k3/platform/generic/firmware"
  cp "$K3_SDK_DIR/bsp-src/opensbi/platform/generic/spacemit/fw_dynamic.its" \
     "$FW_DIR/"
  (cd "$FW_DIR" && \
   "$K3_SDK_DIR/output/k3/build/uboot-custom/tools/mkimage" \
     -f fw_dynamic.its fw_dynamic.itb)

There are two ways to enter U-Boot fastboot. On a provisioned board, hold
`s` during U-Boot startup and run:

  => fastboot 0

Alternatively, extract factory/FSBL.bin and u-boot.itb from
Bianbu-Minimal-K3-20260728010729.tar.gz. Hold FEL while resetting the
board to enter BROM fastboot, then run on the host:

  fastboot stage factory/FSBL.bin
  fastboot continue
  sleep 8
  fastboot stage u-boot.itb
  fastboot continue

COM260 boots from SPI NOR and uses partition_4M.json from the Bianbu image
for its firmware layout. Select that MTD layout before writing a firmware
partition:

  fastboot flash mtd partition_4M.json

If the installed FSBL and U-Boot already match the prerequisites above,
only the OpenSBI partition needs updating:

  fastboot flash opensbi "$FW_DIR/fw_dynamic.itb"
  fastboot reboot

For an older boot firmware, update the boot-chain components from the
pinned SDK build in the same fastboot session before rebooting:

  SDK_IMAGES="$K3_SDK_DIR/output/k3/images"
  fastboot flash bootinfo "$SDK_IMAGES/bootinfo_spinor.bin"
  fastboot flash fsbl "$SDK_IMAGES/FSBL.bin"
  fastboot flash uboot "$SDK_IMAGES/u-boot.itb"
  fastboot flash opensbi "$FW_DIR/fw_dynamic.itb"
  fastboot reboot

The full Bianbu Minimal image is only needed to initialize a board without
a usable system; this OpenSBI test does not otherwise depend on its Linux
or root filesystem images.

Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
Changes in v3:
  - select the HSM backend from the root compatible while preserving K1's
    existing start and stop behavior
  - start secondary harts on demand from the K3 HSM callback; remove the
    cold-boot wake-all loop, WFI tables, and timeout
  - perform PMA, cache, and H-extension setup before the common warm entry;
    use the OpenSBI VMA and guest-translation fence helpers
  - use assembler-safe constants shared by the C and assembly paths
  - omit the 64-bit-only SpacemiT platform objects from RV32 builds
  - clarify the boundary between the K3 HSM backend and ESOS services
  - update the cover letter with the public SDK build and split NOR
    validation procedure
  - add Reviewed-by trailers from Bo Gan
  - Link to v2: https://patch.msgid.link/20260818-spacemit-k3-v2-0-84cb7773a481@linux.spacemit.com

Changes in v2:
  - correct the K3 PMACFG0 CSR number from 0xbc0 to 0x7de
  - select the expected-trap handler per hart for heterogeneous H support
  - move K1 and K3 per-hart setup out of cold_boot_allowed()
  - split the generic and K1 fixes into standalone patches, growing the
    series from three patches to five
  - document X100/A100 ISA and VLEN differences and the homogeneous-core
    audit
  - document OpenSBI/U-Boot packaging, the UART compatible adjustment,
    and the USB fastboot test procedure
  - Link to v1: https://lore.kernel.org/r/20260724-spacemit-k3-v1-0-f0e49329feb8@linux.spacemit.com

---
Troy Mitchell (2):
      lib: sbi: select expected trap handler per hart
      platform: generic: spacemit: k1: move hart init to nascent hook

Xianbin Zhu (3):
      platform: generic: spacemit: k1: rename cache flush operation
      platform: generic: spacemit: k1: refactor platform support
      platform: generic: spacemit: k3: add platform support

 include/sbi/sbi_csr_detect.h                 |   4 +-
 include/sbi/sbi_hart.h                       |   2 +-
 lib/sbi/sbi_hart.c                           |   9 +-
 lib/sbi/sbi_illegal_atomic.c                 |   4 +-
 lib/sbi/sbi_unpriv.c                         |   6 +-
 lib/utils/hsm/fdt_hsm_spacemit.c             | 125 ++++++++++++++++++++------
 platform/generic/Kconfig                     |  11 +++
 platform/generic/configs/defconfig           |   1 +
 platform/generic/include/spacemit/common.h   |  90 +++++++++++++++++++
 platform/generic/include/spacemit/k1.h       |  96 ++++----------------
 platform/generic/include/spacemit/k3.h       | 127 +++++++++++++++++++++++++++
 platform/generic/include/spacemit/k3_asm.h   |  16 ++++
 platform/generic/include/spacemit/spacemit.h |  14 +++
 platform/generic/spacemit/k1.c               |  45 ++++------
 platform/generic/spacemit/k3.c               | 122 +++++++++++++++++++++++++
 platform/generic/spacemit/k3_asm.S           |  52 +++++++++++
 platform/generic/spacemit/objects.mk         |   5 ++
 platform/generic/spacemit/spacemit.c         |  36 ++++++++
 18 files changed, 617 insertions(+), 148 deletions(-)
---
base-commit: c0f87f10d1bfb9e72a84ddfafb5604ee1bfe9d04
change-id: 20260723-spacemit-k3-84720a7be53d

Best regards,
--  
Troy Mitchell <troy.mitchell@linux.spacemit.com>


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v3 1/5] lib: sbi: select expected trap handler per hart
  2026-08-27  9:19 [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Troy Mitchell
@ 2026-08-27  9:19 ` Troy Mitchell
  2026-08-31  2:21   ` Alvin Chang
  2026-08-27  9:19 ` [PATCH v3 2/5] platform: generic: spacemit: k1: rename cache flush operation Troy Mitchell
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 20+ messages in thread
From: Troy Mitchell @ 2026-08-27  9:19 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Troy Mitchell

The expected trap handler is selected once by the cold boot hart. This
breaks heterogeneous systems where the cold boot hart implements H but
another hart does not, because the H-aware handler accesses mtval2 and
mtinst.

Select the handler from the current hart's MISA at each use so every
hart uses only the CSRs it implements.

Fixes: 1de66d170e71 ("lib: Optimize unpriv load/store implementation")
Reported-by: Bo Gan <ganboing@gmail.com>
Link: https://lore.kernel.org/r/e702f291-dde8-4b99-a65e-182d2b847720@gmail.com
Suggested-by: Bo Gan <ganboing@gmail.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Reviewed-by: Bo Gan <ganboing@gmail.com>
---
 include/sbi/sbi_csr_detect.h | 4 ++--
 include/sbi/sbi_hart.h       | 2 +-
 lib/sbi/sbi_hart.c           | 9 +++++----
 lib/sbi/sbi_illegal_atomic.c | 4 ++--
 lib/sbi/sbi_unpriv.c         | 6 +++---
 5 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/include/sbi/sbi_csr_detect.h b/include/sbi/sbi_csr_detect.h
index 097c31c8..31e50db9 100644
--- a/include/sbi/sbi_csr_detect.h
+++ b/include/sbi/sbi_csr_detect.h
@@ -16,9 +16,9 @@
 
 #define csr_read_allowed(csr_num, trap)					\
 	({								\
+	register ulong mtvec = sbi_hart_expected_trap_addr();		\
 	register ulong tinfo asm("a3") = (ulong)trap;			\
 	register ulong ttmp asm("a4");					\
-	register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
 	register ulong ret = 0;						\
 	((struct sbi_trap_info *)(trap))->cause = 0;			\
 	asm volatile(							\
@@ -35,9 +35,9 @@
 
 #define csr_write_allowed(csr_num, trap, value)				\
 	({								\
+	register ulong mtvec = sbi_hart_expected_trap_addr();		\
 	register ulong tinfo asm("a3") = (ulong)trap;			\
 	register ulong ttmp asm("a4");					\
-	register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
 	((struct sbi_trap_info *)(trap))->cause = 0;			\
 	asm volatile(							\
 		"add %[ttmp], %[tinfo], zero\n"				\
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index 543393bb..6f4ee31e 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -135,7 +135,7 @@ struct sbi_scratch;
 int sbi_hart_reinit(struct sbi_scratch *scratch);
 int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
 
-extern void (*sbi_hart_expected_trap)(void);
+ulong sbi_hart_expected_trap_addr(void);
 
 unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
 void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index bee88557..14e44955 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -25,7 +25,11 @@
 extern void __sbi_expected_trap(void);
 extern void __sbi_expected_trap_hext(void);
 
-void (*sbi_hart_expected_trap)(void) = &__sbi_expected_trap;
+ulong sbi_hart_expected_trap_addr(void)
+{
+	return misa_extension('H') ? (ulong)&__sbi_expected_trap_hext :
+				     (ulong)&__sbi_expected_trap;
+}
 
 unsigned long hart_features_offset;
 
@@ -712,9 +716,6 @@ int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot)
 	csr_write(CSR_MIP, 0);
 
 	if (cold_boot) {
-		if (misa_extension('H'))
-			sbi_hart_expected_trap = &__sbi_expected_trap_hext;
-
 		hart_features_offset = sbi_scratch_alloc_offset(
 					sizeof(struct sbi_hart_features));
 		if (!hart_features_offset)
diff --git a/lib/sbi/sbi_illegal_atomic.c b/lib/sbi/sbi_illegal_atomic.c
index 977a9ad0..30f5118e 100644
--- a/lib/sbi/sbi_illegal_atomic.c
+++ b/lib/sbi/sbi_illegal_atomic.c
@@ -30,7 +30,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
 	{									\
 		register ulong tinfo asm("a3");					\
 		register ulong mstatus = 0;					\
-		register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
+		register ulong mtvec = sbi_hart_expected_trap_addr();		\
 		type ret = 0;							\
 		trap->cause = 0;						\
 		asm volatile(							\
@@ -57,7 +57,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
 	{									\
 		register ulong tinfo asm("a3");					\
 		register ulong mstatus = 0;					\
-		register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
+		register ulong mtvec = sbi_hart_expected_trap_addr();		\
 		type ret = 0;							\
 		trap->cause = 0;						\
 		asm volatile(							\
diff --git a/lib/sbi/sbi_unpriv.c b/lib/sbi/sbi_unpriv.c
index 60becedc..1550d111 100644
--- a/lib/sbi/sbi_unpriv.c
+++ b/lib/sbi/sbi_unpriv.c
@@ -33,9 +33,9 @@ union sbi_unpriv_data {
 	type sbi_load_##type(const type *addr,                                \
 			     struct sbi_trap_info *trap)                      \
 	{                                                                     \
+		register ulong mtvec = sbi_hart_expected_trap_addr();         \
 		register ulong tinfo asm("a3") = (ulong)trap;                 \
 		register ulong mstatus = 0;                                   \
-		register ulong mtvec = (ulong)sbi_hart_expected_trap;         \
 		type ret = 0;                                                 \
 		trap->cause = 0;                                              \
 		asm volatile(                                                 \
@@ -58,9 +58,9 @@ union sbi_unpriv_data {
 	void sbi_store_##type(type *addr, type val,                           \
 			      struct sbi_trap_info *trap)                     \
 	{                                                                     \
+		register ulong mtvec = sbi_hart_expected_trap_addr();         \
 		register ulong tinfo asm("a3") = (ulong)trap;                 \
 		register ulong mstatus = 0;                                   \
-		register ulong mtvec = (ulong)sbi_hart_expected_trap;         \
 		trap->cause = 0;                                              \
 		asm volatile(                                                 \
 			"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n"      \
@@ -207,7 +207,7 @@ ulong sbi_get_insn(ulong mepc, struct sbi_trap_info *trap)
 	register ulong tinfo asm("a3");
 	register ulong ttmp asm("a4");
 	register ulong mstatus = 0;
-	register ulong mtvec = (ulong)sbi_hart_expected_trap;
+	register ulong mtvec = sbi_hart_expected_trap_addr();
 	ulong insn = 0;
 
 	trap->cause = 0;

-- 
2.55.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 2/5] platform: generic: spacemit: k1: rename cache flush operation
  2026-08-27  9:19 [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Troy Mitchell
  2026-08-27  9:19 ` [PATCH v3 1/5] lib: sbi: select expected trap handler per hart Troy Mitchell
@ 2026-08-27  9:19 ` Troy Mitchell
  2026-08-27  9:19 ` [PATCH v3 3/5] platform: generic: spacemit: k1: move hart init to nascent hook Troy Mitchell
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-08-27  9:19 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Troy Mitchell

From: Xianbin Zhu <xianbin.zhu@linux.spacemit.com>

MRAOP_ICACHE_INVALID is used to flush the local D-cache before a hart
stops, so the name incorrectly describes I-cache invalidation. Rename
it to MRAOP_CACHE_FLUSH without changing its encoded value.

Signed-off-by: Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
Co-developed-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
 lib/utils/hsm/fdt_hsm_spacemit.c       | 2 +-
 platform/generic/include/spacemit/k1.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/utils/hsm/fdt_hsm_spacemit.c b/lib/utils/hsm/fdt_hsm_spacemit.c
index 868e49bf..99c52335 100644
--- a/lib/utils/hsm/fdt_hsm_spacemit.c
+++ b/lib/utils/hsm/fdt_hsm_spacemit.c
@@ -92,7 +92,7 @@ static int spacemit_hart_stop(void)
 	asm volatile ("fence iorw, iorw");
 
 	/* flush local dcache */
-	csr_write(CSR_MRAOP, MRAOP_ICACHE_INVALID);
+	csr_write(CSR_MRAOP, MRAOP_CACHE_FLUSH);
 	asm volatile ("fence iorw, iorw");
 
 	/* disable dcache */
diff --git a/platform/generic/include/spacemit/k1.h b/platform/generic/include/spacemit/k1.h
index 7095bc08..ac727b04 100644
--- a/platform/generic/include/spacemit/k1.h
+++ b/platform/generic/include/spacemit/k1.h
@@ -20,8 +20,8 @@
 /* ECC enable */
 #define MSETUP_ECCE				BIT(16)
 
-/* icache invalidation */
-#define MRAOP_ICACHE_INVALID			GENMASK(1, 0)
+/* cache flush */
+#define MRAOP_CACHE_FLUSH			GENMASK(1, 0)
 
 #define PMU_AP_BASE				0xd4282800
 

-- 
2.55.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 3/5] platform: generic: spacemit: k1: move hart init to nascent hook
  2026-08-27  9:19 [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Troy Mitchell
  2026-08-27  9:19 ` [PATCH v3 1/5] lib: sbi: select expected trap handler per hart Troy Mitchell
  2026-08-27  9:19 ` [PATCH v3 2/5] platform: generic: spacemit: k1: rename cache flush operation Troy Mitchell
@ 2026-08-27  9:19 ` Troy Mitchell
  2026-08-27  9:19 ` [PATCH v3 4/5] platform: generic: spacemit: k1: refactor platform support Troy Mitchell
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-08-27  9:19 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Troy Mitchell

cold_boot_allowed() is a policy query and should not modify per-hart
state. The K1 callback currently programs ML2SETUP as a side effect.

Move the ML2SETUP programming to nascent_init(), which runs on every
hart before common initialization. Chain generic_nascent_init() to keep
the generic per-hart setup intact.

Fixes: 1f84ec2ac22e ("platform: generic: spacemit: add K1")
Reported-by: Bo Gan <ganboing@gmail.com>
Link: https://lore.kernel.org/r/56220293-88e3-451f-833e-8251656a83d9@gmail.com
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Reviewed-by: Bo Gan <ganboing@gmail.com>
---
 platform/generic/spacemit/k1.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/platform/generic/spacemit/k1.c b/platform/generic/spacemit/k1.c
index 7ee5f17a..19a9b27c 100644
--- a/platform/generic/spacemit/k1.c
+++ b/platform/generic/spacemit/k1.c
@@ -8,6 +8,7 @@
  */
 
 #include <platform_override.h>
+#include <sbi/riscv_asm.h>
 #include <sbi/riscv_io.h>
 #include <sbi/sbi_hsm.h>
 #include <spacemit/k1.h>
@@ -86,16 +87,23 @@ static int spacemit_k1_early_init(bool cold_boot)
 	return 0;
 }
 
-static bool spacemit_cold_boot_allowed(u32 hartid)
+static int spacemit_k1_nascent_init(void)
 {
-	csr_set(CSR_ML2SETUP, 1 << (hartid % PLATFORM_MAX_CPUS_PER_CLUSTER));
+	csr_set(CSR_ML2SETUP,
+		1 << (current_hartid() % PLATFORM_MAX_CPUS_PER_CLUSTER));
+
+	return generic_nascent_init();
+}
 
+static bool spacemit_cold_boot_allowed(u32 hartid)
+{
 	return !hartid;
 }
 
 static int spacemit_k1_platform_init(const void *fdt, int nodeoff,
 				     const struct fdt_match *match)
 {
+	generic_platform_ops.nascent_init = spacemit_k1_nascent_init;
 	generic_platform_ops.early_init = spacemit_k1_early_init;
 	generic_platform_ops.cold_boot_allowed = spacemit_cold_boot_allowed;
 

-- 
2.55.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 4/5] platform: generic: spacemit: k1: refactor platform support
  2026-08-27  9:19 [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Troy Mitchell
                   ` (2 preceding siblings ...)
  2026-08-27  9:19 ` [PATCH v3 3/5] platform: generic: spacemit: k1: move hart init to nascent hook Troy Mitchell
@ 2026-08-27  9:19 ` Troy Mitchell
  2026-08-27  9:19 ` [PATCH v3 5/5] platform: generic: spacemit: k3: add " Troy Mitchell
       [not found] ` <20260831200832.404000-1-valentin.haudiquet@canonical.com>
  5 siblings, 0 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-08-27  9:19 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Troy Mitchell

From: Xianbin Zhu <xianbin.zhu@linux.spacemit.com>

K3 shares cache-control CSRs, PMU idle fields, cluster sizing, and the
CCI-550 programming sequence with K1. Keeping these definitions and the
CCI helper in K1-specific files would either duplicate them or make K3
depend on K1 support.

Add a hidden PLATFORM_SPACEMIT option and move the shared definitions to
spacemit/common.h. Move cci_enable_snoop_dvm_reqs() to spacemit.c while
keeping each SoC's CCI topology and boot flow in its own platform driver.

Rename the PMU idle fields to match the K1 and K3 User Manuals. Keep the
K1 power-down mask at 0x1b, so K1 power-management behavior remains
unchanged. Keep the K1 HSM implementation K1-specific and switch it to
the shared definitions.

This is a non-functional refactoring that prepares the common support
used by K3.

Signed-off-by: Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
Co-developed-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
 lib/utils/hsm/fdt_hsm_spacemit.c             | 10 +--
 platform/generic/Kconfig                     |  4 ++
 platform/generic/include/spacemit/common.h   | 86 +++++++++++++++++++++++++
 platform/generic/include/spacemit/k1.h       | 94 +++++-----------------------
 platform/generic/include/spacemit/spacemit.h | 14 +++++
 platform/generic/spacemit/k1.c               | 33 ++--------
 platform/generic/spacemit/objects.mk         |  1 +
 platform/generic/spacemit/spacemit.c         | 36 +++++++++++
 8 files changed, 169 insertions(+), 109 deletions(-)

diff --git a/lib/utils/hsm/fdt_hsm_spacemit.c b/lib/utils/hsm/fdt_hsm_spacemit.c
index 99c52335..6348f6a3 100644
--- a/lib/utils/hsm/fdt_hsm_spacemit.c
+++ b/lib/utils/hsm/fdt_hsm_spacemit.c
@@ -10,6 +10,7 @@
 #include <platform_override.h>
 #include <sbi/riscv_io.h>
 #include <sbi/sbi_hsm.h>
+#include <spacemit/common.h>
 #include <spacemit/k1.h>
 
 static const u64 cpu_wakeup_reg[] = {
@@ -42,9 +43,9 @@ static inline void spacemit_set_cpu_power(u32 hartid, bool enable)
 	value = readl(cpu_idle_base);
 
 	if (enable)
-		value &= ~PMU_AP_IDLE_PWRDOWN_MASK;
+		value &= ~PMU_AP_IDLE_PWRDOWN_K1_MASK;
 	else
-		value |= PMU_AP_IDLE_PWRDOWN_MASK;
+		value |= PMU_AP_IDLE_PWRDOWN_K1_MASK;
 
 	writel(value, cpu_idle_base);
 }
@@ -87,7 +88,7 @@ static int spacemit_hart_stop(void)
 	csr_write(CSR_STIMECMP, GENMASK_ULL(63, 0));
 	csr_clear(CSR_MIE, MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP | MIP_SEIP | MIP_MEIP);
 
-	/* disable data preftch */
+	/* disable data prefetch */
 	csr_clear(CSR_MSETUP, MSETUP_PFE);
 	asm volatile ("fence iorw, iorw");
 
@@ -102,8 +103,7 @@ static int spacemit_hart_stop(void)
 	/*
 	 * Core4-7 do not have dedicated bits in ML2SETUP;
 	 * instead, they reuse the same bits as core0-3.
-	 *
-	 * Thereforspacemit_deassert_cpue, use modulo with PLATFORM_MAX_CPUS_PER_CLUSTER
+	 * Therefore, use modulo with PLATFORM_MAX_CPUS_PER_CLUSTER
 	 * to select the proper bit.
 	 */
 	csr_clear(CSR_ML2SETUP, 1 << (current_hartid() % PLATFORM_MAX_CPUS_PER_CLUSTER));
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index d594b140..958610d3 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -100,9 +100,13 @@ config PLATFORM_THEAD
 	select THEAD_C9XX_PMU
 	default n
 
+config PLATFORM_SPACEMIT
+	bool
+
 config PLATFORM_SPACEMIT_K1
 	bool "Spacemit K1 support"
 	select FDT_HSM_SPACEMIT
+	select PLATFORM_SPACEMIT
 	default n
 
 config CPU_MIPS_P8700
diff --git a/platform/generic/include/spacemit/common.h b/platform/generic/include/spacemit/common.h
new file mode 100644
index 00000000..317bb3e9
--- /dev/null
+++ b/platform/generic/include/spacemit/common.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2025 SpacemiT
+ * Authors:
+ *   Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
+ *   Troy Mitchell <troy.mitchell@linux.spacemit.com>
+ */
+
+#ifndef __RISCV_SPACEMIT_COMMON_H__
+#define __RISCV_SPACEMIT_COMMON_H__
+
+#include <sbi/sbi_bitops.h>
+
+#define CSR_MSETUP				0x7c0
+#define CSR_ML2SETUP				0x7f0
+
+/* dcache 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)
+
+#define PMU_AP_BASE				0xd4282800
+
+#define PMU_AP_CORE0_WAKEUP			(PMU_AP_BASE + 0x12c)
+#define PMU_AP_CORE1_WAKEUP			(PMU_AP_BASE + 0x130)
+#define PMU_AP_CORE2_WAKEUP			(PMU_AP_BASE + 0x134)
+#define PMU_AP_CORE3_WAKEUP			(PMU_AP_BASE + 0x138)
+#define PMU_AP_CORE4_WAKEUP			(PMU_AP_BASE + 0x324)
+#define PMU_AP_CORE5_WAKEUP			(PMU_AP_BASE + 0x328)
+#define PMU_AP_CORE6_WAKEUP			(PMU_AP_BASE + 0x32c)
+#define PMU_AP_CORE7_WAKEUP			(PMU_AP_BASE + 0x330)
+
+#define PMU_AP_CORE0_IDLE_CFG			(PMU_AP_BASE + 0x124)
+#define PMU_AP_CORE1_IDLE_CFG			(PMU_AP_BASE + 0x128)
+#define PMU_AP_CORE2_IDLE_CFG			(PMU_AP_BASE + 0x160)
+#define PMU_AP_CORE3_IDLE_CFG			(PMU_AP_BASE + 0x164)
+#define PMU_AP_CORE4_IDLE_CFG			(PMU_AP_BASE + 0x304)
+#define PMU_AP_CORE5_IDLE_CFG			(PMU_AP_BASE + 0x308)
+#define PMU_AP_CORE6_IDLE_CFG			(PMU_AP_BASE + 0x30c)
+#define PMU_AP_CORE7_IDLE_CFG			(PMU_AP_BASE + 0x310)
+
+/* boot entry for X100 clusters (C0, C1) */
+#define C0_RVBADDR_LO_ADDR			0xd4282db0
+#define C0_RVBADDR_HI_ADDR			0xd4282db4
+#define C1_RVBADDR_LO_ADDR			0xd4282eb0
+#define C1_RVBADDR_HI_ADDR			0xd4282eb4
+
+/* CCI-550 base and slave interface layout */
+#define CCI_550_PLATFORM_CCI_ADDR		0xd8500000
+#define CCI_550_STATUS				0x000c
+#define CCI_550_STATUS_CHANGE_PENDING		BIT(0)
+#define CCI_550_SLAVE_IFACE0_OFFSET		0x1000
+#define CCI_550_SLAVE_IFACE_OFFSET(idx)		\
+		(CCI_550_SLAVE_IFACE0_OFFSET + ((0x1000) * (idx)))
+#define CCI_550_SNOOP_CTRL			0x0000
+#define CCI_550_SNOOP_CTRL_ENABLE_SNOOPS	BIT(0)
+#define CCI_550_SNOOP_CTRL_ENABLE_DVMS		BIT(1)
+
+/*
+ * PMU AP per-core idle control register bits (PMU_AP_COREn_IDLE_CFG).
+ * Bit definitions are identical in K1 and K3 User Manuals.
+ * These replace the original ad-hoc names from k1.h (which incorrectly
+ * called bit 1 SRAM_PWRDWN, bit 3 WAKE_MCE, and bit 4 MC_SW_REQ).
+ */
+/* bit 0: CORE_IDLE - gate core clock externally when core enters WFI */
+#define PMU_AP_IDLE_CORE_IDLE			BIT(0)
+/* bit 1: CORE_PWRDWN - power off core on WFI (requires CORE_IDLE set) */
+#define PMU_AP_IDLE_CORE_PWRDWN			BIT(1)
+/* bit 2: Core L1 SRAM Power Down - reserved/not used in K1 and K3 */
+#define PMU_AP_IDLE_CORE_L1_SRAM_PWRDWN		BIT(2)
+/* bit 3: MASK_GIC_NIRQ_TO_CORE - mask nIRQ from GIC, auto-cleared by HW on power-down entry */
+#define PMU_AP_IDLE_MASK_GIC_NIRQ		BIT(3)
+/* bit 4: MASK_GIC_NFIQ_TO_CORE - mask nFIQ from GIC, auto-cleared by HW on power-down entry */
+#define PMU_AP_IDLE_MASK_GIC_NFIQ		BIT(4)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER		4
+
+#endif /* __RISCV_SPACEMIT_COMMON_H__ */
diff --git a/platform/generic/include/spacemit/k1.h b/platform/generic/include/spacemit/k1.h
index ac727b04..662b42e5 100644
--- a/platform/generic/include/spacemit/k1.h
+++ b/platform/generic/include/spacemit/k1.h
@@ -1,88 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2025 SpacemiT
+ * Authors:
+ *   Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
+ *   Troy Mitchell <troy.mitchell@linux.spacemit.com>
+ */
+
 #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
+#include <spacemit/common.h>
 
-/* 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)
+#define CSR_MRAOP				0x7c2
 
-/* cache flush */
 #define MRAOP_CACHE_FLUSH			GENMASK(1, 0)
 
-#define PMU_AP_BASE				0xd4282800
-
-#define PMU_AP_CORE0_WAKEUP			(PMU_AP_BASE + 0x12c)
-#define PMU_AP_CORE1_WAKEUP			(PMU_AP_BASE + 0x130)
-#define PMU_AP_CORE2_WAKEUP			(PMU_AP_BASE + 0x134)
-#define PMU_AP_CORE3_WAKEUP			(PMU_AP_BASE + 0x138)
-#define PMU_AP_CORE4_WAKEUP			(PMU_AP_BASE + 0x324)
-#define PMU_AP_CORE5_WAKEUP			(PMU_AP_BASE + 0x328)
-#define PMU_AP_CORE6_WAKEUP			(PMU_AP_BASE + 0x32c)
-#define PMU_AP_CORE7_WAKEUP			(PMU_AP_BASE + 0x330)
-
-#define PMU_AP_CORE0_IDLE_CFG			(PMU_AP_BASE + 0x124)
-#define PMU_AP_CORE1_IDLE_CFG			(PMU_AP_BASE + 0x128)
-#define PMU_AP_CORE2_IDLE_CFG			(PMU_AP_BASE + 0x160)
-#define PMU_AP_CORE3_IDLE_CFG			(PMU_AP_BASE + 0x164)
-#define PMU_AP_CORE4_IDLE_CFG			(PMU_AP_BASE + 0x304)
-#define PMU_AP_CORE5_IDLE_CFG			(PMU_AP_BASE + 0x308)
-#define PMU_AP_CORE6_IDLE_CFG			(PMU_AP_BASE + 0x30c)
-#define PMU_AP_CORE7_IDLE_CFG			(PMU_AP_BASE + 0x310)
-
-/* 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			0xd4282eb4
-
-#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)
+#define PMU_AP_IDLE_PWRDOWN_K1_MASK		(PMU_AP_IDLE_CORE_IDLE |	\
+						 PMU_AP_IDLE_CORE_PWRDWN |	\
+						 PMU_AP_IDLE_MASK_GIC_NIRQ |	\
+						 PMU_AP_IDLE_MASK_GIC_NFIQ)
 
-/* 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
+#define PLAT_CCI_K1_CLUSTER0_IFACE_IX		0
+#define PLAT_CCI_K1_CLUSTER1_IFACE_IX		1
 
-#endif
+#endif /* __RISCV_SPACEMIT_K1_H__ */
diff --git a/platform/generic/include/spacemit/spacemit.h b/platform/generic/include/spacemit/spacemit.h
new file mode 100644
index 00000000..671cfd05
--- /dev/null
+++ b/platform/generic/include/spacemit/spacemit.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2025 SpacemiT
+ * Authors:
+ *   Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
+ *   Troy Mitchell <troy.mitchell@linux.spacemit.com>
+ */
+
+#ifndef __RISCV_SPACEMIT_H__
+#define __RISCV_SPACEMIT_H__
+
+void cci_enable_snoop_dvm_reqs(const int *cci_map, unsigned int master_id);
+
+#endif
diff --git a/platform/generic/spacemit/k1.c b/platform/generic/spacemit/k1.c
index 19a9b27c..323239e0 100644
--- a/platform/generic/spacemit/k1.c
+++ b/platform/generic/spacemit/k1.c
@@ -12,37 +12,16 @@
 #include <sbi/riscv_io.h>
 #include <sbi/sbi_hsm.h>
 #include <spacemit/k1.h>
+#include <spacemit/spacemit.h>
+
+#define PLATFORM_MAX_CPUS			8
 
 /* only use 0-1 cluster in SpacemiT K1 */
 static const int cci_map[] = {
-	PLAT_CCI_CLUSTER0_IFACE_IX,
-	PLAT_CCI_CLUSTER1_IFACE_IX,
+	PLAT_CCI_K1_CLUSTER0_IFACE_IX,
+	PLAT_CCI_K1_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;
@@ -62,7 +41,7 @@ static void spacemit_k1_pre_init(void)
 
 		if (!(cluster_enabled & (1 << clusterid))) {
 			cluster_enabled |= 1 << clusterid;
-			cci_enable_snoop_dvm_reqs(clusterid);
+			cci_enable_snoop_dvm_reqs(cci_map, clusterid);
 		}
 	}
 }
diff --git a/platform/generic/spacemit/objects.mk b/platform/generic/spacemit/objects.mk
index dcb37867..8309ad1f 100644
--- a/platform/generic/spacemit/objects.mk
+++ b/platform/generic/spacemit/objects.mk
@@ -2,5 +2,6 @@
 # SPDX-License-Identifier: BSD-2-Clause
 #
 
+platform-objs-$(CONFIG_PLATFORM_SPACEMIT) += spacemit/spacemit.o
 carray-platform_override_modules-$(CONFIG_PLATFORM_SPACEMIT_K1) += spacemit_k1
 platform-objs-$(CONFIG_PLATFORM_SPACEMIT_K1) += spacemit/k1.o
diff --git a/platform/generic/spacemit/spacemit.c b/platform/generic/spacemit/spacemit.c
new file mode 100644
index 00000000..a215c1ad
--- /dev/null
+++ b/platform/generic/spacemit/spacemit.c
@@ -0,0 +1,36 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 SpacemiT
+ * Authors:
+ *   Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
+ *   Troy Mitchell <troy.mitchell@linux.spacemit.com>
+ */
+
+#include <platform_override.h>
+#include <sbi/riscv_io.h>
+#include <spacemit/common.h>
+
+void cci_enable_snoop_dvm_reqs(const int *cci_map, 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 *)(unsigned long)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 *)(unsigned long)CCI_550_PLATFORM_CCI_ADDR + CCI_550_STATUS) &
+	       CCI_550_STATUS_CHANGE_PENDING)
+		;
+}

-- 
2.55.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v3 5/5] platform: generic: spacemit: k3: add platform support
  2026-08-27  9:19 [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Troy Mitchell
                   ` (3 preceding siblings ...)
  2026-08-27  9:19 ` [PATCH v3 4/5] platform: generic: spacemit: k1: refactor platform support Troy Mitchell
@ 2026-08-27  9:19 ` Troy Mitchell
       [not found] ` <20260831200832.404000-1-valentin.haudiquet@canonical.com>
  5 siblings, 0 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-08-27  9:19 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Troy Mitchell

From: Xianbin Zhu <xianbin.zhu@linux.spacemit.com>

SpacemiT K3 has 16 harts split across four clusters, with eight X100
harts in C0/C1 and eight A100 harts in C2/C3. Only hart 0 is powered at
reset, so secondary harts cannot reach the OpenSBI warm-boot path until
the platform removes their PMU power-down votes and wakes them.

Add a start-only HSM backend which performs those operations for the
requested hart. This lets the common HSM state machine start secondary
harts on demand instead of waking every hart during cold boot. ESOS can
remain loaded for the other RPMI services described by the platform DT.
Select the HSM backend from the root compatible, preserving K1's
existing start and stop behavior.

The Boot ROM maps the audio buffer region as I/O although later firmware
uses it as normal memory. Restore its cacheable PMA attribute and mark
the XIP region as I/O before enabling caches. The boot hart performs the
per-hart setup during early platform discovery, while secondary harts do
the same in their assembly entry before reaching common warm-boot code.
This also enables MISA.H on X100 before common code selects its trap
entry; A100 does not implement H. Fence the PMA and guest translation
changes before continuing.

Use assembler-safe constants shared by the C and warm-entry assembly
paths. Since K1 and K3 are RV64-only, omit the SpacemiT platform objects
from RV32 generic builds.

Program the four cluster warm-boot vectors once and enable CCI-550 snoop
and DVM requests before any secondary hart is started.

Signed-off-by: Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
Co-developed-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
 lib/utils/hsm/fdt_hsm_spacemit.c           | 113 +++++++++++++++++++------
 platform/generic/Kconfig                   |   7 ++
 platform/generic/configs/defconfig         |   1 +
 platform/generic/include/spacemit/common.h |  18 ++--
 platform/generic/include/spacemit/k3.h     | 127 +++++++++++++++++++++++++++++
 platform/generic/include/spacemit/k3_asm.h |  16 ++++
 platform/generic/spacemit/k3.c             | 122 +++++++++++++++++++++++++++
 platform/generic/spacemit/k3_asm.S         |  52 ++++++++++++
 platform/generic/spacemit/objects.mk       |   4 +
 9 files changed, 430 insertions(+), 30 deletions(-)

diff --git a/lib/utils/hsm/fdt_hsm_spacemit.c b/lib/utils/hsm/fdt_hsm_spacemit.c
index 6348f6a3..4f76b99e 100644
--- a/lib/utils/hsm/fdt_hsm_spacemit.c
+++ b/lib/utils/hsm/fdt_hsm_spacemit.c
@@ -9,11 +9,13 @@
 
 #include <platform_override.h>
 #include <sbi/riscv_io.h>
+#include <sbi/sbi_error.h>
 #include <sbi/sbi_hsm.h>
 #include <spacemit/common.h>
 #include <spacemit/k1.h>
+#include <spacemit/k3.h>
 
-static const u64 cpu_wakeup_reg[] = {
+static const u64 k1_cpu_wakeup_reg[] = {
 	PMU_AP_CORE0_WAKEUP,
 	PMU_AP_CORE1_WAKEUP,
 	PMU_AP_CORE2_WAKEUP,
@@ -24,7 +26,7 @@ static const u64 cpu_wakeup_reg[] = {
 	PMU_AP_CORE7_WAKEUP,
 };
 
-static const u64 cpu_idle_reg[] = {
+static const u64 k1_cpu_idle_reg[] = {
 	PMU_AP_CORE0_IDLE_CFG,
 	PMU_AP_CORE1_IDLE_CFG,
 	PMU_AP_CORE2_IDLE_CFG,
@@ -35,10 +37,11 @@ static const u64 cpu_idle_reg[] = {
 	PMU_AP_CORE7_IDLE_CFG,
 };
 
-static inline void spacemit_set_cpu_power(u32 hartid, bool enable)
+static inline void spacemit_k1_set_cpu_power(u32 hartid, bool enable)
 {
 	unsigned int value;
-	unsigned int *cpu_idle_base = (unsigned int *)(unsigned long)cpu_idle_reg[hartid];
+	unsigned int *cpu_idle_base =
+		(unsigned int *)(unsigned long)k1_cpu_idle_reg[hartid];
 
 	value = readl(cpu_idle_base);
 
@@ -50,31 +53,32 @@ static inline void spacemit_set_cpu_power(u32 hartid, bool enable)
 	writel(value, cpu_idle_base);
 }
 
-static void spacemit_wakeup_cpu(u32 mpidr)
+static void spacemit_k1_wakeup_cpu(u32 mpidr)
 {
 	unsigned int *cpu_reset_base;
 	unsigned int cur_hartid = current_hartid();
 
-	cpu_reset_base = (unsigned int *)(unsigned long)cpu_wakeup_reg[cur_hartid];
+	cpu_reset_base =
+		(unsigned int *)(unsigned long)k1_cpu_wakeup_reg[cur_hartid];
 
 	writel(1 << mpidr, cpu_reset_base);
 }
 
-static void spacemit_assert_cpu(void)
+static void spacemit_k1_assert_cpu(void)
 {
-	spacemit_set_cpu_power(current_hartid(), false);
+	spacemit_k1_set_cpu_power(current_hartid(), false);
 }
 
-static void spacemit_deassert_cpu(unsigned int hartid)
+static void spacemit_k1_deassert_cpu(unsigned int hartid)
 {
-	spacemit_set_cpu_power(hartid, true);
+	spacemit_k1_set_cpu_power(hartid, true);
 }
 
 /* Start (or power-up) the given hart */
-static int spacemit_hart_start(unsigned int hartid, unsigned long saddr)
+static int spacemit_k1_hart_start(unsigned int hartid, unsigned long saddr)
 {
-	spacemit_deassert_cpu(hartid);
-	spacemit_wakeup_cpu(hartid);
+	spacemit_k1_deassert_cpu(hartid);
+	spacemit_k1_wakeup_cpu(hartid);
 
 	return 0;
 }
@@ -83,10 +87,11 @@ static int spacemit_hart_start(unsigned int hartid, unsigned long saddr)
  * Stop (or power-down) the current hart from running. This call
  * doesn't expect to return if success.
  */
-static int spacemit_hart_stop(void)
+static int spacemit_k1_hart_stop(void)
 {
 	csr_write(CSR_STIMECMP, GENMASK_ULL(63, 0));
-	csr_clear(CSR_MIE, MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP | MIP_SEIP | MIP_MEIP);
+	csr_clear(CSR_MIE, MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP |
+		  MIP_SEIP | MIP_MEIP);
 
 	/* disable data prefetch */
 	csr_clear(CSR_MSETUP, MSETUP_PFE);
@@ -106,31 +111,93 @@ static int spacemit_hart_stop(void)
 	 * Therefore, use modulo with PLATFORM_MAX_CPUS_PER_CLUSTER
 	 * to select the proper bit.
 	 */
-	csr_clear(CSR_ML2SETUP, 1 << (current_hartid() % PLATFORM_MAX_CPUS_PER_CLUSTER));
+	csr_clear(CSR_ML2SETUP,
+		  1 << (current_hartid() % PLATFORM_MAX_CPUS_PER_CLUSTER));
 	asm volatile ("fence iorw, iorw");
 
-	spacemit_assert_cpu();
+	spacemit_k1_assert_cpu();
 
 	wfi();
 
 	return SBI_ENOTSUPP;
 }
 
-static const struct sbi_hsm_device spacemit_hsm_ops = {
+static const struct sbi_hsm_device spacemit_k1_hsm_ops = {
 	.name		= "spacemit-hsm",
-	.hart_start	= spacemit_hart_start,
-	.hart_stop	= spacemit_hart_stop,
+	.hart_start	= spacemit_k1_hart_start,
+	.hart_stop	= spacemit_k1_hart_stop,
 };
 
-static int spacemit_hsm_probe(const void *fdt, int nodeoff, const struct fdt_match *match)
+static const unsigned long k3_cluster_idle_reg[] = {
+	PMU_CX_CAPMP_IDLE_CFG0,  PMU_CX_CAPMP_IDLE_CFG1,
+	PMU_CX_CAPMP_IDLE_CFG2,  PMU_CX_CAPMP_IDLE_CFG3,
+	PMU_CX_CAPMP_IDLE_CFG4,  PMU_CX_CAPMP_IDLE_CFG5,
+	PMU_CX_CAPMP_IDLE_CFG6,  PMU_CX_CAPMP_IDLE_CFG7,
+	PMU_CX_CAPMP_IDLE_CFG8,  PMU_CX_CAPMP_IDLE_CFG9,
+	PMU_CX_CAPMP_IDLE_CFG10, PMU_CX_CAPMP_IDLE_CFG11,
+	PMU_CX_CAPMP_IDLE_CFG12, PMU_CX_CAPMP_IDLE_CFG13,
+	PMU_CX_CAPMP_IDLE_CFG14, PMU_CX_CAPMP_IDLE_CFG15,
+};
+
+static const unsigned long k3_core_idle_reg[] = {
+	PMU_AP_CORE0_IDLE_CFG,   PMU_AP_CORE1_IDLE_CFG,
+	PMU_AP_CORE2_IDLE_CFG,   PMU_AP_CORE3_IDLE_CFG,
+	PMU_AP_CORE4_IDLE_CFG,   PMU_AP_CORE5_IDLE_CFG,
+	PMU_AP_CORE6_IDLE_CFG,   PMU_AP_CORE7_IDLE_CFG,
+	PMU_CAP_CORE8_IDLE_CFG,  PMU_CAP_CORE9_IDLE_CFG,
+	PMU_CAP_CORE10_IDLE_CFG, PMU_CAP_CORE11_IDLE_CFG,
+	PMU_CAP_CORE12_IDLE_CFG, PMU_CAP_CORE13_IDLE_CFG,
+	PMU_CAP_CORE14_IDLE_CFG, PMU_CAP_CORE15_IDLE_CFG,
+};
+
+static const unsigned long k3_core_wakeup_reg[] = {
+	PMU_AP_CORE0_WAKEUP,     PMU_AP_CORE1_WAKEUP,
+	PMU_AP_CORE2_WAKEUP,     PMU_AP_CORE3_WAKEUP,
+	PMU_AP_CORE4_WAKEUP,     PMU_AP_CORE5_WAKEUP,
+	PMU_AP_CORE6_WAKEUP,     PMU_AP_CORE7_WAKEUP,
+	PMU_CAP_CORE8_WAKEUP,    PMU_CAP_CORE9_WAKEUP,
+	PMU_CAP_CORE10_WAKEUP,   PMU_CAP_CORE11_WAKEUP,
+	PMU_CAP_CORE12_WAKEUP,   PMU_CAP_CORE13_WAKEUP,
+	PMU_CAP_CORE14_WAKEUP,   PMU_CAP_CORE15_WAKEUP,
+};
+
+static int spacemit_k3_hart_start(u32 hartid, ulong saddr)
+{
+	u32 value;
+
+	if (hartid >= array_size(k3_core_wakeup_reg))
+		return SBI_EINVAL;
+
+	value = readl((void *)k3_cluster_idle_reg[hartid]);
+	value &= ~CLUSTER_PWR_DOWN_VALUE;
+	writel(value, (void *)k3_cluster_idle_reg[hartid]);
+
+	value = readl((void *)k3_core_idle_reg[hartid]);
+	value &= ~PMU_AP_IDLE_PWRDOWN_K3_MASK;
+	writel(value, (void *)k3_core_idle_reg[hartid]);
+
+	writel(BIT(hartid), (void *)k3_core_wakeup_reg[hartid]);
+
+	return 0;
+}
+
+/* K3 uses this only to power on a hart which has not entered OpenSBI yet. */
+static const struct sbi_hsm_device spacemit_k3_hsm_ops = {
+	.name		= "spacemit-k3-hsm",
+	.hart_start	= spacemit_k3_hart_start,
+};
+
+static int spacemit_hsm_probe(const void *fdt, int nodeoff,
+			      const struct fdt_match *match)
 {
-	sbi_hsm_set_device(&spacemit_hsm_ops);
+	sbi_hsm_set_device(match->data);
 
 	return 0;
 }
 
 static const struct fdt_match spacemit_hsm_match[] = {
-	{ .compatible = "spacemit,k1" },
+	{ .compatible = "spacemit,k1", .data = &spacemit_k1_hsm_ops },
+	{ .compatible = "spacemit,k3", .data = &spacemit_k3_hsm_ops },
 	{ },
 };
 
diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig
index 958610d3..a00b4d13 100644
--- a/platform/generic/Kconfig
+++ b/platform/generic/Kconfig
@@ -109,6 +109,13 @@ config PLATFORM_SPACEMIT_K1
 	select PLATFORM_SPACEMIT
 	default n
 
+config PLATFORM_SPACEMIT_K3
+	bool "Spacemit K3 support"
+	select FDT_HSM
+	select FDT_HSM_SPACEMIT
+	select PLATFORM_SPACEMIT
+	default n
+
 config CPU_MIPS_P8700
 	bool
 	default n
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 341f6b25..58d40898 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -15,6 +15,7 @@ CONFIG_PLATFORM_THEAD=y
 CONFIG_PLATFORM_MIPS_P8700_EYEQ7H=y
 CONFIG_PLATFORM_MIPS_P8700_BOSTON=y
 CONFIG_PLATFORM_SPACEMIT_K1=y
+CONFIG_PLATFORM_SPACEMIT_K3=y
 CONFIG_FDT_CACHE=y
 CONFIG_FDT_CACHE_ANDES_LLCACHE=y
 CONFIG_FDT_CACHE_SIFIVE_CCACHE=y
diff --git a/platform/generic/include/spacemit/common.h b/platform/generic/include/spacemit/common.h
index 317bb3e9..7a75ff3f 100644
--- a/platform/generic/include/spacemit/common.h
+++ b/platform/generic/include/spacemit/common.h
@@ -9,23 +9,27 @@
 #ifndef __RISCV_SPACEMIT_COMMON_H__
 #define __RISCV_SPACEMIT_COMMON_H__
 
+#include <sbi/sbi_const.h>
+
+#ifndef __ASSEMBLY__
 #include <sbi/sbi_bitops.h>
+#endif
 
 #define CSR_MSETUP				0x7c0
 #define CSR_ML2SETUP				0x7f0
 
 /* dcache enable */
-#define MSETUP_DE				BIT(0)
+#define MSETUP_DE				_BITUL(0)
 /* icache enable */
-#define MSETUP_IE				BIT(1)
+#define MSETUP_IE				_BITUL(1)
 /* branch prediction enable */
-#define MSETUP_BPE				BIT(4)
+#define MSETUP_BPE				_BITUL(4)
 /* prefetch functionality enable */
-#define MSETUP_PFE				BIT(5)
+#define MSETUP_PFE				_BITUL(5)
 /* misaligned memory access enable */
-#define MSETUP_MME				BIT(6)
+#define MSETUP_MME				_BITUL(6)
 /* ECC enable */
-#define MSETUP_ECCE				BIT(16)
+#define MSETUP_ECCE				_BITUL(16)
 
 #define PMU_AP_BASE				0xd4282800
 
@@ -74,7 +78,7 @@
 #define PMU_AP_IDLE_CORE_IDLE			BIT(0)
 /* bit 1: CORE_PWRDWN - power off core on WFI (requires CORE_IDLE set) */
 #define PMU_AP_IDLE_CORE_PWRDWN			BIT(1)
-/* bit 2: Core L1 SRAM Power Down - reserved/not used in K1 and K3 */
+/* bit 2: Core L1 SRAM Power Down - reserved in K1, used in K3 */
 #define PMU_AP_IDLE_CORE_L1_SRAM_PWRDWN		BIT(2)
 /* bit 3: MASK_GIC_NIRQ_TO_CORE - mask nIRQ from GIC, auto-cleared by HW on power-down entry */
 #define PMU_AP_IDLE_MASK_GIC_NIRQ		BIT(3)
diff --git a/platform/generic/include/spacemit/k3.h b/platform/generic/include/spacemit/k3.h
new file mode 100644
index 00000000..f444d064
--- /dev/null
+++ b/platform/generic/include/spacemit/k3.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2026 SpacemiT
+ * Authors:
+ *   Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
+ *   Troy Mitchell <troy.mitchell@linux.spacemit.com>
+ */
+
+#ifndef __RISCV_SPACEMIT_K3_H__
+#define __RISCV_SPACEMIT_K3_H__
+
+#include <spacemit/common.h>
+
+/* PMA configuration CSR */
+#define CSR_PMACFG0				0x7de
+
+/*
+ * PMACFG0 audio buffer region field: bits [55:48].
+ * The Boot ROM maps this region as I/O. Restore it to a cacheable
+ * attribute so later firmware can use it for data or instructions.
+ */
+#define PMACFG0_AUDIO_BUF_FIELD_MASK		_UL(0xff)
+#define PMACFG0_AUDIO_BUF_FIELD_SHIFT		48
+#define PMACFG0_AUDIO_BUF_ATTR_CACHEABLE	_UL(0x20)
+
+/*
+ * PMACFG0 XIP region field: bits [23:16].
+ * Lower 12 bits are zero so GAS emits a single lui instruction.
+ */
+#define PMACFG0_XIP_FIELD_CLEAR			_UL(0x00ff0000)
+#define PMACFG0_XIP_ATTR_IO			_UL(0x00220000)
+
+#define CSR_ML2HINT				0x7f7
+#define MISA_EXT_H				_BITUL(7)
+
+/* Enable instruction prefetch in L2 cache on miss */
+#define ML2SETUP_IPRF				_BITUL(16)
+/* Enable TLB prefetch in L2 cache */
+#define ML2SETUP_TPRF				_BITUL(18)
+/* Enable top-of-clk of trace */
+#define ML2HINT_TRACE_TOP_ICGEN			_BITUL(26)
+
+#define MSETUP_BOOT_FLAGS			(MSETUP_DE | MSETUP_IE | \
+						 MSETUP_BPE | MSETUP_PFE | \
+						 MSETUP_MME | MSETUP_ECCE)
+
+/* A100 cores: hart 8-11 belong to C2 cluster, hart 12-15 to C3 cluster */
+#define PMU_CAP_CORE8_WAKEUP			(PMU_AP_BASE + 0x360)
+#define PMU_CAP_CORE9_WAKEUP			(PMU_AP_BASE + 0x364)
+#define PMU_CAP_CORE10_WAKEUP			(PMU_AP_BASE + 0x368)
+#define PMU_CAP_CORE11_WAKEUP			(PMU_AP_BASE + 0x36c)
+#define PMU_CAP_CORE12_WAKEUP			(PMU_AP_BASE + 0x22c)
+#define PMU_CAP_CORE13_WAKEUP			(PMU_AP_BASE + 0x230)
+#define PMU_CAP_CORE14_WAKEUP			(PMU_AP_BASE + 0x234)
+#define PMU_CAP_CORE15_WAKEUP			(PMU_AP_BASE + 0x238)
+
+/* A100 per-core idle config registers (harts 8-15) */
+#define PMU_CAP_CORE8_IDLE_CFG			(PMU_AP_BASE + 0x340)
+#define PMU_CAP_CORE9_IDLE_CFG			(PMU_AP_BASE + 0x344)
+#define PMU_CAP_CORE10_IDLE_CFG			(PMU_AP_BASE + 0x348)
+#define PMU_CAP_CORE11_IDLE_CFG			(PMU_AP_BASE + 0x34c)
+#define PMU_CAP_CORE12_IDLE_CFG			(PMU_AP_BASE + 0x20c)
+#define PMU_CAP_CORE13_IDLE_CFG			(PMU_AP_BASE + 0x210)
+#define PMU_CAP_CORE14_IDLE_CFG			(PMU_AP_BASE + 0x214)
+#define PMU_CAP_CORE15_IDLE_CFG			(PMU_AP_BASE + 0x218)
+
+/* CX CAPMP cluster idle config registers */
+#define PMU_CX_CAPMP_IDLE_CFG0		(PMU_AP_BASE + 0x120)
+#define PMU_CX_CAPMP_IDLE_CFG1		(PMU_AP_BASE + 0x0e4)
+#define PMU_CX_CAPMP_IDLE_CFG2		(PMU_AP_BASE + 0x150)
+#define PMU_CX_CAPMP_IDLE_CFG3		(PMU_AP_BASE + 0x154)
+#define PMU_CX_CAPMP_IDLE_CFG4		(PMU_AP_BASE + 0x314)
+#define PMU_CX_CAPMP_IDLE_CFG5		(PMU_AP_BASE + 0x318)
+#define PMU_CX_CAPMP_IDLE_CFG6		(PMU_AP_BASE + 0x31c)
+#define PMU_CX_CAPMP_IDLE_CFG7		(PMU_AP_BASE + 0x320)
+#define PMU_CX_CAPMP_IDLE_CFG8		(PMU_AP_BASE + 0x350)
+#define PMU_CX_CAPMP_IDLE_CFG9		(PMU_AP_BASE + 0x354)
+#define PMU_CX_CAPMP_IDLE_CFG10		(PMU_AP_BASE + 0x358)
+#define PMU_CX_CAPMP_IDLE_CFG11		(PMU_AP_BASE + 0x35c)
+#define PMU_CX_CAPMP_IDLE_CFG12		(PMU_AP_BASE + 0x21c)
+#define PMU_CX_CAPMP_IDLE_CFG13		(PMU_AP_BASE + 0x220)
+#define PMU_CX_CAPMP_IDLE_CFG14		(PMU_AP_BASE + 0x224)
+#define PMU_CX_CAPMP_IDLE_CFG15		(PMU_AP_BASE + 0x228)
+
+#define PMU_AP_IDLE_PWRDOWN_K3_MASK		(PMU_AP_IDLE_CORE_IDLE |		\
+						 PMU_AP_IDLE_CORE_PWRDWN |		\
+						 PMU_AP_IDLE_CORE_L1_SRAM_PWRDWN |	\
+						 PMU_AP_IDLE_MASK_GIC_NIRQ |		\
+						 PMU_AP_IDLE_MASK_GIC_NFIQ)
+
+/*
+ * PMU CX per-cluster idle control bits (PMU_CX_CAPMPn_IDLE_CFG).
+ */
+/* bit 0: MP Idle - gate cluster clocks externally on WFI */
+#define PMU_CX_IDLE_MP_IDLE			BIT(0)
+/* bit 1: MP Power Down - power off cluster logic when idle */
+#define PMU_CX_IDLE_MP_PWRDWN			BIT(1)
+/* bit 2: L2 Cache SRAM Power Down */
+#define PMU_CX_IDLE_L2_SRAM_PWRDWN		BIT(2)
+/* bit 3: SCU SRAM Power Down - not used, SCU SRAM does not support retention */
+#define PMU_CX_IDLE_MP_SCU_SRAM_PWRDWN		BIT(3)
+/* bit 7: ACNACTM Hardware Control - HW controls ACNACTM port on MP low power entry */
+#define PMU_CX_IDLE_ACNACTM_HW_CTRL		BIT(7)
+
+#define CLUSTER_PWR_DOWN_VALUE			(PMU_CX_IDLE_MP_IDLE |		\
+						 PMU_CX_IDLE_MP_PWRDWN |	\
+						 PMU_CX_IDLE_L2_SRAM_PWRDWN |	\
+						 PMU_CX_IDLE_MP_SCU_SRAM_PWRDWN | \
+						 PMU_CX_IDLE_ACNACTM_HW_CTRL)
+
+/* boot entry for A100 clusters */
+#define C2_RVBADDR_LO_ADDR			(0xd4282c00 + 0x3e8)
+#define C2_RVBADDR_HI_ADDR			(0xd4282c00 + 0x3ec)
+#define C3_RVBADDR_LO_ADDR			(0xd4282c00 + 0x260)
+#define C3_RVBADDR_HI_ADDR			(0xd4282c00 + 0x264)
+
+#define PLATFORM_A100_FIRST_ID			8
+
+#define PLAT_CCI_K3_AIDMA_IFACE_IX		0
+#define PLAT_CCI_K3_CLUSTER0_IFACE_IX		1
+#define PLAT_CCI_K3_CLUSTER1_IFACE_IX		2
+#define PLAT_CCI_K3_CLUSTER2_0_IFACE_IX	3
+#define PLAT_CCI_K3_CLUSTER2_1_IFACE_IX	4
+#define PLAT_CCI_K3_CLUSTER3_0_IFACE_IX	5
+#define PLAT_CCI_K3_CLUSTER3_1_IFACE_IX	6
+
+#endif /* __RISCV_SPACEMIT_K3_H__ */
diff --git a/platform/generic/include/spacemit/k3_asm.h b/platform/generic/include/spacemit/k3_asm.h
new file mode 100644
index 00000000..70c00478
--- /dev/null
+++ b/platform/generic/include/spacemit/k3_asm.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2026 SpacemiT
+ * Authors:
+ *   Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
+ *   Troy Mitchell <troy.mitchell@linux.spacemit.com>
+ */
+
+#ifndef __RISCV_SPACEMIT_K3_ASM_H__
+#define __RISCV_SPACEMIT_K3_ASM_H__
+
+#ifndef __ASSEMBLY__
+void _spacemit_k3_warm_start(void);
+#endif
+
+#endif /* __RISCV_SPACEMIT_K3_ASM_H__ */
diff --git a/platform/generic/spacemit/k3.c b/platform/generic/spacemit/k3.c
new file mode 100644
index 00000000..967d09bf
--- /dev/null
+++ b/platform/generic/spacemit/k3.c
@@ -0,0 +1,122 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 SpacemiT
+ * Authors:
+ *   Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
+ *   Troy Mitchell <troy.mitchell@linux.spacemit.com>
+ */
+
+#include <platform_override.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_hfence.h>
+#include <sbi/sbi_tlb.h>
+#include <spacemit/k3.h>
+#include <spacemit/k3_asm.h>
+#include <spacemit/spacemit.h>
+
+static const int cci_map[] = {
+	PLAT_CCI_K3_AIDMA_IFACE_IX,
+	PLAT_CCI_K3_CLUSTER0_IFACE_IX,
+	PLAT_CCI_K3_CLUSTER1_IFACE_IX,
+	PLAT_CCI_K3_CLUSTER2_0_IFACE_IX,
+	PLAT_CCI_K3_CLUSTER2_1_IFACE_IX,
+	PLAT_CCI_K3_CLUSTER3_0_IFACE_IX,
+	PLAT_CCI_K3_CLUSTER3_1_IFACE_IX,
+};
+
+/*
+ * The boot hart reaches this function before caches are enabled. Secondary
+ * harts perform the same setup in _spacemit_k3_warm_start before entering
+ * the common warm-boot path.
+ */
+static void spacemit_k3_hart_init(u32 hartid)
+{
+	csr_clear(CSR_PMACFG0,
+		  PMACFG0_AUDIO_BUF_FIELD_MASK <<
+		  PMACFG0_AUDIO_BUF_FIELD_SHIFT);
+	csr_set(CSR_PMACFG0,
+		PMACFG0_AUDIO_BUF_ATTR_CACHEABLE <<
+		PMACFG0_AUDIO_BUF_FIELD_SHIFT);
+	csr_clear(CSR_PMACFG0, PMACFG0_XIP_FIELD_CLEAR);
+	csr_set(CSR_PMACFG0, PMACFG0_XIP_ATTR_IO);
+	__sbi_sfence_vma_all();
+
+	csr_set(CSR_ML2SETUP,
+		_BITUL(hartid % PLATFORM_MAX_CPUS_PER_CLUSTER) |
+		ML2SETUP_IPRF | ML2SETUP_TPRF);
+	csr_set(CSR_ML2HINT, ML2HINT_TRACE_TOP_ICGEN);
+	csr_set(CSR_MSETUP, MSETUP_BOOT_FLAGS);
+
+	if (hartid < PLATFORM_A100_FIRST_ID) {
+		/* MISA.H is writable on X100 and not implemented on A100. */
+		csr_set(CSR_MISA, MISA_EXT_H);
+		__sbi_hfence_gvma_all();
+	}
+}
+
+/* The boot hart is already running, so it is never started by the HSM. */
+static void spacemit_k3_keep_boot_hart_powered(void)
+{
+	u32 value;
+
+	value = readl((void *)(unsigned long)PMU_CX_CAPMP_IDLE_CFG0);
+	value &= ~CLUSTER_PWR_DOWN_VALUE;
+	writel(value, (void *)(unsigned long)PMU_CX_CAPMP_IDLE_CFG0);
+
+	value = readl((void *)(unsigned long)PMU_AP_CORE0_IDLE_CFG);
+	value &= ~PMU_AP_IDLE_PWRDOWN_K3_MASK;
+	writel(value, (void *)(unsigned long)PMU_AP_CORE0_IDLE_CFG);
+}
+
+/* Program global state before the HSM starts any secondary hart. */
+static void spacemit_k3_pre_init(void)
+{
+	unsigned long entry = (unsigned long)&_spacemit_k3_warm_start;
+	int i;
+
+	writel((u32)entry, (void *)(unsigned long)C0_RVBADDR_LO_ADDR);
+	writel((u32)(entry >> 32), (void *)(unsigned long)C0_RVBADDR_HI_ADDR);
+
+	writel((u32)entry, (void *)(unsigned long)C1_RVBADDR_LO_ADDR);
+	writel((u32)(entry >> 32), (void *)(unsigned long)C1_RVBADDR_HI_ADDR);
+
+	writel((u32)entry, (void *)(unsigned long)C2_RVBADDR_LO_ADDR);
+	writel((u32)(entry >> 32), (void *)(unsigned long)C2_RVBADDR_HI_ADDR);
+
+	writel((u32)entry, (void *)(unsigned long)C3_RVBADDR_LO_ADDR);
+	writel((u32)(entry >> 32), (void *)(unsigned long)C3_RVBADDR_HI_ADDR);
+
+	for (i = 0; i < array_size(cci_map); i++)
+		cci_enable_snoop_dvm_reqs(cci_map, i);
+
+	spacemit_k3_keep_boot_hart_powered();
+}
+
+static int spacemit_k3_early_init(bool cold_boot)
+{
+	if (cold_boot)
+		spacemit_k3_pre_init();
+
+	return generic_early_init(cold_boot);
+}
+
+static int spacemit_k3_platform_init(const void *fdt, int nodeoff,
+				     const struct fdt_match *match)
+{
+	spacemit_k3_hart_init(current_hartid());
+	generic_platform_ops.early_init = spacemit_k3_early_init;
+
+	return 0;
+}
+
+static const struct fdt_match spacemit_k3_match[] = {
+	{ .compatible = "spacemit,k3" },
+	{ /* sentinel */ }
+};
+
+const struct fdt_driver spacemit_k3 = {
+	.match_table = spacemit_k3_match,
+	.init = spacemit_k3_platform_init,
+};
diff --git a/platform/generic/spacemit/k3_asm.S b/platform/generic/spacemit/k3_asm.S
new file mode 100644
index 00000000..2da58857
--- /dev/null
+++ b/platform/generic/spacemit/k3_asm.S
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2026 SpacemiT
+ * Authors:
+ *   Xianbin Zhu <xianbin.zhu@linux.spacemit.com>
+ *   Troy Mitchell <troy.mitchell@linux.spacemit.com>
+ */
+
+#define __ASSEMBLY__
+#include <spacemit/common.h>
+#include <spacemit/k3.h>
+
+	.section .entry, "ax", %progbits
+	.align 3
+	.globl _spacemit_k3_warm_start
+_spacemit_k3_warm_start:
+	/* Program PMA attributes before enabling the caches. */
+	li	t0, (PMACFG0_AUDIO_BUF_FIELD_MASK << \
+		     PMACFG0_AUDIO_BUF_FIELD_SHIFT)
+	csrc	CSR_PMACFG0, t0
+	li	t0, (PMACFG0_AUDIO_BUF_ATTR_CACHEABLE << \
+		     PMACFG0_AUDIO_BUF_FIELD_SHIFT)
+	csrs	CSR_PMACFG0, t0
+	li	t0, PMACFG0_XIP_FIELD_CLEAR
+	csrc	CSR_PMACFG0, t0
+	li	t0, PMACFG0_XIP_ATTR_IO
+	csrs	CSR_PMACFG0, t0
+	sfence.vma
+
+	/* Enable L1 snooping and L2 prefetch for this hart. */
+	csrr	t0, mhartid
+	andi	t0, t0, (PLATFORM_MAX_CPUS_PER_CLUSTER - 1)
+	li	t1, 1
+	sll	t1, t1, t0
+	li	t2, (ML2SETUP_IPRF | ML2SETUP_TPRF)
+	or	t1, t1, t2
+	csrs	CSR_ML2SETUP, t1
+	li	t0, ML2HINT_TRACE_TOP_ICGEN
+	csrs	CSR_ML2HINT, t0
+
+	li	t0, MSETUP_BOOT_FLAGS
+	csrs	CSR_MSETUP, t0
+
+	/* Enable H before common code selects the per-hart trap entry. */
+	csrr	t0, mhartid
+	li	t1, PLATFORM_A100_FIRST_ID
+	bgeu	t0, t1, 1f
+	li	t0, MISA_EXT_H
+	csrs	misa, t0
+	.word	0x62000073	/* hfence.gvma */
+1:
+	j	_start_warm
diff --git a/platform/generic/spacemit/objects.mk b/platform/generic/spacemit/objects.mk
index 8309ad1f..eac3199c 100644
--- a/platform/generic/spacemit/objects.mk
+++ b/platform/generic/spacemit/objects.mk
@@ -2,6 +2,10 @@
 # SPDX-License-Identifier: BSD-2-Clause
 #
 
+ifeq ($(PLATFORM_RISCV_XLEN), 64)
 platform-objs-$(CONFIG_PLATFORM_SPACEMIT) += spacemit/spacemit.o
 carray-platform_override_modules-$(CONFIG_PLATFORM_SPACEMIT_K1) += spacemit_k1
 platform-objs-$(CONFIG_PLATFORM_SPACEMIT_K1) += spacemit/k1.o
+carray-platform_override_modules-$(CONFIG_PLATFORM_SPACEMIT_K3) += spacemit_k3
+platform-objs-$(CONFIG_PLATFORM_SPACEMIT_K3) += spacemit/k3.o spacemit/k3_asm.o
+endif

-- 
2.55.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 1/5] lib: sbi: select expected trap handler per hart
  2026-08-27  9:19 ` [PATCH v3 1/5] lib: sbi: select expected trap handler per hart Troy Mitchell
@ 2026-08-31  2:21   ` Alvin Chang
  2026-09-01  5:45     ` Troy Mitchell
  0 siblings, 1 reply; 20+ messages in thread
From: Alvin Chang @ 2026-08-31  2:21 UTC (permalink / raw)
  To: Troy Mitchell
  Cc: opensbi, Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt


Hi Troy,

Have you tried stack protector?

I changed them to use extern symbol directly because they break stack protector.
Please check my patchset sent last year:
https://lore.kernel.org/all/20250703151957.2545958-1-alvinga@andestech.com/


Thanks,
Alvin

On Thu, 27 Aug 2026 17:19:19 +0800, Troy Mitchell wrote:
> The expected trap handler is selected once by the cold boot hart. This
> breaks heterogeneous systems where the cold boot hart implements H but
> another hart does not, because the H-aware handler accesses mtval2 and
> mtinst.
>
> Select the handler from the current hart's MISA at each use so every
> hart uses only the CSRs it implements.
>
> Fixes: 1de66d170e71 ("lib: Optimize unpriv load/store implementation")
> Reported-by: Bo Gan <ganboing@gmail.com>
> Link: https://lore.kernel.org/r/e702f291-dde8-4b99-a65e-182d2b847720@gmail.com
> Suggested-by: Bo Gan <ganboing@gmail.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> Reviewed-by: Bo Gan <ganboing@gmail.com>
> ---
>  include/sbi/sbi_csr_detect.h | 4 ++--
>  include/sbi/sbi_hart.h       | 2 +-
>  lib/sbi/sbi_hart.c           | 9 +++++----
>  lib/sbi/sbi_illegal_atomic.c | 4 ++--
>  lib/sbi/sbi_unpriv.c         | 6 +++---
>  5 files changed, 13 insertions(+), 12 deletions(-)
>
> diff --git a/include/sbi/sbi_csr_detect.h b/include/sbi/sbi_csr_detect.h
> index 097c31c8..31e50db9 100644
> --- a/include/sbi/sbi_csr_detect.h
> +++ b/include/sbi/sbi_csr_detect.h
> @@ -16,9 +16,9 @@
>  
>  #define csr_read_allowed(csr_num, trap)					\
>  	({								\
> +	register ulong mtvec = sbi_hart_expected_trap_addr();		\
>  	register ulong tinfo asm("a3") = (ulong)trap;			\
>  	register ulong ttmp asm("a4");					\
> -	register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
>  	register ulong ret = 0;						\
>  	((struct sbi_trap_info *)(trap))->cause = 0;			\
>  	asm volatile(							\
> @@ -35,9 +35,9 @@
>  
>  #define csr_write_allowed(csr_num, trap, value)				\
>  	({								\
> +	register ulong mtvec = sbi_hart_expected_trap_addr();		\
>  	register ulong tinfo asm("a3") = (ulong)trap;			\
>  	register ulong ttmp asm("a4");					\
> -	register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
>  	((struct sbi_trap_info *)(trap))->cause = 0;			\
>  	asm volatile(							\
>  		"add %[ttmp], %[tinfo], zero\n"				\
> diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
> index 543393bb..6f4ee31e 100644
> --- a/include/sbi/sbi_hart.h
> +++ b/include/sbi/sbi_hart.h
> @@ -135,7 +135,7 @@ struct sbi_scratch;
>  int sbi_hart_reinit(struct sbi_scratch *scratch);
>  int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot);
>  
> -extern void (*sbi_hart_expected_trap)(void);
> +ulong sbi_hart_expected_trap_addr(void);
>  
>  unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
>  void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
> diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
> index bee88557..14e44955 100644
> --- a/lib/sbi/sbi_hart.c
> +++ b/lib/sbi/sbi_hart.c
> @@ -25,7 +25,11 @@
>  extern void __sbi_expected_trap(void);
>  extern void __sbi_expected_trap_hext(void);
>  
> -void (*sbi_hart_expected_trap)(void) = &__sbi_expected_trap;
> +ulong sbi_hart_expected_trap_addr(void)
> +{
> +	return misa_extension('H') ? (ulong)&__sbi_expected_trap_hext :
> +				     (ulong)&__sbi_expected_trap;
> +}
>  
>  unsigned long hart_features_offset;
>  
> @@ -712,9 +716,6 @@ int sbi_hart_init(struct sbi_scratch *scratch, bool cold_boot)
>  	csr_write(CSR_MIP, 0);
>  
>  	if (cold_boot) {
> -		if (misa_extension('H'))
> -			sbi_hart_expected_trap = &__sbi_expected_trap_hext;
> -
>  		hart_features_offset = sbi_scratch_alloc_offset(
>  					sizeof(struct sbi_hart_features));
>  		if (!hart_features_offset)
> diff --git a/lib/sbi/sbi_illegal_atomic.c b/lib/sbi/sbi_illegal_atomic.c
> index 977a9ad0..30f5118e 100644
> --- a/lib/sbi/sbi_illegal_atomic.c
> +++ b/lib/sbi/sbi_illegal_atomic.c
> @@ -30,7 +30,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
>  	{									\
>  		register ulong tinfo asm("a3");					\
>  		register ulong mstatus = 0;					\
> -		register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
> +		register ulong mtvec = sbi_hart_expected_trap_addr();		\
>  		type ret = 0;							\
>  		trap->cause = 0;						\
>  		asm volatile(							\
> @@ -57,7 +57,7 @@ int sbi_illegal_atomic(ulong insn, struct sbi_trap_regs *regs)
>  	{									\
>  		register ulong tinfo asm("a3");					\
>  		register ulong mstatus = 0;					\
> -		register ulong mtvec = (ulong)sbi_hart_expected_trap;		\
> +		register ulong mtvec = sbi_hart_expected_trap_addr();		\
>  		type ret = 0;							\
>  		trap->cause = 0;						\
>  		asm volatile(							\
> diff --git a/lib/sbi/sbi_unpriv.c b/lib/sbi/sbi_unpriv.c
> index 60becedc..1550d111 100644
> --- a/lib/sbi/sbi_unpriv.c
> +++ b/lib/sbi/sbi_unpriv.c
> @@ -33,9 +33,9 @@ union sbi_unpriv_data {
>  	type sbi_load_##type(const type *addr,                                \
>  			     struct sbi_trap_info *trap)                      \
>  	{                                                                     \
> +		register ulong mtvec = sbi_hart_expected_trap_addr();         \
>  		register ulong tinfo asm("a3") = (ulong)trap;                 \
>  		register ulong mstatus = 0;                                   \
> -		register ulong mtvec = (ulong)sbi_hart_expected_trap;         \
>  		type ret = 0;                                                 \
>  		trap->cause = 0;                                              \
>  		asm volatile(                                                 \
> @@ -58,9 +58,9 @@ union sbi_unpriv_data {
>  	void sbi_store_##type(type *addr, type val,                           \
>  			      struct sbi_trap_info *trap)                     \
>  	{                                                                     \
> +		register ulong mtvec = sbi_hart_expected_trap_addr();         \
>  		register ulong tinfo asm("a3") = (ulong)trap;                 \
>  		register ulong mstatus = 0;                                   \
> -		register ulong mtvec = (ulong)sbi_hart_expected_trap;         \
>  		trap->cause = 0;                                              \
>  		asm volatile(                                                 \
>  			"csrrw %[mtvec], " STR(CSR_MTVEC) ", %[mtvec]\n"      \
> @@ -207,7 +207,7 @@ ulong sbi_get_insn(ulong mepc, struct sbi_trap_info *trap)
>  	register ulong tinfo asm("a3");
>  	register ulong ttmp asm("a4");
>  	register ulong mstatus = 0;
> -	register ulong mtvec = (ulong)sbi_hart_expected_trap;
> +	register ulong mtvec = sbi_hart_expected_trap_addr();
>  	ulong insn = 0;
>  
>  	trap->cause = 0;
>
> -- 
> 2.55.0
>
>
> -- 
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/3] platform: generic: spacemit: k3: de-vote cluster power-downs and ungate DMASYS before CCI enable
       [not found] ` <20260831200832.404000-1-valentin.haudiquet@canonical.com>
@ 2026-08-31 20:07   ` Valentin Haudiquet
  2026-09-01  2:25     ` Troy Mitchell
  2026-08-31 20:07   ` [PATCH 2/3] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only Valentin Haudiquet
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Valentin Haudiquet @ 2026-08-31 20:07 UTC (permalink / raw)
  To: opensbi
  Cc: troy.mitchell, xianbin.zhu, anup, ganboing, samuel.holland,
	heinrich.schuchardt, Valentin Haudiquet

The v3 patch enables CCI-550 snoop/DVM requests for all seven slave
interfaces before de-voting cluster power-downs.  Clusters that are
still voted for power-down cause the CCI status change-pending
busy-wait to hang indefinitely when snoop/DVM is enabled on their
slave interfaces.

De-vote power-down for all four clusters and the boot hart's core
BEFORE enabling CCI.  Also deassert DMASYS reset and enable its clock
before CCI: the DMA engine sits behind the AIDMA CCI slave interface,
and if DMASYS is held in reset the CCI busy-wait hangs when enabling
snoop/DVM on that interface.

Add DMASYS_RESET and DMASYS_CLK_EN register definitions to k3.h.

Signed-off-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
---
 platform/generic/include/spacemit/k3.h |  5 +++
 platform/generic/spacemit/k3.c         | 50 ++++++++++++++++++++++----
 2 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/platform/generic/include/spacemit/k3.h b/platform/generic/include/spacemit/k3.h
index f444d064..ed1637b9 100644
--- a/platform/generic/include/spacemit/k3.h
+++ b/platform/generic/include/spacemit/k3.h
@@ -124,4 +124,9 @@
 #define PLAT_CCI_K3_CLUSTER3_0_IFACE_IX	5
 #define PLAT_CCI_K3_CLUSTER3_1_IFACE_IX	6
 
+/* DMASYS reset and clock enable */
+#define DMASYS_RESET				(0xd8440000 + 0x22c)
+#define DMASYS_CLK_EN				(0xd8440000 + 0x234)
+#define DMASYS_RESET_DEASSERT			BIT(0)
+#define DMASYS_CLK_EN_BIT			BIT(0)
 #endif /* __RISCV_SPACEMIT_K3_H__ */
diff --git a/platform/generic/spacemit/k3.c b/platform/generic/spacemit/k3.c
index 967d09bf..12c991b6 100644
--- a/platform/generic/spacemit/k3.c
+++ b/platform/generic/spacemit/k3.c
@@ -56,14 +56,39 @@ static void spacemit_k3_hart_init(u32 hartid)
 	}
 }
 
-/* The boot hart is already running, so it is never started by the HSM. */
-static void spacemit_k3_keep_boot_hart_powered(void)
+/*
+ * De-vote power-down for all four clusters.  This must happen BEFORE
+ * CCI snoop/DVM enable: clusters still in power-down vote cause the
+ * CCI busy-wait to hang when enabling snoop/DVM on their slave interfaces.
+ */
+static void spacemit_k3_keep_all_clusters_powered(void)
 {
 	u32 value;
+	int i;
 
-	value = readl((void *)(unsigned long)PMU_CX_CAPMP_IDLE_CFG0);
-	value &= ~CLUSTER_PWR_DOWN_VALUE;
-	writel(value, (void *)(unsigned long)PMU_CX_CAPMP_IDLE_CFG0);
+	static const u32 cluster_idle_regs[] = {
+		PMU_CX_CAPMP_IDLE_CFG0,   /* cluster 0 (harts 0-3)  */
+		PMU_CX_CAPMP_IDLE_CFG4,   /* cluster 1 (harts 4-7)  */
+		PMU_CX_CAPMP_IDLE_CFG8,   /* cluster 2 (harts 8-11) */
+		PMU_CX_CAPMP_IDLE_CFG12,  /* cluster 3 (harts 12-15) */
+	};
+
+	for (i = 0; i < 4; i++) {
+		value = readl((void *)(unsigned long)cluster_idle_regs[i]);
+		value &= ~CLUSTER_PWR_DOWN_VALUE;
+		writel(value, (void *)(unsigned long)cluster_idle_regs[i]);
+	}
+}
+
+/*
+ * De-vote the boot hart's core-level power-down.  The cluster-level
+ * de-vote for cluster 0 is already done by keep_all_clusters_powered();
+ * this clears the per-core idle config so the boot hart is never
+ * powered down by the PMU.
+ */
+static void spacemit_k3_keep_boot_hart_powered(void)
+{
+	u32 value;
 
 	value = readl((void *)(unsigned long)PMU_AP_CORE0_IDLE_CFG);
 	value &= ~PMU_AP_IDLE_PWRDOWN_K3_MASK;
@@ -88,10 +113,21 @@ static void spacemit_k3_pre_init(void)
 	writel((u32)entry, (void *)(unsigned long)C3_RVBADDR_LO_ADDR);
 	writel((u32)(entry >> 32), (void *)(unsigned long)C3_RVBADDR_HI_ADDR);
 
+	/* De-vote all cluster power-downs BEFORE CCI enable. */
+	spacemit_k3_keep_all_clusters_powered();
+	spacemit_k3_keep_boot_hart_powered();
+
+	/*
+	 * Deassert DMASYS reset and enable its clock before CCI: the DMA
+	 * engine sits behind the AIDMA CCI slave interface.  If DMASYS is
+	 * held in reset or its clock is gated, the CCI busy-wait hangs when
+	 * enabling snoop/DVM on that interface.
+	 */
+	writel(DMASYS_RESET_DEASSERT, (void *)(unsigned long)DMASYS_RESET);
+	writel(DMASYS_CLK_EN_BIT, (void *)(unsigned long)DMASYS_CLK_EN);
+
 	for (i = 0; i < array_size(cci_map); i++)
 		cci_enable_snoop_dvm_reqs(cci_map, i);
-
-	spacemit_k3_keep_boot_hart_powered();
 }
 
 static int spacemit_k3_early_init(bool cold_boot)
-- 
2.53.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/3] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only
       [not found] ` <20260831200832.404000-1-valentin.haudiquet@canonical.com>
  2026-08-31 20:07   ` [PATCH 1/3] platform: generic: spacemit: k3: de-vote cluster power-downs and ungate DMASYS before CCI enable Valentin Haudiquet
@ 2026-08-31 20:07   ` Valentin Haudiquet
  2026-09-01  5:45     ` Troy Mitchell
  2026-08-31 20:07   ` [PATCH 3/3] platform: generic: spacemit: k3: wake A100 core 8 for ESOS/RPMI services Valentin Haudiquet
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Valentin Haudiquet @ 2026-08-31 20:07 UTC (permalink / raw)
  To: opensbi
  Cc: troy.mitchell, xianbin.zhu, anup, ganboing, samuel.holland,
	heinrich.schuchardt, Valentin Haudiquet

Only hart 0 is powered at reset on K3.  Without overriding
cold_boot_allowed, the generic default checks a DTB hart mask which may
allow non-hart-0 harts to attempt cold boot, breaking the coldboot
lottery on a platform where only one hart is running.

Add spacemit_k3_cold_boot_allowed() returning true only for hart 0,
matching K1's pattern.

Signed-off-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
---
 platform/generic/spacemit/k3.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/platform/generic/spacemit/k3.c b/platform/generic/spacemit/k3.c
index 12c991b6..f134427d 100644
--- a/platform/generic/spacemit/k3.c
+++ b/platform/generic/spacemit/k3.c
@@ -138,11 +138,17 @@ static int spacemit_k3_early_init(bool cold_boot)
 	return generic_early_init(cold_boot);
 }
 
+static bool spacemit_k3_cold_boot_allowed(u32 hartid)
+{
+	return !hartid;
+}
+
 static int spacemit_k3_platform_init(const void *fdt, int nodeoff,
 				     const struct fdt_match *match)
 {
 	spacemit_k3_hart_init(current_hartid());
 	generic_platform_ops.early_init = spacemit_k3_early_init;
+	generic_platform_ops.cold_boot_allowed = spacemit_k3_cold_boot_allowed;
 
 	return 0;
 }
-- 
2.53.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/3] platform: generic: spacemit: k3: wake A100 core 8 for ESOS/RPMI services
       [not found] ` <20260831200832.404000-1-valentin.haudiquet@canonical.com>
  2026-08-31 20:07   ` [PATCH 1/3] platform: generic: spacemit: k3: de-vote cluster power-downs and ungate DMASYS before CCI enable Valentin Haudiquet
  2026-08-31 20:07   ` [PATCH 2/3] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only Valentin Haudiquet
@ 2026-08-31 20:07   ` Valentin Haudiquet
  2026-09-01  2:25     ` Troy Mitchell
  2026-09-01  5:48   ` [PATCH 0/3] platform: generic: spacemit: k3: follow-up fixes Troy Mitchell
  2026-09-01 22:41   ` [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Bo Gan
  4 siblings, 1 reply; 20+ messages in thread
From: Valentin Haudiquet @ 2026-08-31 20:07 UTC (permalink / raw)
  To: opensbi
  Cc: troy.mitchell, xianbin.zhu, anup, ganboing, samuel.holland,
	heinrich.schuchardt, Valentin Haudiquet

The K3 SoC has two asymmetric CPU complexes: X100 (harts 0-7) and A100
(harts 8-15).  ESOS -- the rcpu-side firmware already loaded in SPI NOR --
runs on A100 core 8 and provides RPMI services (clock, voltage, device
power, system reset, suspend) that the X100 side depends on during boot.

Without waking core 8, all RPMI mailbox transactions time out and the
system hangs early during Linux boot (at basic.target or
cryptsetup.target, depending on which earlier fixes are present).

Wake hart 8 during pre_init by writing its RVBADDR to a minimal assembly
entry (_spacemit_k3_dummy_start) that does A100-specific CSR setup,
restores C2 RVBADDR to the normal warm-boot entry, and enters WFI.  The
HSM can later start hart 8 normally -- the HSM hart_start happens
post-boot from Linux, so there is no race with the dummy path writing
RVBADDR concurrently.

Add A100 performance CSR definitions (VEC_L1BYPASS, L2_PERF_DIST,
CIU_CHR2_DEPD_DIS, CIU_CHR2_MER_DIS) to k3.h and the
_spacemit_k3_dummy_start entry to k3_asm.S.

Signed-off-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
---
 platform/generic/include/spacemit/k3.h     | 11 ++++
 platform/generic/include/spacemit/k3_asm.h |  1 +
 platform/generic/spacemit/k3.c             | 19 ++++++
 platform/generic/spacemit/k3_asm.S         | 75 ++++++++++++++++++++++
 4 files changed, 106 insertions(+)

diff --git a/platform/generic/include/spacemit/k3.h b/platform/generic/include/spacemit/k3.h
index ed1637b9..b50e9b1b 100644
--- a/platform/generic/include/spacemit/k3.h
+++ b/platform/generic/include/spacemit/k3.h
@@ -129,4 +129,15 @@
 #define DMASYS_CLK_EN				(0xd8440000 + 0x234)
 #define DMASYS_RESET_DEASSERT			BIT(0)
 #define DMASYS_CLK_EN_BIT			BIT(0)
+/*
+ * A100 core performance CSRs.  CIU_CHR2_DEPD_DIS and CIU_CHR2_MER_DIS
+ * are bitfields of CSR_ML2HINT (0x7f7), named after the hardware manual's
+ * CIU_CHR2 register description.
+ */
+#define CSR_PERF_CTRL				0x7d0
+#define VEC_L1BYPASS				(_UL(1) << 32)
+#define CSR_PREFETCH_CTRL			0x7d1
+#define L2_PERF_DIST				(_UL(3) << 10)
+#define CIU_CHR2_DEPD_DIS			(_UL(1) << 3)
+#define CIU_CHR2_MER_DIS			(_UL(1) << 2)
 #endif /* __RISCV_SPACEMIT_K3_H__ */
diff --git a/platform/generic/include/spacemit/k3_asm.h b/platform/generic/include/spacemit/k3_asm.h
index 70c00478..3f06b20e 100644
--- a/platform/generic/include/spacemit/k3_asm.h
+++ b/platform/generic/include/spacemit/k3_asm.h
@@ -11,6 +11,7 @@
 
 #ifndef __ASSEMBLY__
 void _spacemit_k3_warm_start(void);
+void _spacemit_k3_dummy_start(void);
 #endif
 
 #endif /* __RISCV_SPACEMIT_K3_ASM_H__ */
diff --git a/platform/generic/spacemit/k3.c b/platform/generic/spacemit/k3.c
index f134427d..650e9f98 100644
--- a/platform/generic/spacemit/k3.c
+++ b/platform/generic/spacemit/k3.c
@@ -128,6 +128,25 @@ static void spacemit_k3_pre_init(void)
 
 	for (i = 0; i < array_size(cci_map); i++)
 		cci_enable_snoop_dvm_reqs(cci_map, i);
+
+	/*
+	 * Wake hart 8 (first A100 core, cluster 2) so that ESOS -- already
+	 * loaded in SPI NOR -- can provide RPMI services (clock, voltage,
+	 * device power, system reset, suspend).  Without this, all RPMI
+	 * mailbox transactions time out.
+	 *
+	 * Core 8 jumps to _spacemit_k3_dummy_start which does minimal A100
+	 * setup, restores C2 RVBADDR to the normal warm-boot entry, and
+	 * enters WFI.  The K3 HSM can later start it normally -- the HSM
+	 * hart_start for hart 8 happens much later (post-boot, from Linux),
+	 * so there is no window where both the dummy path and HSM could
+	 * write RVBADDR concurrently.
+	 */
+	writel((u32)(unsigned long)&_spacemit_k3_dummy_start,
+	       (void *)(unsigned long)C2_RVBADDR_LO_ADDR);
+	writel((u32)((unsigned long)&_spacemit_k3_dummy_start >> 32),
+	       (void *)(unsigned long)C2_RVBADDR_HI_ADDR);
+	writel(BIT(8), (void *)(unsigned long)PMU_CAP_CORE8_WAKEUP);
 }
 
 static int spacemit_k3_early_init(bool cold_boot)
diff --git a/platform/generic/spacemit/k3_asm.S b/platform/generic/spacemit/k3_asm.S
index 2da58857..9d1ea5c5 100644
--- a/platform/generic/spacemit/k3_asm.S
+++ b/platform/generic/spacemit/k3_asm.S
@@ -50,3 +50,78 @@ _spacemit_k3_warm_start:
 	.word	0x62000073	/* hfence.gvma */
 1:
 	j	_start_warm
+
+/*
+ * Minimal entry point for the initial wake of an A100 core (hart 8) on
+ * cluster 2.  Its sole purpose is to power up the cluster so that ESOS
+ * -- already loaded in SPI NOR -- can provide RPMI services (clock, voltage,
+ * device power, system reset, suspend).  After setup the core enters WFI;
+ * the K3 HSM can later start it normally via the warm-boot vector.
+ *
+ * The PMA/L2/cache setup below mirrors _spacemit_k3_warm_start, plus
+ * A100-specific performance CSRs that ESOS needs.  These are applied
+ * only here because upstream K3 support targets X100 harts (0-7) for
+ * Linux; A100 harts (8-15) are used solely for ESOS.  When the HSM
+ * later starts hart 8 from Linux, it enters warm_start -- the perf CSR
+ * settings persist from this initial wake since it is a WFI exit, not
+ * a cold reset.
+ *
+ * The C2 RVBADDR is restored to _spacemit_k3_warm_start so that the next
+ * wake (from HSM hart_start) enters the standard OpenSBI warm-boot path.
+ */
+	.align 3
+	.globl _spacemit_k3_dummy_start
+_spacemit_k3_dummy_start:
+	/* Disable all interrupts. */
+	csrw	0x304, zero		/* CSR_MIE */
+
+	/* Program PMA attributes before enabling the caches. */
+	li	t0, (PMACFG0_AUDIO_BUF_FIELD_MASK << \
+		     PMACFG0_AUDIO_BUF_FIELD_SHIFT)
+	csrc	CSR_PMACFG0, t0
+	li	t0, (PMACFG0_AUDIO_BUF_ATTR_CACHEABLE << \
+		     PMACFG0_AUDIO_BUF_FIELD_SHIFT)
+	csrs	CSR_PMACFG0, t0
+	li	t0, PMACFG0_XIP_FIELD_CLEAR
+	csrc	CSR_PMACFG0, t0
+	li	t0, PMACFG0_XIP_ATTR_IO
+	csrs	CSR_PMACFG0, t0
+	sfence.vma
+
+	/* A100-specific performance CSRs. */
+	li	t0, VEC_L1BYPASS
+	csrs	CSR_PERF_CTRL, t0
+	li	t0, L2_PERF_DIST
+	csrs	CSR_PREFETCH_CTRL, t0
+	li	t0, CIU_CHR2_DEPD_DIS
+	csrc	CSR_ML2HINT, t0
+	li	t0, CIU_CHR2_MER_DIS
+	csrs	CSR_ML2HINT, t0
+
+	/* Enable L1 snooping and L2 prefetch for this hart. */
+	csrr	t0, mhartid
+	andi	t0, t0, (PLATFORM_MAX_CPUS_PER_CLUSTER - 1)
+	li	t1, 1
+	sll	t1, t1, t0
+	li	t2, (ML2SETUP_IPRF | ML2SETUP_TPRF)
+	or	t1, t1, t2
+	csrs	CSR_ML2SETUP, t1
+	li	t0, ML2HINT_TRACE_TOP_ICGEN
+	csrs	CSR_ML2HINT, t0
+
+	/* Enable caches. */
+	li	t0, MSETUP_BOOT_FLAGS
+	csrs	CSR_MSETUP, t0
+	fence	iorw, iorw	/* A100 needs explicit fence after MSETUP */
+
+	/* Restore C2 RVBADDR to the normal warm-boot entry. */
+	lla	t0, _spacemit_k3_warm_start
+	li	t1, C2_RVBADDR_LO_ADDR
+	sw	t0, 0(t1)
+	li	t1, C2_RVBADDR_HI_ADDR
+	srli	t0, t0, 32
+	sw	t0, 0(t1)
+
+	/* Enter WFI until the HSM starts this hart. */
+1:	wfi
+	j	1b
-- 
2.53.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/3] platform: generic: spacemit: k3: de-vote cluster power-downs and ungate DMASYS before CCI enable
  2026-08-31 20:07   ` [PATCH 1/3] platform: generic: spacemit: k3: de-vote cluster power-downs and ungate DMASYS before CCI enable Valentin Haudiquet
@ 2026-09-01  2:25     ` Troy Mitchell
  0 siblings, 0 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-09-01  2:25 UTC (permalink / raw)
  To: Valentin Haudiquet
  Cc: opensbi, troy.mitchell, Xianbin Zhu, Anup Patel, Bo Gan,
	Samuel Holland, Heinrich Schuchardt


[-- Attachment #1.1: Type: text/plain, Size: 2025 bytes --]

On Mon, Aug 31, 2026 at 10:07 PM +0200, Valentin Haudiquet wrote:
> De-vote power-down for all four clusters and the boot hart's core
> BEFORE enabling CCI.  Also deassert DMASYS reset and enable its clock
> before CCI: the DMA engine sits behind the AIDMA CCI slave interface,
> and if DMASYS is held in reset the CCI busy-wait hangs when enabling
> snoop/DVM on that interface.
>
> @@ -88,10 +113,21 @@ static void spacemit_k3_pre_init(void)
>  	writel((u32)entry, (void *)(unsigned long)C3_RVBADDR_LO_ADDR);
>  	writel((u32)(entry >> 32), (void *)(unsigned long)C3_RVBADDR_HI_ADDR);
>  
> +	/* De-vote all cluster power-downs BEFORE CCI enable. */
> +	spacemit_k3_keep_all_clusters_powered();
> +	spacemit_k3_keep_boot_hart_powered();
> +
> +	/*
> +	 * Deassert DMASYS reset and enable its clock before CCI: the DMA
> +	 * engine sits behind the AIDMA CCI slave interface.  If DMASYS is
> +	 * held in reset or its clock is gated, the CCI busy-wait hangs when
> +	 * enabling snoop/DVM on that interface.
> +	 */
> +	writel(DMASYS_RESET_DEASSERT, (void *)(unsigned long)DMASYS_RESET);
> +	writel(DMASYS_CLK_EN_BIT, (void *)(unsigned long)DMASYS_CLK_EN);
> +
>  	for (i = 0; i < array_size(cci_map); i++)
>  		cci_enable_snoop_dvm_reqs(cci_map, i);
> -
> -	spacemit_k3_keep_boot_hart_powered();

This ordering does not match the vendor OpenSBI implementation we have. It
enables CCI interfaces 0 through 6 before de-voting the cluster power-down
bits, and ungates DMASYS only after CCI setup.

Which slave interface remains change-pending, and what register state did
you observe before these writes? Please also specify the boot firmware and
DT combination used for the test. Since cluster de-voting and DMASYS
ungating are independent changes, they should be tested and justified
separately.

The patch also leaves every cluster de-voted after CCI setup. Is that
required, or should the previous power-down state be restored?

                                            - Troy

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 248 bytes --]

[-- Attachment #2: Type: text/plain, Size: 105 bytes --]

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/3] platform: generic: spacemit: k3: wake A100 core 8 for ESOS/RPMI services
  2026-08-31 20:07   ` [PATCH 3/3] platform: generic: spacemit: k3: wake A100 core 8 for ESOS/RPMI services Valentin Haudiquet
@ 2026-09-01  2:25     ` Troy Mitchell
  0 siblings, 0 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-09-01  2:25 UTC (permalink / raw)
  To: Valentin Haudiquet
  Cc: opensbi, troy.mitchell, Xianbin Zhu, Anup Patel, Bo Gan,
	Samuel Holland, Heinrich Schuchardt


[-- Attachment #1.1: Type: text/plain, Size: 1821 bytes --]

On Mon, Aug 31, 2026 at 10:07 PM +0200, Valentin Haudiquet wrote:
> The K3 SoC has two asymmetric CPU complexes: X100 (harts 0-7) and A100
> (harts 8-15).  ESOS -- the rcpu-side firmware already loaded in SPI NOR --
> runs on A100 core 8 and provides RPMI services (clock, voltage, device
> power, system reset, suspend) that the X100 side depends on during boot.
>
> Without waking core 8, all RPMI mailbox transactions time out and the
> system hangs early during Linux boot (at basic.target or
> cryptsetup.target, depending on which earlier fixes are present).

This does not match the SDK firmware layout. ESOS runs on the two RT24
RCPUs; the FIT contains rt24_os0_rcpu.elf and rt24_os1_rcpu.elf. A100
hart 8 is not the processor executing ESOS.

Please clarify what hardware dependency is satisfied by waking hart 8, and
provide the exact kernel, DTB, FSBL/U-Boot and ESOS versions used for the
test, along with the RPMI request that times out.

> +	/* Restore C2 RVBADDR to the normal warm-boot entry. */
> +	lla	t0, _spacemit_k3_warm_start
> +	li	t1, C2_RVBADDR_LO_ADDR
> +	sw	t0, 0(t1)
> +	li	t1, C2_RVBADDR_HI_ADDR
> +	srli	t0, t0, 32
> +	sw	t0, 0(t1)
> +
> +	/* Enter WFI until the HSM starts this hart. */
> +1:	wfi
> +	j	1b

The vendor OpenSBI path powers hart 8 back down and flushes and disables
its caches and snooping before entering WFI. This code instead leaves
hart 8 running in a private WFI loop. Reprogramming C2_RVBADDR does not
by itself transfer an already-running hart to _spacemit_k3_warm_start,
so a later HSM start is not guaranteed to work.

If this sequence is required by the SDK firmware ABI, it should be a
separate, DT-described compatibility path and must preserve the normal HSM
lifecycle.

                                            - Troy

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 248 bytes --]

[-- Attachment #2: Type: text/plain, Size: 105 bytes --]

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 1/5] lib: sbi: select expected trap handler per hart
  2026-08-31  2:21   ` Alvin Chang
@ 2026-09-01  5:45     ` Troy Mitchell
  0 siblings, 0 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-09-01  5:45 UTC (permalink / raw)
  To: Alvin Chang
  Cc: opensbi, troy.mitchell, Xianbin Zhu, Anup Patel, Bo Gan,
	Samuel Holland, Heinrich Schuchardt


[-- Attachment #1.1: Type: text/plain, Size: 800 bytes --]

On Mon, Aug 31, 2026 at 10:21 AM +0800, Alvin Chang wrote:
> Have you tried stack protector?
>
> I changed them to use extern symbol directly because they break stack
> protector.
> Please check my patchset sent last year:
> https://lore.kernel.org/all/20250703151957.2545958-1-alvinga@andestech.com/

I had not tested this version with stack protector enabled. I have now
built and booted it under QEMU with CONFIG_STACK_PROTECTOR_ALL. It boots,
but the generated code confirms that the accessor itself is instrumented
and introduces an out-of-line call in this low-level path.

I will replace it with a per-hart handler address stored in scratch and
loaded directly at each use, then test it on K3 with stack protector
enabled.

                                            - Troy

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 248 bytes --]

[-- Attachment #2: Type: text/plain, Size: 105 bytes --]

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/3] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only
  2026-08-31 20:07   ` [PATCH 2/3] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only Valentin Haudiquet
@ 2026-09-01  5:45     ` Troy Mitchell
  0 siblings, 0 replies; 20+ messages in thread
From: Troy Mitchell @ 2026-09-01  5:45 UTC (permalink / raw)
  To: Valentin Haudiquet
  Cc: opensbi, troy.mitchell, Xianbin Zhu, Anup Patel, Bo Gan,
	Samuel Holland, Heinrich Schuchardt


[-- Attachment #1.1: Type: text/plain, Size: 954 bytes --]

On Mon, Aug 31, 2026 at 10:07 PM +0200, Valentin Haudiquet wrote:
> Only hart 0 is powered at reset on K3.  Without overriding
> cold_boot_allowed, the generic default checks a DTB hart mask which may
> allow non-hart-0 harts to attempt cold boot, breaking the coldboot
> lottery on a platform where only one hart is running.
>
> Add spacemit_k3_cold_boot_allowed() returning true only for hart 0,
> matching K1's pattern.
>
> +static bool spacemit_k3_cold_boot_allowed(u32 hartid)
> +{
> +	return !hartid;
> +}

This matches the K3 boot contract and the vendor OpenSBI behavior. Only
hart 0 should participate in the cold-boot lottery; this does not affect
starting secondary harts later through HSM.

As you mentioned in the cover letter that I could take these patches, I
will include this patch in the next revision of my series, retaining your
authorship and Signed-off-by.

                                            - Troy

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 248 bytes --]

[-- Attachment #2: Type: text/plain, Size: 105 bytes --]

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 0/3] platform: generic: spacemit: k3: follow-up fixes
       [not found] ` <20260831200832.404000-1-valentin.haudiquet@canonical.com>
                     ` (2 preceding siblings ...)
  2026-08-31 20:07   ` [PATCH 3/3] platform: generic: spacemit: k3: wake A100 core 8 for ESOS/RPMI services Valentin Haudiquet
@ 2026-09-01  5:48   ` Troy Mitchell
  2026-09-02  8:41     ` Bo Gan
  2026-09-01 22:41   ` [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Bo Gan
  4 siblings, 1 reply; 20+ messages in thread
From: Troy Mitchell @ 2026-09-01  5:48 UTC (permalink / raw)
  To: Valentin Haudiquet
  Cc: opensbi, troy.mitchell, Xianbin Zhu, Anup Patel, Bo Gan,
	Samuel Holland, Heinrich Schuchardt


[-- Attachment #1.1: Type: text/plain, Size: 1615 bytes --]

On Mon, Aug 31, 2026 at 10:07 PM +0200, Valentin Haudiquet wrote:
> I believe one of the issues is that the v3 HSM wakes A100 core 8 only
> when Linux onlines CPU 8. The vendor kernel onlines all 16 CPUs
> so ESOS starts and RPMI works. Mainline uses only the X100 complex
> (harts 0-7), so CPU 8 is never onlined, core 8 is never woken,
> ESOS never runs, and RPMI mailbox transactions time out.
> Patch 3/3 wakes core 8 in OpenSBI pre_init so ESOS is available
> regardless of which CPUs Linux uses.
>
> [...]
>
> I have adapted those patches from the Spacemit OpenSBI 1.6 vendor tree
> logic, through a lot of trial and error. I'm not sure I deeply understand
> the hardware-specific details at play, so any comments would be appreciated.
>
> Feel free to take this in as part of the patchseries and modify it if needed,
> or send review comments and I can also improve them.

The original scope of this series is the K3 platform initialization and
HSM support needed to bring up the X100 and A100 harts. It is not
intended to reproduce the vendor SDK firmware ABI in the initial series.

In the mainline K3 DT, regulators are managed directly by Linux through
the P1 PMIC driver. It contains no K3 RPMI regulator or power-domain
interface, so this boot path does not depend on ESOS.

Your changes appear to additionally target compatibility with the vendor
SDK stack. That may be useful, but it is outside the scope of this initial
series. Support for the vendor SDK stack can be considered separately in
the future if needed.

                                            - Troy

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 248 bytes --]

[-- Attachment #2: Type: text/plain, Size: 105 bytes --]

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support
       [not found] ` <20260831200832.404000-1-valentin.haudiquet@canonical.com>
                     ` (3 preceding siblings ...)
  2026-09-01  5:48   ` [PATCH 0/3] platform: generic: spacemit: k3: follow-up fixes Troy Mitchell
@ 2026-09-01 22:41   ` Bo Gan
  2026-09-02  5:51     ` Bo Gan
  4 siblings, 1 reply; 20+ messages in thread
From: Bo Gan @ 2026-09-01 22:41 UTC (permalink / raw)
  To: Valentin Haudiquet, opensbi
  Cc: troy.mitchell, xianbin.zhu, anup, ganboing, samuel.holland,
	heinrich.schuchardt

Hi Valentin, Troy,

AFAIK, the ESOS runs on the two RT24 cores, not the A100 cores. While
testing v3 patchset, I also observed the rpmi-shmem-mbox@cac90c00 timeout
xmitting messages, and I lost the rpmi backed power-regulator, which then
caused some issues in Linux. I don't think this is caused by the A100 cores
but I suspect this might have something to do with clocks not configured in
vendor uboot SPL. Please check if there're other modification to vendor
uboot that needs to be done, apart from the dts changes, in order to adapt
to this patchset.

Regarding the core/cluster HSM, can SpacemiT publish the K3 TRM, at least
regarding this topic? As there're special power-up/down sequences that a
core needs to follow, it's impossible for outsiders like me to review and
verify if the sequence is correct or not. I was told there's even more
complicated sequences when powering-down a core, if it's the last one in
cluster to power-down (suppose that we may want to support HSM stop in the
future).

Publishing the TRM would also clarify the mysterious Audio buffer, and PMA
register format. What's the address of the Audio buffer, exactly? Is there
a CSR_PMAADDR0?

Bo

On 8/31/26 13:07, Valentin Haudiquet wrote:
> Hello,
> 
> I have tested this patchseries on my K3 board. I had to patch U-Boot
> SPL and EDK2 with the mentioned DTS changes.
> 
> Afterwards, booting the upstream 7.2 kernel with Spacemit patches
> (still in mailing list) works but the kernel hangs in initramfs.
> 
> I had to add 3 patches to make it work properly, see the series
> below.
> 
> I believe one of the issues is that the v3 HSM wakes A100 core 8 only
> when Linux onlines CPU 8. The vendor kernel onlines all 16 CPUs
> so ESOS starts and RPMI works. Mainline uses only the X100 complex
> (harts 0-7), so CPU 8 is never onlined, core 8 is never woken,
> ESOS never runs, and RPMI mailbox transactions time out.
> Patch 3/3 wakes core 8 in OpenSBI pre_init so ESOS is available
> regardless of which CPUs Linux uses.
> 
> For the other patches, I'm not sure why the issues are not encountered
> with the vendor kernel.
> 
> I have adapted those patches from the Spacemit OpenSBI 1.6 vendor tree
> logic, through a lot of trial and error. I'm not sure I deeply understand
> the hardware-specific details at play, so any comments would be appreciated.
> 
> Feel free to take this in as part of the patchseries and modify it if needed,
> or send review comments and I can also improve them.
> 
> Tested-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
> 


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support
  2026-09-01 22:41   ` [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Bo Gan
@ 2026-09-02  5:51     ` Bo Gan
  0 siblings, 0 replies; 20+ messages in thread
From: Bo Gan @ 2026-09-02  5:51 UTC (permalink / raw)
  To: Bo Gan, Valentin Haudiquet, opensbi
  Cc: troy.mitchell, xianbin.zhu, anup, samuel.holland,
	heinrich.schuchardt

On 9/1/26 15:41, Bo Gan wrote:
> Hi Valentin, Troy,
> 
> AFAIK, the ESOS runs on the two RT24 cores, not the A100 cores. While
> testing v3 patchset, I also observed the rpmi-shmem-mbox@cac90c00 timeout
> xmitting messages, and I lost the rpmi backed power-regulator, which then
> caused some issues in Linux. I don't think this is caused by the A100 cores
> but I suspect this might have something to do with clocks not configured in
> vendor uboot SPL. Please check if there're other modification to vendor
> uboot that needs to be done, apart from the dts changes, in order to adapt
> to this patchset.

I found the problem myself. There're many SpacemiT hacks in the vendor tree.
E.g., https://github.com/spacemit-com/opensbi/commits/k3-br-v1.0.y/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c

Without those, ESOS/rpmi simply won't work. SpacemiT, please don't mislead
folks on this part. I was under the impression that this patch would just
work with the shipped ESOS, but it's clearly not the case.

> 
> Regarding the core/cluster HSM, can SpacemiT publish the K3 TRM, at least
> regarding this topic? As there're special power-up/down sequences that a
> core needs to follow, it's impossible for outsiders like me to review and
> verify if the sequence is correct or not. I was told there's even more
> complicated sequences when powering-down a core, if it's the last one in
> cluster to power-down (suppose that we may want to support HSM stop in the
> future).
> 
> Publishing the TRM would also clarify the mysterious Audio buffer, and PMA
> register format. What's the address of the Audio buffer, exactly? Is there
> a CSR_PMAADDR0?
> 
> Bo
> 
> On 8/31/26 13:07, Valentin Haudiquet wrote:
>> Hello,
>>
>> I have tested this patchseries on my K3 board. I had to patch U-Boot
>> SPL and EDK2 with the mentioned DTS changes.
>>
>> Afterwards, booting the upstream 7.2 kernel with Spacemit patches
>> (still in mailing list) works but the kernel hangs in initramfs.
>>
>> I had to add 3 patches to make it work properly, see the series
>> below.
>>
>> I believe one of the issues is that the v3 HSM wakes A100 core 8 only
>> when Linux onlines CPU 8. The vendor kernel onlines all 16 CPUs
>> so ESOS starts and RPMI works. Mainline uses only the X100 complex
>> (harts 0-7), so CPU 8 is never onlined, core 8 is never woken,
>> ESOS never runs, and RPMI mailbox transactions time out.
>> Patch 3/3 wakes core 8 in OpenSBI pre_init so ESOS is available
>> regardless of which CPUs Linux uses.
>>
>> For the other patches, I'm not sure why the issues are not encountered
>> with the vendor kernel.
>>
>> I have adapted those patches from the Spacemit OpenSBI 1.6 vendor tree
>> logic, through a lot of trial and error. I'm not sure I deeply understand
>> the hardware-specific details at play, so any comments would be appreciated.
>>
>> Feel free to take this in as part of the patchseries and modify it if needed,
>> or send review comments and I can also improve them.
>>
>> Tested-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
>>
> 

Bo


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 0/3] platform: generic: spacemit: k3: follow-up fixes
  2026-09-01  5:48   ` [PATCH 0/3] platform: generic: spacemit: k3: follow-up fixes Troy Mitchell
@ 2026-09-02  8:41     ` Bo Gan
  2026-09-02  9:38       ` Troy Mitchell
  0 siblings, 1 reply; 20+ messages in thread
From: Bo Gan @ 2026-09-02  8:41 UTC (permalink / raw)
  To: Troy Mitchell, Valentin Haudiquet
  Cc: opensbi, Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt

Hi Troy,

I missed this one earlier. So basically I need the latest upstream kernel
to be able to test this patchset, because all the rpmi backed devices in
vendor kernel device-tree just won't work. Perhaps this should be called
out in the cover letter, so I don't have to waste time debugging vendor
stuff. IMO, leaving the rpmi stuff out is the right approach for initial
work. I feel that path needs to be properly reviewed and make sure it
fully conforms to the standard.

Bo

On 8/31/26 22:48, Troy Mitchell wrote:
> On Mon, Aug 31, 2026 at 10:07 PM +0200, Valentin Haudiquet wrote:
>> I believe one of the issues is that the v3 HSM wakes A100 core 8 only
>> when Linux onlines CPU 8. The vendor kernel onlines all 16 CPUs
>> so ESOS starts and RPMI works. Mainline uses only the X100 complex
>> (harts 0-7), so CPU 8 is never onlined, core 8 is never woken,
>> ESOS never runs, and RPMI mailbox transactions time out.
>> Patch 3/3 wakes core 8 in OpenSBI pre_init so ESOS is available
>> regardless of which CPUs Linux uses.
>>
>> [...]
>>
>> I have adapted those patches from the Spacemit OpenSBI 1.6 vendor tree
>> logic, through a lot of trial and error. I'm not sure I deeply understand
>> the hardware-specific details at play, so any comments would be appreciated.
>>
>> Feel free to take this in as part of the patchseries and modify it if needed,
>> or send review comments and I can also improve them.
> 
> The original scope of this series is the K3 platform initialization and
> HSM support needed to bring up the X100 and A100 harts. It is not
> intended to reproduce the vendor SDK firmware ABI in the initial series.
> 
> In the mainline K3 DT, regulators are managed directly by Linux through
> the P1 PMIC driver. It contains no K3 RPMI regulator or power-domain
> interface, so this boot path does not depend on ESOS.
> 
> Your changes appear to additionally target compatibility with the vendor
> SDK stack. That may be useful, but it is outside the scope of this initial
> series. Support for the vendor SDK stack can be considered separately in
> the future if needed.
> 
>                                              - Troy


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 0/3] platform: generic: spacemit: k3: follow-up fixes
  2026-09-02  8:41     ` Bo Gan
@ 2026-09-02  9:38       ` Troy Mitchell
  2026-09-02 11:42         ` Valentin Haudiquet
  0 siblings, 1 reply; 20+ messages in thread
From: Troy Mitchell @ 2026-09-02  9:38 UTC (permalink / raw)
  To: Bo Gan, Troy Mitchell, Valentin Haudiquet
  Cc: opensbi, Xianbin Zhu, Anup Patel, Samuel Holland,
	Heinrich Schuchardt


[-- Attachment #1.1: Type: text/plain, Size: 2051 bytes --]

On Wed, Sep 2, 2026 at 01:41:16AM -0700, Bo Gan wrote:
> Hi Troy,
>
> I missed this one earlier. So basically I need the latest upstream kernel
> to be able to test this patchset,

Yes, that is correct. I have only tested this series with the upstream
kernel, not the vendor kernel. Sorry for not pointing this out in the
cover letter.

>
> because all the rpmi backed devices in
> vendor kernel device-tree just won't work. Perhaps this should be called
> out in the cover letter, so I don't have to waste time debugging vendor
> stuff. IMO, leaving the rpmi stuff out is the right approach for initial
> work. I feel that path needs to be properly reviewed and make sure it
> fully conforms to the standard.

I will state this explicitly in the next cover letter. This series
only provides the basic K3 platform initialization and start-only HSM
support needed to bring up the X100 and A100 harts. It does not include
the vendor-specific OpenSBI RPMI support required by the vendor kernel
and DT.

The relevant public documentation is available here:

  CCI and PMA [1]
  HSM-related power management [2]
  Clock and reset [3]
  SoC address map [4]

We do not currently plan to publish additional K3 hardware details.
Before doing so, we would need to reorganize the documentation and review
which parts can be made public. This is a substantial amount of work and
is not currently scheduled.

Link: https://www.spacemit.com/community/document/info?lang=en&nodepath=hardware/key_stone/k3/k3_docs/k3_usermanual/08_cpu.md [1]
Link: https://www.spacemit.com/community/document/info?lang=en&nodepath=hardware/key_stone/k3/k3_docs/k3_usermanual/16_peripherals/power_management.md [2]
Link: https://www.spacemit.com/community/document/info?lang=en&nodepath=hardware/key_stone/k3/k3_docs/k3_usermanual/17_clock_reset.md [3]
Link: https://www.spacemit.com/community/document/info?lang=en&nodepath=hardware/key_stone/k3/k3_docs/k3_usermanual/06_address_map.md [4]

                                            - Troy

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 248 bytes --]

[-- Attachment #2: Type: text/plain, Size: 105 bytes --]

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 0/3] platform: generic: spacemit: k3: follow-up fixes
  2026-09-02  9:38       ` Troy Mitchell
@ 2026-09-02 11:42         ` Valentin Haudiquet
  0 siblings, 0 replies; 20+ messages in thread
From: Valentin Haudiquet @ 2026-09-02 11:42 UTC (permalink / raw)
  To: Troy Mitchell
  Cc: Bo Gan, opensbi, Xianbin Zhu, Anup Patel, Samuel Holland,
	Heinrich Schuchardt, Sarah Emery

Hi Troy, Bo,

Thanks all for the clarifications. Sorry I misunderstood the
architecture and thought ESOS was using A100, I now understand that
this is not the case and that it should not be needed for the upstream
kernel boot.

Troy,
I agree that the vendor path not being part of this series makes
sense. However, you said in cover letter:

> U-Boot and Linux 6.18.3 started, Linux detected SBI v3.0 and the HSM extension, and all 16 CPUs came online.

The "Linux 6.18.3" made me think this was the vendor kernel. The
upstream kernel patches are based on 7.2/7.3 (or at least I thought?).
Thanks for confirming that you tested an upstream-based tree as well
(with backporting of the patches, then?). Also, the upstream kernel
only sees the 8 X100 cores AFAIK, so how did the 16 cores (i.e.
including the A100?) came online?
This is the reason why I assumed you were testing the vendor kernel.

I'm still debugging the issues I have with the upstream 7.2 kernel. I
believe that is the main difference between our tests: you must have
used U-Boot DTB where I used the upstream DTB (force-fed to the kernel
using Grub `devicetree` or an EFI stub), which only describe the 8
X100 cores.

It seems I was mistaken with the ESOS explanation, but I now have a
new theory :)

Here's what I believe is happening:

The v3 pre_init enables CCI-550 snoop and DVM requests for all seven
slave interfaces, including interfaces 3-6 (clusters 2-3, the A100
clusters). The CCI-550
broadcasts every snoop to all enabled slave interfaces. It doesn't
matter that only X100
CPUs are running; every coherent memory access from any X100 core
triggers a snoop to the A100 clusters interfaces.

With the upstream kernel DTB (8 X100 CPUs, clusters 0-1), the kernel
never onlines harts
8-15, so the HSM hart_start is never called for clusters 2-3. Those
clusters stay
unpowered. But the CCI is already snooping their interfaces from
pre_init. Snoops to an
unpowered cluster stall the issuing CPU in a memory instruction: a hard lockup.

I tested this by applying the patches incrementally:

1. v3 unmodified: hard lockup during udev coldplug. The clusters are
still voted for
power-down; the CCI snoop to a fully-dead interconnect can't respond at all.
2. De-vote all clusters + pin cold boot to hart 0: the hang moves
later but still occurs.
A soft hang at basic.target that changes location between reboots.
3. Wake core 8 in pre_init (without the A100 perf CSRs): boots
reliably. Waking core 8
powers up cluster 2, CCI snoops to interfaces 3-4 complete reliably.
(I believe cluster 3 does not need powering up as its L2 was never
touched, and empty L2 returns clean immediately on snoop).

If you used U-Boot DTB, with 16 CPUs, then the kernel onlines all
harts and HSM de-votes
and powers clusters 2-3 before doing coherent memory operations. With
upstream kernel DTB, HSM path never runs.

I'm still trying to figure out all the hardware details and fully
grasp the issues.

I guess I see two paths forward:
- Make the platform X100-only: enable CCI snoop/DVM for interfaces 0-2
(AIDMA + clusters 0-1 only), and drop the A100 HSM support. This
matches the upstream kernel DTB and avoids the stall, but limits the
platform to 8 harts.
- Keep the full 16-hart support, but power all clusters before
enabling CCI snoop. De-vote all clusters and wake core 8 in pre_init
so the interconnects are alive before the CCI starts snooping them.
This is my modified patches 1 and 3 (de-vote all clusters + wake core
8, without the A100 perf CSRs).

Does that make sense? What do you think?

Thanks for the comments and the patience while I try to figure out how
the internals of the K3 platform work.

--
Valentin Haudiquet




On Wed, 2 Sept 2026 at 11:38, Troy Mitchell
<troy.mitchell@linux.spacemit.com> wrote:
>
> On Wed, Sep 2, 2026 at 01:41:16AM -0700, Bo Gan wrote:
> > Hi Troy,
> >
> > I missed this one earlier. So basically I need the latest upstream kernel
> > to be able to test this patchset,
>
> Yes, that is correct. I have only tested this series with the upstream
> kernel, not the vendor kernel. Sorry for not pointing this out in the
> cover letter.
>
> >
> > because all the rpmi backed devices in
> > vendor kernel device-tree just won't work. Perhaps this should be called
> > out in the cover letter, so I don't have to waste time debugging vendor
> > stuff. IMO, leaving the rpmi stuff out is the right approach for initial
> > work. I feel that path needs to be properly reviewed and make sure it
> > fully conforms to the standard.
>
> I will state this explicitly in the next cover letter. This series
> only provides the basic K3 platform initialization and start-only HSM
> support needed to bring up the X100 and A100 harts. It does not include
> the vendor-specific OpenSBI RPMI support required by the vendor kernel
> and DT.
>
> The relevant public documentation is available here:
>
>   CCI and PMA [1]
>   HSM-related power management [2]
>   Clock and reset [3]
>   SoC address map [4]
>
> We do not currently plan to publish additional K3 hardware details.
> Before doing so, we would need to reorganize the documentation and review
> which parts can be made public. This is a substantial amount of work and
> is not currently scheduled.
>
> Link: https://www.spacemit.com/community/document/info?lang=en&nodepath=hardware/key_stone/k3/k3_docs/k3_usermanual/08_cpu.md [1]
> Link: https://www.spacemit.com/community/document/info?lang=en&nodepath=hardware/key_stone/k3/k3_docs/k3_usermanual/16_peripherals/power_management.md [2]
> Link: https://www.spacemit.com/community/document/info?lang=en&nodepath=hardware/key_stone/k3/k3_docs/k3_usermanual/17_clock_reset.md [3]
> Link: https://www.spacemit.com/community/document/info?lang=en&nodepath=hardware/key_stone/k3/k3_docs/k3_usermanual/06_address_map.md [4]
>
>                                             - Troy

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2026-09-02 11:43 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-27  9:19 [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Troy Mitchell
2026-08-27  9:19 ` [PATCH v3 1/5] lib: sbi: select expected trap handler per hart Troy Mitchell
2026-08-31  2:21   ` Alvin Chang
2026-09-01  5:45     ` Troy Mitchell
2026-08-27  9:19 ` [PATCH v3 2/5] platform: generic: spacemit: k1: rename cache flush operation Troy Mitchell
2026-08-27  9:19 ` [PATCH v3 3/5] platform: generic: spacemit: k1: move hart init to nascent hook Troy Mitchell
2026-08-27  9:19 ` [PATCH v3 4/5] platform: generic: spacemit: k1: refactor platform support Troy Mitchell
2026-08-27  9:19 ` [PATCH v3 5/5] platform: generic: spacemit: k3: add " Troy Mitchell
     [not found] ` <20260831200832.404000-1-valentin.haudiquet@canonical.com>
2026-08-31 20:07   ` [PATCH 1/3] platform: generic: spacemit: k3: de-vote cluster power-downs and ungate DMASYS before CCI enable Valentin Haudiquet
2026-09-01  2:25     ` Troy Mitchell
2026-08-31 20:07   ` [PATCH 2/3] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only Valentin Haudiquet
2026-09-01  5:45     ` Troy Mitchell
2026-08-31 20:07   ` [PATCH 3/3] platform: generic: spacemit: k3: wake A100 core 8 for ESOS/RPMI services Valentin Haudiquet
2026-09-01  2:25     ` Troy Mitchell
2026-09-01  5:48   ` [PATCH 0/3] platform: generic: spacemit: k3: follow-up fixes Troy Mitchell
2026-09-02  8:41     ` Bo Gan
2026-09-02  9:38       ` Troy Mitchell
2026-09-02 11:42         ` Valentin Haudiquet
2026-09-01 22:41   ` [PATCH v3 0/5] platform: generic: spacemit: add K3 platform support Bo Gan
2026-09-02  5:51     ` Bo Gan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox