OpenSBI Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support
@ 2026-09-10 14:00 Troy Mitchell
  2026-09-10 14:00 ` [PATCH v4 1/6] lib: sbi: select expected trap handler per hart Troy Mitchell
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Troy Mitchell @ 2026-09-10 14:00 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, Troy Mitchell, Alvin Chang,
	Valentin Haudiquet

This series adds basic K3 platform initialization and start-only HSM
support. Secondary harts are started directly through the SoC PMU. RPMI
support for the vendor kernel is outside the scope of this series; the
upstream Linux boot path does not depend on ESOS.

K3 has eight X100 harts and eight A100 harts across four clusters. X100
implements H with a 256-bit VLEN; A100 has no H and a 1024-bit VLEN. The
existing expected-trap handler is chosen by the cold-boot hart, which
fails if that hart implements H and another does not. Store the handler
per hart in scratch space and load it directly, avoiding an accessor call
in CSR probes. Other extension and vector state is already maintained or
queried per hart.

Only hart 0 is powered at reset. The HSM backend clears the requested
hart's core and cluster power-down votes and wakes it on demand. PMA,
cache and X100 H-extension setup precede the common warm-boot entry.
Cold boot programs the cluster reset vectors and enables CCI-550 snoop
and DVM requests before secondary harts start.

The shared SpacemiT code is limited to common register definitions and
the CCI-550 helper. K1 retains its topology, boot flow and HSM behavior.

I tested this on a K3 COM260 with Linux v7.3-rc1 and only the v5 CPU PLL
rate table patch [1] applied, using the unmodified upstream
k3-com260-ifx.dtb and a minimal initramfs. The board booted from SPI NOR
using the public SDK FSBL and U-Boot, with OpenSBI installed as a
separate FIT using the procedure below.

OpenSBI used the SDK's 16-hart DT and booted on hart 0. Linux brought up
the eight X100 harts described by its DT and reached a shell. I did not
reproduce the hang Valentin reported with Linux 7.2 and an eight-CPU
kernel DT [2].

Build-tested with RV64 generic (CONFIG_STACK_PROTECTOR_ALL) and RV32
generic. SpacemiT platform objects are excluded from RV32 builds.

Firmware installation
---------------------

The following NOR installation steps use the public K3 SDK v1.0.7:

  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 SDK is used to build the boot firmware; the Linux kernel and root
filesystem are built separately. The commands below assume the SDK is
configured for K3, with its host toolchain available in output/k3/host.

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. Rebuild 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/output/k3" uboot-rebuild

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

  FSBL.bin
  bootinfo_spinor.bin
  u-boot.itb

From the OpenSBI source directory, build with the SDK toolchain at the
address used by the SDK, then wrap fw_dynamic.bin in the SDK's standalone
OpenSBI FIT:

  SDK_CROSS_COMPILE="$K3_SDK_DIR/output/k3/host/bin/riscv64-unknown-linux-gnu-"
  make -j24 O=build-k3 CROSS_COMPILE="$SDK_CROSS_COMPILE" \
       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

An existing system can be kept when updating the boot firmware. Flashing
the full Bianbu Minimal system image is only needed for a board without
a usable system.

Link: https://lore.kernel.org/all/20260907-k3-pll5-pll8-1800mhz-v5-1-5cc96d716b0a@linux.spacemit.com/ [1]
Link: https://lore.kernel.org/all/CAPEPrSMsnbuPOUuvj06+PtczdokK42vSpy8n_0hCLh0cEO-QkQ@mail.gmail.com/ [2]

Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
Changes in v4:
- use per-hart scratch for the expected-trap handler, avoiding accessor
  calls and their stack-protector instrumentation; initialize it before
  platform hooks and preserve scratch allocation alignment
- include Valentin Haudiquet's hart-0-only cold-boot restriction as a
  separate patch after K3 platform support
- update the cover letter's test environment, results, and support scope
- Link to v3: https://patch.msgid.link/20260827-spacemit-k3-v3-0-5d8dbb68539d@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

Valentin Haudiquet (1):
      platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only

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                       |   5 +-
 include/sbi/sbi_scratch.h                    |   7 +-
 lib/sbi/sbi_hart.c                           |   8 --
 lib/sbi/sbi_illegal_atomic.c                 |   4 +-
 lib/sbi/sbi_init.c                           |   7 ++
 lib/sbi/sbi_scratch.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               | 128 +++++++++++++++++++++++++++
 platform/generic/spacemit/k3_asm.S           |  52 +++++++++++
 platform/generic/spacemit/objects.mk         |   5 ++
 platform/generic/spacemit/spacemit.c         |  36 ++++++++
 21 files changed, 638 insertions(+), 153 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] 14+ messages in thread

* [PATCH v4 1/6] lib: sbi: select expected trap handler per hart
  2026-09-10 14:00 [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support Troy Mitchell
@ 2026-09-10 14:00 ` Troy Mitchell
  2026-10-08  0:29   ` E Shattow
  2026-09-10 14:00 ` [PATCH v4 2/6] platform: generic: spacemit: k1: rename cache flush operation Troy Mitchell
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Troy Mitchell @ 2026-09-10 14:00 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, Troy Mitchell, Alvin Chang

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 each hart's MISA at entry to sbi_init(), before
platform hooks can probe CSRs, and store its address in that hart's
scratch space. Load the address directly at each use. This avoids an
accessor call and its stack-protector instrumentation in the CSR probing
and unprivileged memory access paths.

