docs: ASCII typography and style normalization across all repo text
Replace every em dash with real punctuation (rewrites, not hyphen swaps) in docs, code comments, scripts, configs, and the port records; convert en dashes, curly quotes, ellipsis glyphs, arrows, and section signs to ASCII; drop machine-writing tell phrases from living docs. ADR titles now use a colon. The M2 bring-up DTS model string carried an em dash into the patch series and its record echoes; fixed at both, and the full series re-verified to apply cleanly onto pristine 6.18.46. One comment in freshness.h deliberately names the em dash glyph the UI renders as the unknown mark; that is data, kept as prose naming it. Verified: cargo tests (sim, config-lint, rs485-bridge), shellcheck, both driver MC/DC harnesses, patches-apply.
This commit is contained in:
+19
-19
@@ -1,4 +1,4 @@
|
||||
# RV1106 → Linux 6.18 forward-port (self-built, from vendor 5.10)
|
||||
# RV1106 -> Linux 6.18 forward-port (self-built, from vendor 5.10)
|
||||
|
||||
**Decision (2026-08-23):** forward-port the RV1106 SoC enablement from the
|
||||
Rockchip **vendor 5.10** tree straight to **Linux 6.18 LTS**, ourselves, using **no
|
||||
@@ -6,7 +6,7 @@ plan44 code**, built on **our Buildroot 2025.02 LTS + uClibc**. We own the tree.
|
||||
|
||||
## The reality this rests on (verified, not assumed)
|
||||
|
||||
Vanilla mainline (6.6.93 and 6.18) has **zero** RV1106 support — no devicetree, no
|
||||
Vanilla mainline (6.6.93 and 6.18) has **zero** RV1106 support: no devicetree, no
|
||||
clock driver, no pinctrl data, not one `rv1106` reference in `arch/arm` or
|
||||
`drivers/`. So "the newest kernel" is a generic ARM kernel that cannot boot this
|
||||
SoC. What we forward-port is the **entire RV1106 BSP**: ~120 files in the vendor
|
||||
@@ -16,48 +16,48 @@ it is delivered incrementally, console-first.
|
||||
|
||||
## Method (how each piece is ported)
|
||||
|
||||
- **Framework drivers → sibling-delta.** clk and pinctrl are driven by the shared
|
||||
- **Framework drivers -> sibling-delta.** clk and pinctrl are driven by the shared
|
||||
rockchip framework (`drivers/clk/rockchip/clk.c`, `pinctrl-rockchip.c`). RV1106's
|
||||
siblings **rv1126 and rv1108 exist in BOTH vendor-5.10 and mainline-6.18**, so
|
||||
their 5.10→6.18 delta is the exact recipe for how the framework API changed —
|
||||
we apply that recipe to rv1106's data (`clk-rv1106.c` = 1284 lines;
|
||||
their 5.10->6.18 delta is the exact recipe for how the framework API changed.
|
||||
We apply that recipe to rv1106's data (`clk-rv1106.c` = 1284 lines;
|
||||
`rv1106-cru.h` clock IDs; the rv1106 pinctrl table). This turns "adapt to APIs
|
||||
we have to guess" into "copy a diff a sibling already proves."
|
||||
- **SoC-unique code → forward-port + build-fix-build.** `mach-rockchip`
|
||||
- **SoC-unique code -> forward-port + build-fix-build.** `mach-rockchip`
|
||||
(machine, `rockchip_hptimer`, `rv1106_pm`/`rv1106_sleep.S`), the CRU/GRF glue,
|
||||
and the board DT have no sibling; port directly and iterate on the 6.18 build.
|
||||
- **Mainline-present drivers → just wire DT + clocks.** 8250-dw UART, dw_mmc
|
||||
- **Mainline-present drivers -> just wire DT + clocks.** 8250-dw UART, dw_mmc
|
||||
(SDIO/eMMC), dw-apb i2c, rockchip gpio/pinctrl core, pwm, dw-wdt watchdog are all
|
||||
in mainline 6.18 — we do **not** port them, we supply the DT nodes + clock/reset
|
||||
in mainline 6.18. We do **not** port them, we supply the DT nodes + clock/reset
|
||||
phandles and let the mainline drivers bind.
|
||||
- **Out-of-tree drivers → port the driver.** AIC8800 wifi (plan44 has none; ours),
|
||||
RGA/MPP kernel bits (assess vs need — the 86-Panel has no camera), carrying our
|
||||
- **Out-of-tree drivers -> port the driver.** AIC8800 wifi (plan44 has none; ours),
|
||||
RGA/MPP kernel bits (assess vs need: the 86-Panel has no camera), carrying our
|
||||
Tier-1 SDIO-wakeup fix forward.
|
||||
- **Our 4 kernel patches** (panel-mcu-reset/logo, watchdog-enable, usb-otg
|
||||
dual-role, recovery-splash) → re-apply against 6.18 (line offsets + some DT
|
||||
dual-role, recovery-splash) -> re-apply against 6.18 (line offsets + some DT
|
||||
bindings changed).
|
||||
|
||||
## Bring-up milestones (console-first order)
|
||||
|
||||
- **M0 — buildable base.** 6.18.46 tree + our Buildroot/uClibc toolchain builds a
|
||||
- **M0: buildable base.** 6.18.46 tree + our Buildroot/uClibc toolchain builds a
|
||||
generic ARM kernel; a `rv1106_defconfig` forward-ported from vendor 5.10.
|
||||
- **M1 — SoC compiles.** `mach-rockchip` RV1106 select + `clk-rv1106` +
|
||||
- **M1: SoC compiles.** `mach-rockchip` RV1106 select + `clk-rv1106` +
|
||||
rv1106 pinctrl data + `rv1106-cru.h` compile clean against 6.18 (no boot yet).
|
||||
- **M2 — earlycon boot.** DT (`rv1106.dtsi` core) + clk + pinctrl + 8250-dw →
|
||||
- **M2: earlycon boot.** DT (`rv1106.dtsi` core) + clk + pinctrl + 8250-dw ->
|
||||
kernel prints to the RV1106 UART. The first "it's alive."
|
||||
- **M3 — rootfs boot.** dw_mmc + DT → eMMC/SD rootfs, userspace up on our Buildroot.
|
||||
- **M4 — display.** VOP2 + the RGB666 720×720 panel + GT911 touch + PWM backlight →
|
||||
- **M3: rootfs boot.** dw_mmc + DT -> eMMC/SD rootfs, userspace up on our Buildroot.
|
||||
- **M4: display.** VOP2 + the RGB666 720x720 panel + GT911 touch + PWM backlight ->
|
||||
the LVGL UI renders.
|
||||
- **M5 — wifi + our patches.** AIC8800 SDIO driver ported (+ Tier-1 fix); the 4
|
||||
- **M5: wifi + our patches.** AIC8800 SDIO driver ported (+ Tier-1 fix); the 4
|
||||
custom kernel patches re-applied.
|
||||
- **M6 — the rest.** RGA (UI accel), watchdog, HPMCU coprocessor, USB-OTG dual role.
|
||||
- **M6: the rest.** RGA (UI accel), watchdog, HPMCU coprocessor, USB-OTG dual role.
|
||||
|
||||
## Regression (so a 6.18 port doesn't reintroduce the struct-ABI bug class)
|
||||
|
||||
The warden-sdk simulator + MC/DC harness are how we hold the line: `HpmcuSim` and
|
||||
the register/`MemBus` seam test the supervisor/reset logic off the ported kernel;
|
||||
the `relays-mcdc` pattern extends to each ported driver we own; and a
|
||||
**config-lint CI gate** (the class that bricked c8a3 — a load address in unreserved
|
||||
**config-lint CI gate** (the class that bricked c8a3: a load address in unreserved
|
||||
kernel RAM) checks the DT reservations against the drivers on every build.
|
||||
|
||||
## Layout (this repo)
|
||||
|
||||
@@ -3,39 +3,39 @@
|
||||
Booting the self-built 6.18 kernel on real hardware (warden-c8a3), 2026-08-24.
|
||||
The build side (zImage + dtb) is in `../rv1106-enablement/`; this is the on-target
|
||||
half. **The safe-test framework and the boot-image format below are the reusable
|
||||
findings — they worked on the first hardware try.**
|
||||
findings: they worked on the first hardware try.**
|
||||
|
||||
## The safe test path (A/B slot _b, never touch _a)
|
||||
|
||||
c8a3 is the desk-connected bench Warden: reachable over its USB-gadget ethernet
|
||||
(dev-build dropbear; address and bench credentials live in the private
|
||||
deployment notes — use `scp -O`, no sftp-server), plus the serial console at
|
||||
deployment notes: use `scp -O`, no sftp-server), plus the serial console at
|
||||
115200 and remotely switchable power. It runs an A/B
|
||||
firmware (boot_a=mmcblk0p5 / boot_b=mmcblk0p6, 32 MiB each; rootfs_a/_b; AvbABData
|
||||
in `misc` sector 4 / byte 2048).
|
||||
|
||||
The test never risks the working system:
|
||||
1. Back up `boot_b` (`dd .../by-name/boot_b -> /userdata/boot_b.bak`).
|
||||
2. Write the test `boot.img` to **boot_b only** — `_a` (the shipped WardenOS) is
|
||||
2. Write the test `boot.img` to **boot_b only**. `_a` (the shipped WardenOS) is
|
||||
untouched.
|
||||
3. Flip AvbABData to a **one-shot _b**: `craft_ab.py 14 0 1 15 1 0 1` → A(prio14,
|
||||
3. Flip AvbABData to a **one-shot _b**: `craft_ab.py 14 0 1 15 1 0 1` -> A(prio14,
|
||||
tries0,ok1) B(prio15,tries1,ok0); write to `misc` sector 4. U-Boot's SPL then
|
||||
picks _b once, decrements tries→0, and boots it.
|
||||
picks _b once, decrements tries->0, and boots it.
|
||||
4. If the test kernel fails/hangs, U-Boot auto-reverts to `_a` (SPL: "slot boot
|
||||
failed, resetting" → next boot `A/B-slot: _a, successful: 1`). A hung kernel
|
||||
failed, resetting" -> next boot `A/B-slot: _a, successful: 1`). A hung kernel
|
||||
just needs a Zigbee power-cycle; `_a` boots WardenOS back. **Zero manual
|
||||
recovery needed — verified across three failed attempts.**
|
||||
recovery needed: verified across three failed attempts.**
|
||||
|
||||
`earlycon=uart8250,mmio32,0xff4c0000` is confirmed correct: it is in the live
|
||||
5.10 cmdline, and U-Boot's own DDR probe reports `Adding bank: 0x0 - 0x10000000`
|
||||
(256 MiB) — so the M2 DT's memory node and earlycon are right.
|
||||
(256 MiB), so the M2 DT's memory node and earlycon are right.
|
||||
|
||||
## The boot-image format (this was the whole fight)
|
||||
|
||||
rockchip U-Boot (this build) needs a very specific `boot.img`, NOT a plain FIT:
|
||||
|
||||
- **External-data FIT.** `mkimage -f its -E -p 0x800`. The FDT metadata stays tiny
|
||||
(totalsize ≈ 1536 B, matching boot_a); the kernel/fdt/resource **data is
|
||||
(totalsize ~ 1536 B, matching boot_a); the kernel/fdt/resource **data is
|
||||
appended** after it. A normal embedded-data FIT (totalsize = whole image) is
|
||||
rejected with `FIT: No fit blob` / `No FIT image`.
|
||||
- **A `resource` (multi) sub-image is mandatory.** rockchip reads the DTB via the
|
||||
@@ -43,62 +43,62 @@ rockchip U-Boot (this build) needs a very specific `boot.img`, NOT a plain FIT:
|
||||
with `resource_tool --pack`. Without it: `Failed to load DTB, ret=-19`.
|
||||
- **Sysmem sentinel load addresses.** fdt `load=0xffffff00`, kernel
|
||||
`load=entry=0xffffff01`; U-Boot's sysmem places them (it chose kernel@0x8000,
|
||||
fdt@0xc00000). Real low addresses collided → "No fit blob".
|
||||
fdt@0xc00000). Real low addresses collided -> "No fit blob".
|
||||
- `CONFIG_FIT_SIGNATURE` is **off** in this U-Boot, so the image need not be
|
||||
signed. Template: `sdk/sysdrv/source/kernel/boot.its`; builder recipe:
|
||||
`sdk/project/scripts/mk-fitimage.sh` (`mkimage -E -p 0x800`).
|
||||
|
||||
With the correct format, U-Boot loaded my kernel + my DTB and printed my DT model
|
||||
string (`Model: WardenOS 86-Panel (RV1106) — M2 earlycon bring-up`), then
|
||||
string (`Model: WardenOS 86-Panel (RV1106), M2 earlycon bring-up`), then
|
||||
`Starting kernel ...`.
|
||||
|
||||
## Result: [x] M2 achieved — the 6.18 kernel boots on hardware
|
||||
## Result: [x] M2 achieved, the 6.18 kernel boots on hardware
|
||||
|
||||
Six attempts, each auto-recovering to `_a`, then a clean boot:
|
||||
|
||||
```
|
||||
[0.000000] Linux version 6.18.46 … #2 SMP
|
||||
[0.000000] Linux version 6.18.46 ... #2 SMP
|
||||
[0.000000] CPU: ARMv7 Processor [410fc075]
|
||||
[0.000000] OF: fdt: Machine model: WardenOS 86-Panel (RV1106) — M2 earlycon bring-up
|
||||
[0.000000] OF: fdt: Machine model: WardenOS 86-Panel (RV1106), M2 earlycon bring-up
|
||||
[0.000000] earlycon: uart8250 at MMIO32 0xff4c0000
|
||||
[0.000000] cma: Reserved 64 MiB at 0x0c000000
|
||||
[0.040693] Calibrating delay loop … 48.00 BogoMIPS ← arch timer up
|
||||
[0.040693] Calibrating delay loop ... 48.00 BogoMIPS <- arch timer up
|
||||
[0.343810] pinctrl core: initialized pinctrl subsystem
|
||||
[1.968703] ff4c0000.serial: ttyS2 … is a 16550A ← 8250 on our CRU clock
|
||||
[1.968703] ff4c0000.serial: ttyS2 ... is a 16550A <- 8250 on our CRU clock
|
||||
```
|
||||
|
||||
Two more bugs, found via the DEBUG_LL rebuild (`DEBUG_LL_UART_8250`, PHYS
|
||||
0xff4c0000, shift 2, 32-bit word + `earlyprintk` — the decompressor prints
|
||||
0xff4c0000, shift 2, 32-bit word + `earlyprintk`, the decompressor prints
|
||||
pre-MMU), then fixed:
|
||||
|
||||
- **DTB overrun → `r2=0` / `invalid dtb`.** The multi_v7 zImage decompresses to
|
||||
- **DTB overrun -> `r2=0` / `invalid dtb`.** The multi_v7 zImage decompresses to
|
||||
~20 MiB from 0x8000, overrunning the DTB at 0xc00000, so the decompressor handed
|
||||
the kernel a null DTB pointer. Fix: place the fdt high — `load=0x08000000` in the
|
||||
the kernel a null DTB pointer. Fix: place the fdt high (`load=0x08000000`) in the
|
||||
FIT `.its` (see `boot5.its`). The real fix is a lean defconfig; multi_v7 is bloat.
|
||||
- **`grf_ctx` NULL deref in clk-rv1106.** `rockchip_clk_register_branches(grf_ctx,…)`
|
||||
- **`grf_ctx` NULL deref in clk-rv1106.** `rockchip_clk_register_branches(grf_ctx,...)`
|
||||
crashed because the minimal DT had no `rockchip,rv1106-grf-cru` node to set
|
||||
`grf_ctx`. Fix: add the `grf-clock-controller` child to the grf syscon (now in
|
||||
`dts/rv1106-warden-m2.dts`).
|
||||
|
||||
**Console baud gotcha:** `console=ttyS2,115200`. earlycon is readable at 115200
|
||||
(U-Boot leaves uart2 there), but the vendor's 1.5M console rate is garbage on the
|
||||
CP2102 bench adapter — so the M2 DT pins 115200 for readable bring-up; production
|
||||
CP2102 bench adapter, so the M2 DT pins 115200 for readable bring-up; production
|
||||
overrides to 1.5M.
|
||||
|
||||
## M3 (same session): [x] the full WardenOS runs on the 6.18 kernel
|
||||
|
||||
Adding the eMMC `dw_mmc` node (`mmc@ffa90000`, clocks from cru + grf_cru) was the
|
||||
only change M3 needed — the mmc/ext4 drivers are already in-config. The kernel
|
||||
only change M3 needed: the mmc/ext4 drivers are already in-config. The kernel
|
||||
enumerated the eMMC at HS200, mounted the ext4 rootfs, ran `/sbin/init`, and
|
||||
started every WardenOS daemon. A serial root login confirms `uname -a` →
|
||||
started every WardenOS daemon. A serial root login confirms `uname -a` ->
|
||||
`Linux warden-c8a3 6.18.46 armv7l`, with `warden-flared/-modbus/-mikrotik/-asic/
|
||||
-ui/-flight` all running. Expected M4/M5 gaps show cleanly: the 5.10 aic8800 `.ko`
|
||||
won't load (vermagic → M5), and there's no backlight/framebuffer yet (→ M4).
|
||||
won't load (vermagic -> M5), and there's no backlight/framebuffer yet (-> M4).
|
||||
|
||||
**Console lesson applied:** with `console=ttyS2,115200` the whole boot is readable
|
||||
on the CP2102 (the 1.5M vendor rate is garbage on it). Serial login uses the same
|
||||
`c8a3_run.py` helper (dev-build bench credentials, see private deployment notes)
|
||||
as the 5.10 firmware — the userspace is unchanged.
|
||||
as the 5.10 firmware: the userspace is unchanged.
|
||||
|
||||
Next: M4 (VOP2 display + panel + touch), M5 (AIC8800 SDIO port + our 4 patches),
|
||||
M6 (RGA/watchdog/HPMCU/USB-OTG); plus a lean defconfig + Buildroot-on-6.18 cleanup.
|
||||
|
||||
Reference in New Issue
Block a user