sdk: bootstrap standalone repo (P0)

- Dual license (LICENSE / LICENSE-MIT / LICENSE-APACHE) matching the crate manifests.
- ADRs 0001-0005: kernel base (direct 5.10->6.18.46 forward-port), tiered MC/DC,
  standalone repo, CI runner (3rd repo-scoped runner on 0640), driver source-of-truth.
- README goal 1 reconciled to the verified 6.18.46 forward-port (was stale plan44/6.6).
- Drop tracked build objects (*.o now gitignored).
- Capture the display (VOP dclk-pol + WIN1) and GT911 touch bring-up VERIFIED docs
  + capabilities-audit update from this session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
This commit is contained in:
BFE Engineering
2026-08-25 13:46:08 -06:00
co-authored by Claude Opus 4.8
parent 19ff701deb
commit 189f7aec38
14 changed files with 547 additions and 15 deletions
+4
View File
@@ -3,6 +3,10 @@ target/
**/target/ **/target/
Cargo.lock Cargo.lock
# build artifacts (firmware/kernel objects are rebuilt from source)
*.o
*.a
# scratch / editor # scratch / editor
*.swp *.swp
*~ *~
+10
View File
@@ -0,0 +1,10 @@
warden-sdk is dual-licensed under either of
* Apache License, Version 2.0 (LICENSE-APACHE)
* MIT license (LICENSE-MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+39
View File
@@ -0,0 +1,39 @@
MIT License
Copyright (c) 2026 BlueFlare
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-------------------------------------------------------------------------------
Third-party components carry their own licenses, which are not superseded by
the above:
- LVGL (the UI library, fetched during build, not vendored here) is MIT
licensed by its authors.
- The Luckfox / Rockchip RV1106 SDK and its cross-toolchain are covered by
their respective vendor licenses.
- vendor/asic-rs is 256 Foundation's asic-rs, vendored into this repository
with git subtree and licensed under Apache-2.0. Its license text is kept
at vendor/asic-rs/LICENSE.txt. Files modified locally must carry a notice
saying so, per Apache-2.0 section 4(b); see vendor/README.md.
The contents of branding/ (BlueFlare logos, wordmarks, and splash artwork) are
NOT covered by the MIT license above. They are proprietary to BlueFlare, all
rights reserved, and are included only so the firmware builds and displays as
shipped. Do not reuse them in derivative works.
+10 -5
View File
@@ -29,11 +29,16 @@ without a panel in the loop**, and to move us onto a modern, maintained kernel.
## Goals (from future-features) ## Goals (from future-features)
1. **Modern kernel.** Move to the newest stable Linux we can run on our current 1. **Modern kernel.** A self-built **Linux 6.18.46**, forward-ported directly from
Buildroot LTS (2025.02.x). The realistic ceiling is **plan44's OpenWrt RV1106 the vendor 5.10.160 tree (no plan44/OpenWrt code) on our current Buildroot LTS
fork — Linux 6.6**, which carries 152 RV1106 patches and a devicetree for our (2025.02.x). This is **done and hardware-verified on `warden-c8a3`**: essentially
exact board. Mainline is not viable (no DT/clk/display/RGA/NPU/flash-boot). every RV1106 block the 86-Panel uses boots and works — clk, pinctrl, eMMC, GMAC,
This is a bounded, evidence-backed forward-port, not a mainline chase. TRNG, OTP, SARADC/TSADC, RTC, USB host, PWM/backlight, **VOP display**, **GT911
touch**, **AIC8800 wifi**, **RGA**, **I2S audio**, **HPMCU mailbox**, the **open
NPU driver**, and **PVTM**. Mainline was not viable (no DT/clk/display/RGA/NPU/
flash-boot upstream for RV1106); the direct 5.10→6.18 forward-port reuses the
already-in-mainline rv1126 register data where it matches and carries our deltas
as a reviewable patch series (`patches/`).
2. **Ported, hardened drivers → 100% MC/DC on the code we own.** "100% MC/DC on 2. **Ported, hardened drivers → 100% MC/DC on the code we own.** "100% MC/DC on
100% of drivers" is infeasible as literally stated: ~97% of driver LOC is 100% of drivers" is infeasible as literally stated: ~97% of driver LOC is
vendor blobs (the AIC8800 wifi driver alone is 88.5K lines). So the target is vendor blobs (the AIC8800 wifi driver alone is 88.5K lines). So the target is
+28
View File
@@ -0,0 +1,28 @@
# ADR 0001 — Kernel base: direct 5.10→6.18 forward-port
**Status:** Accepted (2026-08-25). Supersedes the README's original plan44/6.6 goal.
## Context
The vendor kernel is Rockchip 5.10.160 (via Luckfox). We want the newest stable
Linux runnable on our Buildroot LTS (2025.02.x). Two candidate paths existed:
(a) baseline on plan44's OpenWrt RV1106 fork (Linux 6.6, 152 RV1106 patches), or
(b) forward-port the vendor tree directly onto a chosen upstream stable.
## Decision
Forward-port **directly to Linux 6.18.46** from vendor 5.10.160, carrying **no
plan44/OpenWrt code**. Reuse the already-upstream **rv1126** register data where it
matches the RV1106 ("RV-series lite" VOP, clk, pinctrl), and carry the RV1106
deltas as a reviewable patch series in `patches/`.
## Consequences
- Done and **hardware-verified on `warden-c8a3`**: clk, pinctrl, eMMC, GMAC, TRNG,
OTP, SARADC/TSADC, RTC, USB host, PWM/backlight, VOP display, GT911 touch, AIC8800
wifi, RGA, I2S audio, HPMCU mailbox, open NPU driver, PVTM.
- **uClibc stays load-bearing** — RGA/MPP/ISP/NPU userspace ship as uClibc-only
blobs; a glibc swap breaks media (flare-edge #51, wontfix). Any kernel bump
inherits this.
- Kernel bumps risk struct-ABI breaks for out-of-tree modules (the AIC8800/VLAN
`struct net_device` offset saga). Mitigation: ship one matched full boot+oem
image, never a partial reflash.
- Deferred by design: crypto-v3 accelerator (CPU crypto already covers the need),
open NPU *compute* (a person-year register-RE effort, no RV1106 prior art).
+28
View File
@@ -0,0 +1,28 @@
# ADR 0002 — Tiered MC/DC coverage policy
**Status:** Accepted (2026-08-25).
## Context
The goal "port + harden 100% of drivers to 100% MC/DC" is infeasible as literally
stated: ~97% of driver LOC is vendor blobs (the AIC8800 wifi driver alone is 88.5K
lines) that we cannot meaningfully unit-test to MC/DC on the host. Forcing MC/DC on
that code would be theatre, not assurance.
## Decision
A **two-tier** policy, measured against the Hardware Abstraction Seam:
- **Tier 1 — our own hardware-facing code → real 100% MC/DC.** `modbus_engine.c`,
`relays.c`, `warden_rga.c` (wrapper), `hpmcu.rs`, `devmem.rs`, `freshness.c`, plus
the two smallest near-mainline drivers where feasible. Enforced in CI
(`gcc-14 -fcondition-coverage` + `gcov-14 --conditions`; `cargo-llvm-cov --mcdc`
for Rust).
- **Tier 2 — ported/vendor drivers → fault-injection + branch coverage + benchmarks**
against the simulator, behind a stable seam. Explicitly NOT literal MC/DC.
## Consequences
- Matches the user's framing: "as many drivers as possible at 100% MC/DC; for the
rest, a very serious testing and benchmarking system."
- The seam is the shared object: the same thing MC/DC is measured against and the
simulator implements — the two goals reinforce, not duplicate.
- Every Tier-1 file gets a `drivers/<name>-mcdc/` host harness with an
`enforce-mcdc.sh` that fails CI below 100%.
+20
View File
@@ -0,0 +1,20 @@
# ADR 0003 — warden-sdk is a standalone repo
**Status:** Accepted (2026-08-25).
## Context
Our real SDK changes lived as uncommitted edits in a 2GB opaque vendor fork, with
no CI, tests, or versioning of their own. The SDK requirement (future-features-2
§SDK) calls for "its own repo, held to firmware standards."
## Decision
A **private** `bfe-noah/warden-sdk` GitHub repo, standalone from day one with its own
CI/versioning. Work lands on a `bringup` branch; the first commit to `main` is gated
on a passing code-review-harness run, green CI, and [maintainer]'s fresh explicit go-ahead.
## Consequences
- flare-edge consumes warden-sdk later (flared depending on `warden-sim`, drivers
built from here) — a separate, [maintainer]-gated integration step; flare-edge is not
edited by the SDK-completion effort.
- Private for now (references bench devices / in-progress hardening); can be opened
later once scrubbed, matching how `flare-deployment` is handled.
+21
View File
@@ -0,0 +1,21 @@
# ADR 0004 — CI/CD runner: 3rd repo-scoped self-hosted runner on 0640
**Status:** Accepted (2026-08-25).
## Context
The heavy kernel/firmware build needs the SDK toolchain and Buildroot's baked-in
absolute paths — impractical on GitHub-hosted runners. flare-edge already builds on
a repo-scoped self-hosted runner on `bfe-mpc-0640` (label `flare-edge`); a repo-scoped
registration cannot be shared across repos by label alone.
## Decision
Register a **third repo-scoped runner instance** on `bfe-mpc-0640`, label
`warden-sdk` (own systemd unit `actions.runner.bfe-noah-warden-sdk.*`, own
`CPUQuota=400%`/`MemoryMax=6G` drop-in). Only the heavy `kernel-build` job uses
`runs-on: [self-hosted, warden-sdk]`; all host-testable jobs (tests, coverage, MC/DC,
benchmarks, badges, patches-apply) run on GitHub-hosted runners.
## Consequences
- Isolated from the flare backend + flare-edge CI already on that host (cgroup-capped).
- Runner setup + host build deps + the project-local `python` venv documented in
`docs/ci-cd.md`, mirroring flare-edge's.
@@ -0,0 +1,21 @@
# ADR 0005 — Hardened drivers live in warden-sdk/drivers/
**Status:** Accepted (2026-08-25).
## Context
Our own hardware-facing driver code (relays, modbus master, RGA wrapper, HPMCU
supervisor, devmem/reset ladder, freshness) is the Tier-1 MC/DC target, but it
currently lives in flare-edge. The kernel driver source lives in an un-versioned
scratch tree (`flare-edge/research/linux-6.18.46/`).
## Decision
Bring **hardened copies into `warden-sdk/drivers/`** as the canonical source-of-truth,
each with its HAL seam and a 100% MC/DC host harness. The RV1106 kernel deltas are
formalized as a patch series in `patches/`. flare-edge consumes warden-sdk later
(separate, [maintainer]-gated step).
## Consequences
- Realizes the seam architecture (ADR-referenced in `docs/architecture.md`).
- flare-edge is not edited now; a later integration step points flare-edge at these.
- Risk: temporary duplication of shared constants between the two repos until the
integration lands — tracked, acceptable for the bring-up window.
+13 -1
View File
@@ -16,8 +16,20 @@ PWM backlight · **USB host** (dwc3/xhci) + usb2phy · grf/pmu syscons.
- **GMAC** — eth0 Link Up 100 Mbps/Full (`gmac/`). - **GMAC** — eth0 Link Up 100 Mbps/Full (`gmac/`).
- **SARADC** — iio:device0 reads 2 ch; the 22 was vref, not clk (`adc/SARADC-FIX.md`). - **SARADC** — iio:device0 reads 2 ch; the 22 was vref, not clk (`adc/SARADC-FIX.md`).
## ✅ VOP display — VERIFIED this run (2026-08-25)
Full WardenOS Dashboard renders on the 86-Panel on 6.18 (`_b`), webcam-verified,
pixel-identical to stock `_a`. Two VOP driver bugs were the final black-screen
cause: `rgb_dclk_pol` hardcoded inverted (panel needs 0), and the wrong primary
scanout window (rv1106 uses **WIN1**, not rv1126's WIN2). Full chain + `_a`-vs-`_b`
register diff in `display/VERIFIED.md`.
## ✅ GT911 touch — VERIFIED this run (2026-08-25)
UI responds to taps/swipes on the panel ([maintainer]-confirmed); GT911 detected
(`ID 911, version 1060`), `/dev/input/event0` held by warden-ui. Fix:
`CONFIG_TOUCHSCREEN_GOODIX=y` (built-in — the rootfs `goodix.ko` is a 5.10 build
that can't load on 6.18) + GT911 node on `&i2c3`. Details in `touch/VERIFIED.md`.
## 🔨 In flight ## 🔨 In flight
- **VOP display** — binds; connector is tomorrow's on-panel work.
- **i2s-tdm** — DAI builds; needs the codec + card (below). - **i2s-tdm** — DAI builds; needs the codec + card (below).
- **AIC8800 BT** — module built (6.18 vermagic); HCI bring-up not yet exercised. - **AIC8800 BT** — module built (6.18 vermagic); HCI bring-up not yet exercised.
+7 -9
View File
@@ -39,13 +39,11 @@ rockchip-drm display-subsystem: bound ff990000.vop
brightness settable). **The VOP driver port is validated** — the register data, brightness settable). **The VOP driver port is validated** — the register data,
version, feature, and resets are right. version, feature, and resets are right.
## Open (needs on-panel eyes + a little more debug) ## ✅ RESOLVED — full UI renders on the panel (2026-08-25)
`/sys/class/drm/card0-*` has **no connector yet** — `rockchip_rgb_init` isn't The connector *and* the deeper black-screen chain that followed it are fixed; the
producing one (log: `Cannot find any crtc or sizes`), despite INTERNAL_RGB set and 86-Panel now draws the full WardenOS Dashboard on 6.18 (`_b`), verified by webcam.
a clean vop→panel of_graph. Likely a panel-probe-order / `drm_of_find_panel_or_bridge` The two final root causes were VOP driver bugs — `rgb_dclk_pol` hardcoded inverted,
detail. This is the last mile of M4 and, unlike the driver bind, needs the panel and the wrong primary scanout window (rv1106 scans out via **WIN1**, not WIN2).
physically observed (pixels can't be verified over serial/ssh). To pin it down: a See **`VERIFIED.md`** for the complete bring-up chain, the `_a`-vs-`_b` register
debug print in `rockchip_rgb_init` (child_count / find-panel ret), and set the panel diff that pinned it down, and every file changed.
bus_format to `MEDIA_BUS_FMT_RGB666_1X18` (a small `panel_dpi_probe` addition, since
mainline panel-dpi doesn't read bus-format from DT).
@@ -0,0 +1,87 @@
# Display (VOP + RGB panel) — ✅ VERIFIED on warden-c8a3 (2026-08-25)
The 86-Panel renders the **full WardenOS Dashboard UI** on our self-built Linux
6.18.46 (`_b` slot), pixel-identical to the stock 5.10 `_a` slot. Verified by
webcam pointed at the physical panel (pixels can't be checked over serial/ssh) —
`warden-ui -b DRM` drawing the Dashboard: nav sidebar, "Wellhead 03" site card,
Mesh/WAN/LAN/RS485 status rows, correct colors, no banding, no colour swap.
This closes the "Open" item in `README.md` (connector-not-created + the deeper
black-screen chain that followed it).
## The bring-up chain (each step was a real blocker)
1. **Connector never created** (`Cannot find any crtc`): `CONFIG_ROCKCHIP_RGB`
was not set, AND the vendor `&rgb` bridge node's dangling endpoint
(`rgb_in_vop -> vop_out_rgb`) read to fw_devlink as a vop↔panel dependency
cycle, so the VOP probed before the panel. Fix: enable `ROCKCHIP_RGB` +
`/delete-node/ &rgb;` so `vop_out_rgb <-> panel_in_vop` is the only graph link
(rockchip_rgb_init then defers + retries and finds the panel → `LVDS-1`).
2. **Backlight dark**: `&pwm1` had `pinctrl-names = "active"`; mainline
pwm-rockchip relies on the driver core auto-applying the **`"default"`** state,
so the PWM pin was never muxed. Fix: rename to `"default"`.
3. **bus-format unset** (RGB output width undefined): mainline `panel-dpi`
ignores the DT `bus-format`. Fix: small `panel_dpi_probe()` patch to read it +
`bus-format = <MEDIA_BUS_FMT_RGB666_1X18>` on the panel node.
4. **RGB output pins unmuxed** (no data reaches the panel): the 22-pin parallel
bus (`lcd_clk` + `lcd_d0..d17` + den/hsync/vsync) needs the `&lcd_pins` mux.
The vendor carried it as `pinctrl-0 = <&lcd_pins>` **on the `&rgb` node**, which
we deleted in step 1. Fix: re-attach it on `&vop` (`pinctrl-names="default"`;
the core auto-applies it at VOP probe).
5. **`reset-gpios` on the panel node is WRONG** (leave it off): GPIO0_A1 resets the
CH32V003 panel-init MCU, released once early by U-Boot `board_init()`. Handing
it to `panel-simple` makes `drm_panel_prepare()` re-reset the MCU mid-scanout.
Luckfox deleted these props upstream (commit e2b0ffa22); the flare-edge 5.10 DTS
documents the deletion as "the fix." We match: **backlight only, no reset-gpios**.
## The two root causes of the final "backlit-black" (VOP driver bugs)
With connector + backlight + pins + panel-init all correct, the screen was still
physically black (backlight on, `LVDS-1` connected, VOP streaming, fb0 720×720,
`modetest`/splash written) — the classic "everything healthy, glass dark" state.
Found by dumping the VOP register block `0xff990000` on the **working `_a` slot**
and diffing against `_b` (same SoC, same register map):
**Bug 1 — DCLK polarity inverted.** `rockchip_drm_vop.c` hardcodes
`rgb_dclk_pol = 1` for the LVDS/RGB output. The panel latches pixel data on the
**non-inverted** edge — `_a` reads `PX30_DSP_CTRL0` (0xff990020) = `0x1`
(rgb_dclk_pol bit1 = **0**). The vendor 5.10 derives it as
`(bus_flags & PIXDATA_DRIVE_NEGEDGE) ? 1 : 0`, which is 0 for this panel. With the
inverted clock the panel samples RGB on the wrong edge → black. **Fix:** set
`rgb_dclk_pol` to 0 in the `DRM_MODE_CONNECTOR_LVDS` case.
**Bug 2 — wrong primary scanout window.** The rv1106 VOP scans out through
**WIN1**, but our port reused rv1126's win table (`win0`-overlay + **`win2`**-primary).
The vendor `rv1106_vop_win_data` is `{ NULL-win0, rk3366_lit_win1_data-primary }`
i.e. WIN1 (`PX30_WIN1_*` at 0x090). Mainline was configuring WIN2, which never
reaches this SoC's RGB interface, so WIN1 stayed all-zero and nothing scanned out.
Register evidence (`_a` working vs `_b` broken, before the fix):
| reg | name | `_a` (works) | `_b` (black) |
|---|---|---|---|
| 0x090 | WIN1_CTRL0 (enable) | `0x00000001` | `0x00000000` |
| 0x098 | WIN1_VIR (stride) | `0x000002D0` (720) | `0x00000000` |
| 0x0a0 | WIN1_MST (fb addr) | `0x0F900000` | `0x00000000` |
| 0x0a4 | WIN1_DSP_INFO (size)| `0x02CF02CF` (720×720) | `0x00EF013F` (stale) |
**Fix:** `rv1106_vop_win_data[] = { { .phy = &px30_win1_data, PRIMARY } }`
(`px30_win1_data` already exists in mainline over `PX30_WIN1_*` — just wasn't wired
for rv1106). After the fix `_b` reads WIN1_CTRL0=1, WIN1_DSP_INFO=0x02CF02CF —
matching `_a`.
## Files changed (in research/linux-6.18.46)
- `drivers/gpu/drm/rockchip/rockchip_drm_vop.c``rgb_dclk_pol` 1 → 0 (LVDS case).
- `drivers/gpu/drm/rockchip/rockchip_vop_reg.c``rv1106_vop_win_data` uses
`px30_win1_data` as the single PRIMARY window (was rv1126's win0+win2).
- `drivers/gpu/drm/panel/panel-simple.c``panel_dpi_probe()` reads DT `bus-format`.
- `arch/arm/boot/dts/rockchip/rv1106-warden.dts``&vop` pinctrl `<&lcd_pins>`;
`&pwm1` pinctrl "default"; `/delete-node/ &rgb`; panel `bus-format` RGB666,
no reset-gpios.
## Known separate issue (NOT display)
`_b` still cold-reboots periodically (pre-existing `_b` general-stability issue,
independent of the display — the panel renders correctly the whole time it is up).
Tracked separately; the high-bootlimit env (`bootlimit=10000`) keeps these reboots
from tripping `altbootcmd=download` into the loader during bring-up.
@@ -0,0 +1,57 @@
# GT911 capacitive touch — ✅ VERIFIED on warden-c8a3 (2026-08-25)
Touch works on our self-built 6.18.46 (`_b`): the WardenOS UI responds to
taps/swipes ([maintainer] confirmed on the physical panel). Objective evidence:
```
Goodix-TS 3-0014: ID 911, version: 1060
input: Goodix Capacitive TouchScreen as .../i2c-3/3-0014/input/input0
```
`/dev/input/event0` is created and held open by `warden-ui` (pid 517, exclusive
EVIOCGRAB — which is why a second reader sees 0 bytes; the events go to the UI).
## Root cause on `_b`
Touch was dead on `_b` while fine on `_a`. dmesg showed:
```
module goodix: .gnu.linkonce.this_module section size must match the kernel's
built struct module size at run time
```
The **stock rootfs ships `goodix.ko` built for the 5.10 kernel**; it cannot load
on our 6.18 (`struct module` layout mismatch). Our 6.18 `.config` did **not** have
the driver at all (`# CONFIG_TOUCHSCREEN_GOODIX is not set`), and the DTS had no
GT911 node — so nothing drove the GT911.
## Fix
1. **`CONFIG_TOUCHSCREEN_GOODIX=y`** — build the mainline Goodix driver *into* the
kernel (no module → no vermagic/struct mismatch; the stale rootfs `.ko` still
fails to insmod but is now harmless).
2. **GT911 DT node** under `&i2c3` (matches the vendor 86-panel wiring):
```
touchscreen@14 {
compatible = "goodix,gt911";
reg = <0x14>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PA0 IRQ_TYPE_EDGE_FALLING>;
irq-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio3 RK_PD0 GPIO_ACTIVE_HIGH>;
};
```
plus `pinctrl-0 = <&i2c3m2_xfer &tp_rst &tp_irq>` on `&i2c3` and the `tp_rst`
(GPIO3_D0) / `tp_irq` (GPIO0_A0) pin groups.
Polarity note: mainline goodix drives reset **logical 0 = hold, 1 = release**, and
the GT911 reset is physically active-low, so `reset-gpios` is **ACTIVE_HIGH**
(logical==physical) — NOT the ACTIVE_LOW the vendor 5.10 driver used. Confirmed
against mainline gt911 DT examples (sun7i-a20-wexler-tab7200 etc.): both irq-gpios
and reset-gpios are ACTIVE_HIGH; reg 0x14 needs irq-gpios for address select.
Non-fatal: `Direct firmware load for goodix_911_cfg.bin failed (-2)` — the GT911
uses its flashed internal config; touch works without a cfg.bin.
## Files changed (research/linux-6.18.46)
- `.config` — `CONFIG_TOUCHSCREEN_GOODIX=y`.
- `arch/arm/boot/dts/rockchip/rv1106-warden.dts` — GT911 node on `&i2c3`,
`tp_rst`/`tp_irq` pin groups under `&pinctrl`.