Align scratch allocations after the enlarged fixed scratch area so that
the new field preserves the allocator's cache-line alignment guarantee.

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>
Link: https://lore.kernel.org/r/20260831022156.2060561-1-alvinga@andestech.com
Cc: Alvin Chang <alvinga@andestech.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
 include/sbi/sbi_csr_detect.h | 4 ++--
 include/sbi/sbi_hart.h       | 5 ++++-
 include/sbi/sbi_scratch.h    | 7 ++++++-
 lib/sbi/sbi_hart.c           | 8 --------
 lib/sbi/sbi_illegal_atomic.c | 4 ++--
 lib/sbi/sbi_init.c           | 7 +++++++
 lib/sbi/sbi_scratch.c        | 4 ++++
 lib/sbi/sbi_unpriv.c         | 6 +++---
 8 files changed, 28 insertions(+), 17 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..f0a4be61 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -12,6 +12,7 @@
 
 #include <sbi/sbi_types.h>
 #include <sbi/sbi_bitops.h>
+#include <sbi/sbi_scratch.h>
 
 /** Possible privileged specification versions of a hart */
 enum sbi_hart_priv_versions {
@@ -135,7 +136,9 @@ 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);
+/* Keep the load free of function calls, including stack-protector code. */
+#define sbi_hart_expected_trap_addr() \
+	(sbi_scratch_thishart_ptr()->expected_trap)
 
 unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
 void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
diff --git a/include/sbi/sbi_scratch.h b/include/sbi/sbi_scratch.h
index 06097c8a..20e7dcd0 100644
--- a/include/sbi/sbi_scratch.h
+++ b/include/sbi/sbi_scratch.h
@@ -46,8 +46,10 @@
 #define SBI_SCRATCH_OPTIONS_OFFSET		(14 * __SIZEOF_POINTER__)
 /** Offset of hartindex member in sbi_scratch */
 #define SBI_SCRATCH_HARTINDEX_OFFSET		(15 * __SIZEOF_POINTER__)
+/** Offset of expected_trap member in sbi_scratch */
+#define SBI_SCRATCH_EXPECTED_TRAP_OFFSET		(16 * __SIZEOF_POINTER__)
 /** Offset of extra space in sbi_scratch */
-#define SBI_SCRATCH_EXTRA_SPACE_OFFSET		(16 * __SIZEOF_POINTER__)
+#define SBI_SCRATCH_EXTRA_SPACE_OFFSET		(17 * __SIZEOF_POINTER__)
 /** Maximum size of sbi_scratch (4KB) */
 #define SBI_SCRATCH_SIZE			(0x1000)
 
