CPU0 start/stop binding decision for the mainline kernel (task 1.2)
Evidence class: source and document reading, 2026-10-12. No board, no
build, no code. Supersedes the vendor-tree binding text that
openspec/changes/the-small-core-runs-as-a-coprocessor/design.md and its
spec delta originally carried. Those cited the vendor 6.6 tree’s
canaan,k230-sysctl-reset node and K230_RESET_* macros; the daily kernel is
mainline v7.3-rc5 (nix/kernel-mainline-src.nix:30, rev
72d3fcf802c4...; nix/kernel-mainline.nix:153 version 7.3.0-rc5;
nix/kernel-mainline-drm.nix:54-56 adds the patched
linux-mainline-k230-drm-src), and none of the vendor names exist there. All
mainline citations below are in that patched source tree
(/nix/store/4jrzy64mg619y75lgrlihz78darglas6-linux-mainline-k230-drm-src),
relative paths shown.
Decision
- Consumer binding:
resets = <&rst RST_CPU0>;with#include <dt-bindings/reset/canaan,k230-rst.h>. The controller isrst: reset-controller@91101000,compatible = "canaan,k230-rst",#reset-cells = <1>(arch/riscv/boot/dts/canaan/k230.dtsi:92-96; schemaDocumentation/devicetree/bindings/reset/canaan,k230-rst.yamlrequires exactly one cell).RST_CPU0 = 0,RST_CPU1 = 1(include/dt-bindings/reset/canaan,k230-rst.h:9-10). The vendor four-cell<&sysctl_reset 0x4 0 12 0>form is not valid on mainline. - Only
.resetworks for CPU0.RST_CPU0is{ 0x4, RST_TYPE_CPU0, BIT(12), BIT(0) }(drivers/reset/reset-k230.c:74).k230_rst_assertandk230_rst_deassertreturn-EOPNOTSUPPforRST_TYPE_CPU0(:225-228,:256-259).k230_rst_resetis the only CPU0 path: clear the done bit, set the reset request, wait for done, delay 10 us (:280-290); the ops table registers.reset,.assert,.deassert(:326-330). The consumer therefore callsreset_control_reset(). This is a pulse, not a hold/release pair. - Start = vector write, then
reset_control_reset(). The vector goes to0x91102100first (the pinnedboot_baremetal 0order,arch/riscv/cpu/k230/cpu.c:125-160in the vendor U-Boot overlay), then the pulse starts CPU0 at it. The register is not named in any mainline binding. - Stop is not available through the reset framework, and the hardware
offers no hold bit.
reset_control_assert()onRST_CPU0fails with-EOPNOTSUPP. The TRM’sCPU0_RST_CTL(RMU offset0x4, i.e.0x91101004) bit 0cpu0_reset_reqis access type W1T: “write-only and self-clear”, “1: request to reset cpu0 subsystem”; bit 12cpu0_rst_doneis W1C (TRM RMU register description, PDF page 16 of the downloaded file; see the feasibility note for the file hash). That explains why mainline implements only.reset: there is no level-held reset to assert. A clean stop therefore cannot come from a reset-driver patch alone. Candidates for task 5.2, not decided here: a firmware-cooperative stop (CPU0 firmware parks inwfion a request from Linux, and a later pulse restarts it); or the PWR block’s CPU0 power control (TRM section 2.3.4, not read for this note, with the NOC low-power handshake caveat in section 2.3.3). Do not have the remoteproc driver write0x91101004itself behind the reset driver. Task 5.2’s “assert only” wording is superseded accordingly. - The vector register gets a private mapping, not a syscon. The
sysclknode covers only0x91102000-0x9110203f(k230.dtsi:103-110,reg = <0x0 0x91102000 0x0 0x40>), so0x91102100is not claimed by any mainline driver or node. The reset driver maps0x91102060for its restart handler with a privatedevm_ioremap(reset-k230.c:337-338,:369-371;K230_SYSCTL_BOOT_BASE0x91102000 plusK230_CPU0_RST_CTL0x60, writtenBIT(0) | BIT(16)at:345), which is the precedent. The remoteproc node therefore carries its ownreg = <0x0 0x91102100 0x0 0x4>(disjoint from thesysclkwindow and from0x91102060) and the driver maps it withdevm_platform_ioremap_resource(). There is nosysctl_bootnode on mainline (the vendor tree hassysctl_boot@91102000, vendork230.dtsi:241-244). The width and side effects of the write are only whatboot_baremetalalready does, which this project observed work on 2026-10-12. - Hazard: never request
RST_CPU1.RST_CPU1 = 1is{ 0xc, RST_TYPE_CPU1, ... }(reset-k230.c:75) and resets the core Linux runs on (CPU1; see heartbeat-physical-2026-10-12/README.md and the stage-1 audit). The driver must hard-codeRST_CPU0in the binding and refuse any otherresetsindex. AlsoRST_CPU0_FLUSH(2) exists separately and is not needed. - Interaction with the restart handler. The same driver’s restart
path writes
sysctl_boot+0x60(:345), a different register fromCPU0_RST_CTLat0x91101004; a CPU0 pulse throughRST_CPU0is whatboot_baremetalalready does and is not the system-restart write.
Not yet in the kernel configuration
CONFIG_REMOTEPROC appears in none of the project’s mainline Nix kernel
inputs (grep -rn REMOTEPROC nix/ finds nothing), so a remoteproc driver
also needs that option, a Kconfig entry, and a DT node. No mailbox or
rproc driver exists for K230 in the tree (ls drivers/remoteproc has no
K230 file). Mailbox registers are recorded in
docs/research/second-core-feasibility.md (“TRM mailbox register map”).
What this note does not establish
- That a reset pulse on
RST_CPU0alone leaves CPU1/Linux undisturbed while Linux runs; that is task 5.3. - That the RMU “done” handshake in
k230_rst_resetcompletes with CPU0 running Linux-launched firmware (U-Boot’s version of the sequence was proven on the board; the Linux driver’s was not run). - The vendor-tree names remain correct for the vendor kernel
(
nix/kernel-src.nix) that the shipped image boots; this decision is for the mainline path the project is moving to.