@@ -91,6 +93,8 @@ struct sbi_scratch {
 	unsigned long options;
 	/** Index of the hart */
 	unsigned long hartindex;
+	/** Address of the expected trap handler for this HART */
+	unsigned long expected_trap;
 };
 
 /**
@@ -113,6 +117,7 @@ assert_member_offset(struct sbi_scratch, tmp0, SBI_SCRATCH_TMP0_OFFSET);
 assert_member_offset(struct sbi_scratch, tmp1, SBI_SCRATCH_TMP1_OFFSET);
 assert_member_offset(struct sbi_scratch, options, SBI_SCRATCH_OPTIONS_OFFSET);
 assert_member_offset(struct sbi_scratch, hartindex, SBI_SCRATCH_HARTINDEX_OFFSET);
+assert_member_offset(struct sbi_scratch, expected_trap, SBI_SCRATCH_EXPECTED_TRAP_OFFSET);
 
 /** Possible options for OpenSBI library */
 enum sbi_scratch_options {
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index bee88557..61c5f945 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -22,11 +22,6 @@
 #include <sbi/sbi_string.h>
 #include <sbi/sbi_trap.h>
 
-extern void __sbi_expected_trap(void);
-extern void __sbi_expected_trap_hext(void);
-
-void (*sbi_hart_expected_trap)(void) = &__sbi_expected_trap;
-
 unsigned long hart_features_offset;
 
 static void mstatus_init(struct sbi_scratch *scratch)
@@ -712,9 +707,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_init.c b/lib/sbi/sbi_init.c
index 9bb1a37e..76b4fd91 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -36,6 +36,9 @@
 #include <sbi/sbi_version.h>
 #include <sbi/sbi_unit_test.h>
 
+extern void __sbi_expected_trap(void);
+extern void __sbi_expected_trap_hext(void);
+
 #define BANNER                                              \
 	"   ____                    _____ ____ _____\n"     \
 	"  / __ \\                  / ____|  _ \\_   _|\n"  \
@@ -585,6 +588,10 @@ void __noreturn sbi_init(struct sbi_scratch *scratch)
 	u32 hartid			= current_hartid();
 	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
 
+	/* Platform hooks may probe CSRs before sbi_hart_init(). */
+	scratch->expected_trap = misa_extension('H') ?
+		(ulong)&__sbi_expected_trap_hext : (ulong)&__sbi_expected_trap;
+
 	switch (scratch->next_mode) {
 	case PRV_M:
 		next_mode_supported = true;
diff --git a/lib/sbi/sbi_scratch.c b/lib/sbi/sbi_scratch.c
index bb14a1a2..88ef1547 100644
--- a/lib/sbi/sbi_scratch.c
+++ b/lib/sbi/sbi_scratch.c
@@ -97,6 +97,10 @@ unsigned long sbi_scratch_alloc_offset(unsigned long size)
 
 	spin_lock(&extra_lock);
 
+	/* The fixed scratch fields need not end on a cache-line boundary. */
+	extra_offset = (extra_offset + scratch_alloc_align - 1) &
+		       ~(scratch_alloc_align - 1);
+
 	if (SBI_SCRATCH_SIZE < (extra_offset + size))
 		goto done;
 
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] 14+ messages in thread

* [PATCH v4 2/6] platform: generic: spacemit: k1: rename cache flush operation
  2026-09-10 14:00 [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support Troy Mitchell
  2026-09-10 14:00 ` [PATCH v4 1/6] lib: sbi: select expected trap handler per hart Troy Mitchell
@ 2026-09-10 14:00 ` Troy Mitchell
  2026-10-07 21:20   ` E Shattow
  2026-09-10 14:00 ` [PATCH v4 3/6] platform: generic: spacemit: k1: move hart init to nascent hook Troy Mitchell
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Troy Mitchell @ 2026-09-10 14:00 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, 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] 14+ messages in thread

* [PATCH v4 3/6] platform: generic: spacemit: k1: move hart init to nascent hook
  2026-09-10 14:00 [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support Troy Mitchell
  2026-09-10 14:00 ` [PATCH v4 1/6] lib: sbi: select expected trap handler per hart Troy Mitchell
  2026-09-10 14:00 ` [PATCH v4 2/6] platform: generic: spacemit: k1: rename cache flush operation Troy Mitchell
@ 2026-09-10 14:00 ` Troy Mitchell
  2026-10-07 21:14   ` E Shattow
  2026-09-10 14:00 ` [PATCH v4 4/6] platform: generic: spacemit: k1: refactor platform support Troy Mitchell
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Troy Mitchell @ 2026-09-10 14:00 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, 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] 14+ messages in thread

* [PATCH v4 4/6] platform: generic: spacemit: k1: refactor platform support
  2026-09-10 14:00 [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support Troy Mitchell
                   ` (2 preceding siblings ...)
  2026-09-10 14:00 ` [PATCH v4 3/6] platform: generic: spacemit: k1: move hart init to nascent hook Troy Mitchell
@ 2026-09-10 14:00 ` Troy Mitchell
  2026-10-08  0:30   ` E Shattow
  2026-09-10 14:00 ` [PATCH v4 5/6] platform: generic: spacemit: k3: add " Troy Mitchell
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Troy Mitchell @ 2026-09-10 14:00 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, 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] 14+ messages in thread

* [PATCH v4 5/6] platform: generic: spacemit: k3: add platform support
  2026-09-10 14:00 [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support Troy Mitchell
                   ` (3 preceding siblings ...)
  2026-09-10 14:00 ` [PATCH v4 4/6] platform: generic: spacemit: k1: refactor platform support Troy Mitchell
@ 2026-09-10 14:00 ` Troy Mitchell
  2026-10-08  0:30   ` E Shattow
  2026-09-10 14:00 ` [PATCH v4 6/6] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only Troy Mitchell
  2026-10-08  0:28 ` [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support E Shattow
  6 siblings, 1 reply; 14+ messages in thread
From: Troy Mitchell @ 2026-09-10 14:00 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, 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.
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] 14+ messages in thread

* [PATCH v4 6/6] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only
  2026-09-10 14:00 [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support Troy Mitchell
                   ` (4 preceding siblings ...)
  2026-09-10 14:00 ` [PATCH v4 5/6] platform: generic: spacemit: k3: add " Troy Mitchell
@ 2026-09-10 14:00 ` Troy Mitchell
  2026-10-07 20:58   ` E Shattow
  2026-10-08  0:28 ` [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support E Shattow
  6 siblings, 1 reply; 14+ messages in thread
From: Troy Mitchell @ 2026-09-10 14:00 UTC (permalink / raw)
  To: opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, Troy Mitchell,
	Valentin Haudiquet

From: Valentin Haudiquet <valentin.haudiquet@canonical.com>

Only hart 0 is powered at reset on K3; secondary harts are started later
through HSM. Restrict cold-boot eligibility to hart 0 instead of using
the generic DT-configured hart mask, matching K1.

Signed-off-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.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 967d09bf..7922ab11 100644
--- a/platform/generic/spacemit/k3.c
+++ b/platform/generic/spacemit/k3.c
@@ -102,11 +102,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.55.0


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

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

* Re: [PATCH v4 6/6] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only
  2026-09-10 14:00 ` [PATCH v4 6/6] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only Troy Mitchell
@ 2026-10-07 20:58   ` E Shattow
  0 siblings, 0 replies; 14+ messages in thread
From: E Shattow @ 2026-10-07 20:58 UTC (permalink / raw)
  To: Troy Mitchell, opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, Valentin Haudiquet

On 9/10/26 07:00, Troy Mitchell wrote:
> From: Valentin Haudiquet <valentin.haudiquet@canonical.com>
> 
> Only hart 0 is powered at reset on K3; secondary harts are started later
> through HSM. Restrict cold-boot eligibility to hart 0 instead of using
> the generic DT-configured hart mask, matching K1.
> 
> Signed-off-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.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 967d09bf..7922ab11 100644
> --- a/platform/generic/spacemit/k3.c
> +++ b/platform/generic/spacemit/k3.c
> @@ -102,11 +102,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;
>  }
> 

Reviewed-by: E Shattow <e@freeshell.de>

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

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

* Re: [PATCH v4 3/6] platform: generic: spacemit: k1: move hart init to nascent hook
  2026-09-10 14:00 ` [PATCH v4 3/6] platform: generic: spacemit: k1: move hart init to nascent hook Troy Mitchell
@ 2026-10-07 21:14   ` E Shattow
  0 siblings, 0 replies; 14+ messages in thread
From: E Shattow @ 2026-10-07 21:14 UTC (permalink / raw)
  To: Troy Mitchell, opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang

Hi Troy,

On 9/10/26 07:00, Troy Mitchell wrote:
> 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));

I think use BIT macro here for bitwise left-shift unless some reason not to?

> +
> +	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;
>  
> 

-E

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

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

* Re: [PATCH v4 2/6] platform: generic: spacemit: k1: rename cache flush operation
  2026-09-10 14:00 ` [PATCH v4 2/6] platform: generic: spacemit: k1: rename cache flush operation Troy Mitchell
@ 2026-10-07 21:20   ` E Shattow
  0 siblings, 0 replies; 14+ messages in thread
From: E Shattow @ 2026-10-07 21:20 UTC (permalink / raw)
  To: Troy Mitchell, opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang

Hi Troy,

On 9/10/26 07:00, Troy Mitchell wrote:
> 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 */

There is no mystery about the symbol name this comment describes, to
need a comment. If you want to explicitly write the comment as "D-cache
flush" that adds to the readability. Otherwise it appears to be a
redundant comment. Expand the description in comment so it adds value or
drop the comment, please.

> +#define MRAOP_CACHE_FLUSH			GENMASK(1, 0)
>  
>  #define PMU_AP_BASE				0xd4282800
>  
> 

With that,

Reviewed-by: E Shattow <e@freeshell.de>

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

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

* Re: [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support
  2026-09-10 14:00 [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support Troy Mitchell
                   ` (5 preceding siblings ...)
  2026-09-10 14:00 ` [PATCH v4 6/6] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only Troy Mitchell
@ 2026-10-08  0:28 ` E Shattow
  6 siblings, 0 replies; 14+ messages in thread
From: E Shattow @ 2026-10-08  0:28 UTC (permalink / raw)
  To: Troy Mitchell, opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, Alvin Chang, Valentin Haudiquet

Hi Troy, I reviewed patches in this series for coding style details you
may have overlooked and also here follows an update with my testing
notes for anyone interested.

On 9/10/26 07:00, Troy Mitchell wrote:
> This series adds basic K3 platform initialization and start-only HSM
> support. Secondary harts are started directly through the SoC PMU. RPMI
> support for the vendor kernel is outside the scope of this series; the
> upstream Linux boot path does not depend on ESOS.
> 
> K3 has eight X100 harts and eight A100 harts across four clusters. X100
> implements H with a 256-bit VLEN; A100 has no H and a 1024-bit VLEN. The
> existing expected-trap handler is chosen by the cold-boot hart, which
> fails if that hart implements H and another does not. Store the handler
> per hart in scratch space and load it directly, avoiding an accessor call
> in CSR probes. Other extension and vector state is already maintained or
> queried per hart.
> 
> Only hart 0 is powered at reset. The HSM backend clears the requested
> hart's core and cluster power-down votes and wakes it on demand. PMA,
> cache and X100 H-extension setup precede the common warm-boot entry.
> Cold boot programs the cluster reset vectors and enables CCI-550 snoop
> and DVM requests before secondary harts start.
> 
> The shared SpacemiT code is limited to common register definitions and
> the CCI-550 helper. K1 retains its topology, boot flow and HSM behavior.
> 
> I tested this on a K3 COM260 with Linux v7.3-rc1 and only the v5 CPU PLL
> rate table patch [1] applied, using the unmodified upstream

CPU PLL rate table patch is now released in Linux 7.3-rc6 and did not
yet get picked up for Linux stable patch releases as of 7.2.9

> k3-com260-ifx.dtb and a minimal initramfs. The board booted from SPI NOR
> using the public SDK FSBL and U-Boot, with OpenSBI installed as a
> separate FIT using the procedure below.

There is now a related group of patch series in review at the U-Boot
mailing list adding support for U-Boot main app on K3 Pico-ITX, and
dependent on this K3 support series in OpenSBI 'fw_dynamic.bin'
integrated to the 'u-boot.itb' FIT image. Work on extending upstream
U-Boot support for K3 to SPL for DDR initialization is expected soon
after that is merged. All testing for mainline U-Boot is with this
OpenSBI K3 platform support series.

> 
> OpenSBI used the SDK's 16-hart DT and booted on hart 0. Linux brought up
> the eight X100 harts described by its DT and reached a shell. I did not
> reproduce the hang Valentin reported with Linux 7.2 and an eight-CPU
> kernel DT [2].
> 
> Build-tested with RV64 generic (CONFIG_STACK_PROTECTOR_ALL) and RV32
> generic. SpacemiT platform objects are excluded from RV32 builds.
> 
> Firmware installation
> ---------------------
> 
> The following NOR installation steps use the public K3 SDK v1.0.7:
> 
>   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 SDK is used to build the boot firmware; the Linux kernel and root
> filesystem are built separately. The commands below assume the SDK is
> configured for K3, with its host toolchain available in output/k3/host.
> 
> 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

FYI one-liner for modifying the vendor fork of u-boot v2022.10 as
described above:

sed -i 's%compatible = "ns16550";%compatible = "spacemit,k1-uart",
"intel,xscale-uart", "ns16550";%' u-boot.git/arch/riscv/dts/k3.dtsi
git -C u-boot.git add arch/riscv/dts/k3.dtsi
git -C u-boot.git commit --no-edit -m 'dts: riscv: spacemit: k3 uart
compatible with mainline opensbi'

I did suggest the change to be included by the vendor as a pull request:

https://github.com/spacemit-com/uboot-2022.10/pull/5

However I do not expect this to be considered, as the vendor uses their
own fork of OpenSBI.

> stops serial output. Rebuild 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/output/k3" uboot-rebuild
> 
> This produces the following files under output/k3/images:
> 
>   FSBL.bin
>   bootinfo_spinor.bin
>   u-boot.itb
> 
> From the OpenSBI source directory, build with the SDK toolchain at the
> address used by the SDK, then wrap fw_dynamic.bin in the SDK's standalone
> OpenSBI FIT:
> 
>   SDK_CROSS_COMPILE="$K3_SDK_DIR/output/k3/host/bin/riscv64-unknown-linux-gnu-"
>   make -j24 O=build-k3 CROSS_COMPILE="$SDK_CROSS_COMPILE" \
>        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
> 
> An existing system can be kept when updating the boot firmware. Flashing
> the full Bianbu Minimal system image is only needed for a board without
> a usable system.

Although I was unable boot a Linux userland from vendor 'FSBL.bin' plus
the mainline in-development 'u-boot.itb' the Linux kernel appears mostly
functional and does output some messages up to the point of 'init'.
There is no dependency on any SPI NOR flash content at all, it can be
fully erased and the 'esos' 'FSBL' 'opensbi' 'uboot' NOR flash regions
are not involved in testing when loading in-development for mainline
U-Boot (including mainline OpenSBI fw_dynamic.bin) 'u-boot.itb' and
whatever SPL (currently the vendor SDK/BSP 'FSBL.bin' SPL) is required
by that.

> 
> Link: https://lore.kernel.org/all/20260907-k3-pll5-pll8-1800mhz-v5-1-5cc96d716b0a@linux.spacemit.com/ [1]
> Link: https://lore.kernel.org/all/CAPEPrSMsnbuPOUuvj06+PtczdokK42vSpy8n_0hCLh0cEO-QkQ@mail.gmail.com/ [2]
> 
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
> Changes in v4:
> - use per-hart scratch for the expected-trap handler, avoiding accessor
>   calls and their stack-protector instrumentation; initialize it before
>   platform hooks and preserve scratch allocation alignment
> - include Valentin Haudiquet's hart-0-only cold-boot restriction as a
>   separate patch after K3 platform support
> - update the cover letter's test environment, results, and support scope
> - Link to v3: https://patch.msgid.link/20260827-spacemit-k3-v3-0-5d8dbb68539d@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
> 
> Valentin Haudiquet (1):
>       platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only
> 
> 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                       |   5 +-
>  include/sbi/sbi_scratch.h                    |   7 +-
>  lib/sbi/sbi_hart.c                           |   8 --
>  lib/sbi/sbi_illegal_atomic.c                 |   4 +-
>  lib/sbi/sbi_init.c                           |   7 ++
>  lib/sbi/sbi_scratch.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               | 128 +++++++++++++++++++++++++++
>  platform/generic/spacemit/k3_asm.S           |  52 +++++++++++
>  platform/generic/spacemit/objects.mk         |   5 ++
>  platform/generic/spacemit/spacemit.c         |  36 ++++++++
>  21 files changed, 638 insertions(+), 153 deletions(-)
> ---
> base-commit: c0f87f10d1bfb9e72a84ddfafb5604ee1bfe9d04
> change-id: 20260723-spacemit-k3-84720a7be53d
> 
> Best regards,
> --  
> Troy Mitchell <troy.mitchell@linux.spacemit.com>
> 
> 

I did read through all the patches in this series for any obvious style
problems. For the series with no endorsement of suitability for what the
code does or how it does so, okay to apply my R-by tag (and/or
Tested-by) and with or without any trivial style corrections as requested.

Hopefully this series will land soon in the tree.

Thanks for your work on this,

- E Shattow

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

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

* Re: [PATCH v4 1/6] lib: sbi: select expected trap handler per hart
  2026-09-10 14:00 ` [PATCH v4 1/6] lib: sbi: select expected trap handler per hart Troy Mitchell
@ 2026-10-08  0:29   ` E Shattow
  0 siblings, 0 replies; 14+ messages in thread
From: E Shattow @ 2026-10-08  0:29 UTC (permalink / raw)
  To: Troy Mitchell, opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang, Alvin Chang

On 9/10/26 07:00, 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 each hart's MISA at entry to sbi_init(), before
> platform hooks can probe CSRs, and store its address in that hart's
> scratch space. Load the address directly at each use. This avoids an
> accessor call and its stack-protector instrumentation in the CSR probing
> and unprivileged memory access paths.
> 
> Align scratch allocations after the enlarged fixed scratch area so that
> the new field preserves the allocator's cache-line alignment guarantee.
> 
> 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>
> Link: https://lore.kernel.org/r/20260831022156.2060561-1-alvinga@andestech.com
> Cc: Alvin Chang <alvinga@andestech.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  include/sbi/sbi_csr_detect.h | 4 ++--
>  include/sbi/sbi_hart.h       | 5 ++++-
>  include/sbi/sbi_scratch.h    | 7 ++++++-
>  lib/sbi/sbi_hart.c           | 8 --------
>  lib/sbi/sbi_illegal_atomic.c | 4 ++--
>  lib/sbi/sbi_init.c           | 7 +++++++
>  lib/sbi/sbi_scratch.c        | 4 ++++
>  lib/sbi/sbi_unpriv.c         | 6 +++---
>  8 files changed, 28 insertions(+), 17 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..f0a4be61 100644
> --- a/include/sbi/sbi_hart.h
> +++ b/include/sbi/sbi_hart.h
> @@ -12,6 +12,7 @@
>  
>  #include <sbi/sbi_types.h>
>  #include <sbi/sbi_bitops.h>
> +#include <sbi/sbi_scratch.h>
>  
>  /** Possible privileged specification versions of a hart */
>  enum sbi_hart_priv_versions {
> @@ -135,7 +136,9 @@ 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);
> +/* Keep the load free of function calls, including stack-protector code. */
> +#define sbi_hart_expected_trap_addr() \
> +	(sbi_scratch_thishart_ptr()->expected_trap)
>  
>  unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch);
>  void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
> diff --git a/include/sbi/sbi_scratch.h b/include/sbi/sbi_scratch.h
> index 06097c8a..20e7dcd0 100644
> --- a/include/sbi/sbi_scratch.h
> +++ b/include/sbi/sbi_scratch.h
> @@ -46,8 +46,10 @@
>  #define SBI_SCRATCH_OPTIONS_OFFSET		(14 * __SIZEOF_POINTER__)
>  /** Offset of hartindex member in sbi_scratch */
>  #define SBI_SCRATCH_HARTINDEX_OFFSET		(15 * __SIZEOF_POINTER__)
> +/** Offset of expected_trap member in sbi_scratch */
> +#define SBI_SCRATCH_EXPECTED_TRAP_OFFSET		(16 * __SIZEOF_POINTER__)
>  /** Offset of extra space in sbi_scratch */
> -#define SBI_SCRATCH_EXTRA_SPACE_OFFSET		(16 * __SIZEOF_POINTER__)
> +#define SBI_SCRATCH_EXTRA_SPACE_OFFSET		(17 * __SIZEOF_POINTER__)
>  /** Maximum size of sbi_scratch (4KB) */
>  #define SBI_SCRATCH_SIZE			(0x1000)
>  
> @@ -91,6 +93,8 @@ struct sbi_scratch {
>  	unsigned long options;
>  	/** Index of the hart */
>  	unsigned long hartindex;
> +	/** Address of the expected trap handler for this HART */
> +	unsigned long expected_trap;
>  };
>  
>  /**
> @@ -113,6 +117,7 @@ assert_member_offset(struct sbi_scratch, tmp0, SBI_SCRATCH_TMP0_OFFSET);
>  assert_member_offset(struct sbi_scratch, tmp1, SBI_SCRATCH_TMP1_OFFSET);
>  assert_member_offset(struct sbi_scratch, options, SBI_SCRATCH_OPTIONS_OFFSET);
>  assert_member_offset(struct sbi_scratch, hartindex, SBI_SCRATCH_HARTINDEX_OFFSET);
> +assert_member_offset(struct sbi_scratch, expected_trap, SBI_SCRATCH_EXPECTED_TRAP_OFFSET);
>  
>  /** Possible options for OpenSBI library */
>  enum sbi_scratch_options {
> diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
> index bee88557..61c5f945 100644
> --- a/lib/sbi/sbi_hart.c
> +++ b/lib/sbi/sbi_hart.c
> @@ -22,11 +22,6 @@
>  #include <sbi/sbi_string.h>
>  #include <sbi/sbi_trap.h>
>  
> -extern void __sbi_expected_trap(void);
> -extern void __sbi_expected_trap_hext(void);
> -
> -void (*sbi_hart_expected_trap)(void) = &__sbi_expected_trap;
> -
>  unsigned long hart_features_offset;
>  
>  static void mstatus_init(struct sbi_scratch *scratch)
> @@ -712,9 +707,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_init.c b/lib/sbi/sbi_init.c
> index 9bb1a37e..76b4fd91 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -36,6 +36,9 @@
>  #include <sbi/sbi_version.h>
>  #include <sbi/sbi_unit_test.h>
>  
> +extern void __sbi_expected_trap(void);
> +extern void __sbi_expected_trap_hext(void);
> +
>  #define BANNER                                              \
>  	"   ____                    _____ ____ _____\n"     \
>  	"  / __ \\                  / ____|  _ \\_   _|\n"  \
> @@ -585,6 +588,10 @@ void __noreturn sbi_init(struct sbi_scratch *scratch)
>  	u32 hartid			= current_hartid();
>  	const struct sbi_platform *plat = sbi_platform_ptr(scratch);
>  
> +	/* Platform hooks may probe CSRs before sbi_hart_init(). */
> +	scratch->expected_trap = misa_extension('H') ?
> +		(ulong)&__sbi_expected_trap_hext : (ulong)&__sbi_expected_trap;
> +
>  	switch (scratch->next_mode) {
>  	case PRV_M:
>  		next_mode_supported = true;
> diff --git a/lib/sbi/sbi_scratch.c b/lib/sbi/sbi_scratch.c
> index bb14a1a2..88ef1547 100644
> --- a/lib/sbi/sbi_scratch.c
> +++ b/lib/sbi/sbi_scratch.c
> @@ -97,6 +97,10 @@ unsigned long sbi_scratch_alloc_offset(unsigned long size)
>  
>  	spin_lock(&extra_lock);
>  
> +	/* The fixed scratch fields need not end on a cache-line boundary. */
> +	extra_offset = (extra_offset + scratch_alloc_align - 1) &
> +		       ~(scratch_alloc_align - 1);
> +
>  	if (SBI_SCRATCH_SIZE < (extra_offset + size))
>  		goto done;
>  
> 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;
> 

Tested-by: E Shattow <e@freeshell.de>

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

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

* Re: [PATCH v4 4/6] platform: generic: spacemit: k1: refactor platform support
  2026-09-10 14:00 ` [PATCH v4 4/6] platform: generic: spacemit: k1: refactor platform support Troy Mitchell
@ 2026-10-08  0:30   ` E Shattow
  0 siblings, 0 replies; 14+ messages in thread
From: E Shattow @ 2026-10-08  0:30 UTC (permalink / raw)
  To: Troy Mitchell, opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang

On 9/10/26 07:00, Troy Mitchell wrote:
> 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)
> +		;
> +}
> 

Tested-by: E Shattow <e@freeshell.de>

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

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

* Re: [PATCH v4 5/6] platform: generic: spacemit: k3: add platform support
  2026-09-10 14:00 ` [PATCH v4 5/6] platform: generic: spacemit: k3: add " Troy Mitchell
@ 2026-10-08  0:30   ` E Shattow
  0 siblings, 0 replies; 14+ messages in thread
From: E Shattow @ 2026-10-08  0:30 UTC (permalink / raw)
  To: Troy Mitchell, opensbi
  Cc: Xianbin Zhu, Anup Patel, Bo Gan, Samuel Holland,
	Heinrich Schuchardt, Kevin Zhang

On 9/10/26 07:00, Troy Mitchell wrote:
> 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.
> 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
> 

Tested-by: E Shattow <e@freeshell.de>

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

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

end of thread, other threads:[~2026-10-08  0:30 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-10 14:00 [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support Troy Mitchell
2026-09-10 14:00 ` [PATCH v4 1/6] lib: sbi: select expected trap handler per hart Troy Mitchell
2026-10-08  0:29   ` E Shattow
2026-09-10 14:00 ` [PATCH v4 2/6] platform: generic: spacemit: k1: rename cache flush operation Troy Mitchell
2026-10-07 21:20   ` E Shattow
2026-09-10 14:00 ` [PATCH v4 3/6] platform: generic: spacemit: k1: move hart init to nascent hook Troy Mitchell
2026-10-07 21:14   ` E Shattow
2026-09-10 14:00 ` [PATCH v4 4/6] platform: generic: spacemit: k1: refactor platform support Troy Mitchell
2026-10-08  0:30   ` E Shattow
2026-09-10 14:00 ` [PATCH v4 5/6] platform: generic: spacemit: k3: add " Troy Mitchell
2026-10-08  0:30   ` E Shattow
2026-09-10 14:00 ` [PATCH v4 6/6] platform: generic: spacemit: k3: override cold_boot_allowed for hart 0 only Troy Mitchell
2026-10-07 20:58   ` E Shattow
2026-10-08  0:28 ` [PATCH v4 0/6] platform: generic: spacemit: add K3 platform support E Shattow

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