19 KiB
ACPI I2C / I2C-HID Implementation Plan
Goal
Implement a real laptop-class ACPI I2C stack for Red Bear OS, with I2C-HID via ACPI
as the first user-visible deliverable. This is required for modern touchpads, keyboards,
and other embedded input devices that are no longer exposed via PS/2.
The shortest correct path is:
ACPI _CRS decode -> I2C controller ownership -> I2C bus API/scheme -> i2c-hidd ->
inputd integration
This work must be treated as bare-metal boot-critical substrate, not as optional polish.
Current State
What already exists:
acpidhas AML evaluation and a scheme surface for tables, AML symbols, DMI, power, reboot, and PCI registration.hwdalready recognizesPNP0C50asI2C HIDduring ACPI probe, but only as a label.amlserdecan already carry raw AML buffers and the relevant opregion kinds.
What is missing:
- no decoded
_CRSresource parser for ACPI devices - no
/scheme/acpi/...API for decodedI2cSerialBus,GpioInt,GpioIo, or IRQ data - no native I2C controller subsystem
- no native I2C controller drivers for Intel LPSS / AMD laptop paths
- no
i2c-hidd - no completed input path for laptop-class ACPI-attached keyboards and touchpads
Reference Carriers In Local Tree
These Linux sources are reference carriers only. They should guide design and descriptor semantics, but should not be transliterated blindly.
build/linux-kernel-cache/linux-7.0/drivers/hid/i2c-hid/i2c-hid-acpi.cbuild/linux-kernel-cache/linux-7.0/drivers/hid/i2c-hid/i2c-hid-core.cbuild/linux-kernel-cache/linux-7.0/drivers/i2c/i2c-core-acpi.cbuild/linux-kernel-cache/linux-7.0/drivers/acpi/resource.cbuild/linux-kernel-cache/linux-7.0/drivers/mfd/intel-lpss-pci.cbuild/linux-kernel-cache/linux-7.0/drivers/mfd/intel-lpss-acpi.cbuild/linux-kernel-cache/linux-7.0/drivers/i2c/busses/i2c-designware-amdpsp.cbuild/linux-kernel-cache/linux-7.0/drivers/i2c/busses/i2c-amd-mp2-pci.c
Execution Order
Phase A: ACPI _CRS substrate
Deliverables:
- add decoded ACPI resource support in
acpid - expose decoded device resources through
/scheme/acpi - support at minimum:
- IRQ
- Extended IRQ
- GPIO interrupt
- GPIO I/O
I2cSerialBus
Acceptance:
- a consumer can query decoded resources for a device path without reimplementing AML resource decoding
- known laptop devices show valid controller link, slave address, and interrupt metadata
Phase B: Native I2C substrate
Deliverables:
- add a small
i2cdscheme / API - support controller registration, transfers, and per-device addressing
- keep scope tight; do not clone Linux I2C core complexity
Acceptance:
- a userspace daemon can open an adapter and issue I2C transfers using a stable Red Bear API
Phase C: Intel laptop controller path
Deliverables:
- add Intel LPSS / Serial IO I2C controller ownership first
Why first:
- this is the most common modern Intel laptop path for touchpads and keyboards
- it directly unblocks
I2C-HIDon many real machines
Acceptance:
- at least one Intel bare-metal laptop registers a usable I2C adapter from ACPI-described hardware
Phase D: i2c-hidd
Deliverables:
- bind ACPI
PNP0C50/ACPI0C50 - evaluate
_DSMusing the HID-over-I2C GUID to retrieve the HID descriptor address - fetch HID descriptor and report descriptor via I2C
- stream input reports into
inputd
Acceptance:
- at least one laptop touchpad or keyboard produces usable events
Phase E: AMD controller path
Deliverables:
- add AMD laptop-class I2C controller support
- likely DesignWare / MP2 mediated paths depending on platform
Acceptance:
- at least one AMD laptop reaches a functioning internal input device through ACPI I2C
Phase F: Remaining ACPI I2C functions
Deliverables:
_STAgating before bind_INIwhere required_PS0/_PS3best-effort device power transitionsGpioIntandGpioIosemantics for reset, wake, and power sequencing_S0W/ wake-capable handling where hardware requires it- GenericSerialBus / SMBus opregion support only where firmware actually needs it
Acceptance:
- runtime bring-up no longer depends on USB or PS/2 fallback for supported laptops
Design Rules
- prefer a small, explicit Red Bear userspace API over Linux-core emulation
- decode ACPI resources once in
acpid; do not duplicate_CRSparsing in every consumer - make controller ownership data-driven through decoded ACPI resources where possible
- keep laptop input as a boot-resilience feature, not a desktop-only feature
- treat Intel and AMD laptops as equal-priority hardware targets
Other Boot-Relevant I2C Device Classes
I2C-HID is the first and most important I2C deliverable, but it is not the only I2C-related
surface that can matter during boot on modern bare metal.
Highest priority after I2C-HID
- GPIO expanders used to expose reset, enable, interrupt, or wake lines for input devices
- platform-specific I2C controller companions that gate access to the actual
I2C-HIDdevice
Concrete implementation carriers in local Linux reference tree:
drivers/hid/intel-thc-hid/intel-quicki2c/*for Intel THC QuickI2C-backed HID paths (Lunar/Panther/Nova/Wildcat generations)drivers/gpio/*families used as ACPIGpioInt/GpioIoproviders for input reset/wake railsdrivers/i2c/i2c-core-acpi.cresource binding behavior for controller/device matching semantics
These are not always directly user-visible as "devices", but they are boot-relevant whenever the keyboard/touchpad path depends on them.
Sometimes boot-relevant
- USB-C / UCSI / PD related I2C-attached endpoints on platforms where a USB-C attached keyboard or dock path is firmware-mediated and not available without those services
- embedded controller-adjacent I2C peripherals that gate keyboard/touchpad power or wake routing
These should be treated as platform-dependent bring-up work, not as universal phase-1 targets.
Not first-order blockers for reaching login
- sensors (accelerometer, gyro, ambient light)
- battery / charger / fuel-gauge devices
- camera-side I2C devices
- most audio codecs and amplifier control devices
- thermal and fan-adjacent I2C sensors
These matter for full laptop support, but they do not outrank keyboard/touchpad bring-up for live boot and recovery.
Boot Priority Order
For boot-to-login on modern laptops, the correct priority is:
I2C-HIDkeyboards and touchpads- any GPIO-expander or companion I2C devices required to make those devices usable
- platform-specific USB-C / UCSI I2C surfaces only on machines that actually depend on them for input availability
- all other I2C-attached peripherals
Immediate Next Steps
- land
_CRSdecoding inacpid - expose decoded resources under
/scheme/acpi - validate decoded
I2cSerialBusand GPIO/IRQ data on real hardware logs - introduce the minimal native I2C userspace substrate
- implement Intel LPSS controller ownership
- implement
i2c-hidd
Boot-Critical I2C Addendum (post-Phase D)
The remaining boot-critical order after initial i2c-hidd is:
- Intel THC QuickI2C transport path for ACPI-described HID devices on new Intel laptops
- GPIO companion completeness for
GpioIntandGpioIoreset/wake wiring - platform-specific I2C controller companions only where they gate input availability
Anything outside this list should not preempt keyboard/touchpad path completion for boot-to-login.
Concrete device classes to implement next (boot-first order)
| Priority | Device class | Linux carrier in tree | Red Bear status |
|---|---|---|---|
| P0 | Intel THC QuickI2C transport (HID over THC) |
drivers/hid/intel-thc-hid/intel-quicki2c/* |
detection/parking landed, transport still missing |
| P1 | GPIO companions for GpioInt/GpioIo (reset/wake rails) |
drivers/gpio/*, ACPI resource flow |
partially landed, board-specific gaps remain |
| P2 | Controller-companion ACPI methods (_DSM/_DSD) that gate input |
i2c-core-acpi.c, QuickI2C ACPI helpers |
partially landed, still platform-dependent |
| P3 | USB-C/UCSI I2C only on machines where input depends on it | drivers/usb/typec/ucsi/* and ACPI glue |
partial: ACPI UCSI (PNP0CA0/AMDI0042) discovery + bounded I2C probe/policy surface landed; runtime UCSI transport/partner path still missing |
This order is strict for boot-to-login resilience on modern laptops.
Current in-tree staging note:
- initfs boot ownership for ACPI/PIC is now explicit:
40_pcid.service->41_acpid.service->40_hwd.service->40_pcid-spawner-initfs.service;hwdno longer spawnsacpidorpcidad hoc. redbear-live-mininow enables00_i2c-hidd.servicein non-blocking mode (oneshot_async) instead of masking it withcmd = "true".redbear-live-mininow carries non-blocking00_i2c-gpio-expanderd.serviceand00_ucsid.serviceoverlays so the boot-minimal image keeps companion GPIO and UCSI topology diagnostics aligned with the boot-critical I2C path.intel-thc-hiddnow performs ACPI companion resolution,_DSMcapability reads,PNP0C50scan, THC-bound candidate diagnostics, BAR mapping, and registers a minimalintel-thc-quicki2cadapter intoi2cdwith transfer handling through THC I2C subIP (DesignWare-style path).intel-thc-hiddnow also consumes bounded ACPI controller-companion methodsICRSandISUBwhen present, using them to refine adapter speed/addressing diagnostics and to apply ACPI timing overrides for DW SCL high/low counters.intel-thc-hiddnow emits compactRB_THC_HIDD_SCHEMA/RB_THC_HIDDmarker lines with THC-bound PNP0C50 candidate counts and status reasons (availablevsnot-available) so boot logs can distinguish missing ACPI binding surfaces from transport/runtime faults.intel-thc-hiddnow canonicalizes the primaryRB_THC_HIDDstatus field and warns/coerces unknown values toerror, matching the parser-robust status policy used inhwd/i2c-hidd.RB_THC_HIDD/RB_THC_HIDD_FATALmarkers now includegeneration=<n>for explicit correlation with other boot-readiness streams.RB_THC_HIDDstatus semantics now explicitly includenot-ready(ACPI symbols not ready) anderror(ACPI symbol scan failure), so init ordering and enumeration faults are disambiguated in CI logs.intel-thc-hiddnow emitsRB_THC_HIDD_FATAL status=error ...markers on hard-stop failures (BAR map/size failures, unexpected DW component type, i2cd registration failure, provider-loop failure) so fatal transport bring-up exits are machine-classifiable.hwdnow emits compactRB_THC_QUICKI2C status=not-ready ...and UCSIRB_UCSI_* status=not-ready ...markers even when ACPI symbol enumeration returnsWouldBlock, preserving machine-readable readiness signals during early init ordering windows.hwdnow reports THC companionICRS/ISUBmethod readiness counts (thc_quicki2c_ready) during ACPI probe so missing controller-companion surfaces are visible before driver bring-up.hwdnow also emits compactRB_THC_QUICKI2C_SCHEMA/RB_THC_QUICKI2Cmarker lines (status=absent|available|not-ready) for THC companion readiness scraping in CI/log pipelines.RB_THC_QUICKI2Cnow also includesgeneration=<n>for consistent correlation semantics with other marker streams.hwdnow assigns marker generation per ACPI probe pass and threads it through UCSI/THC fallback markers as well, eliminatinggeneration=0ambiguity on local fallback paths.- schema markers now also carry generation (
RB_UCSI_SCHEMA,RB_THC_QUICKI2C_SCHEMA,RB_UCSID_SCHEMA,RB_I2C_HIDD_SCHEMA,RB_THC_HIDD_SCHEMA) so schema and data lines share the same correlation key shape. i2c-hiddnow consults THC companionICRSwhen bound throughintel-thc-quicki2c, and performs a bounded slave-address override if HID_CRSI2C address and companion-method address disagree.i2c-hiddnow emits compactRB_I2C_HIDD_SCHEMAandRB_I2C_HIDD_BLOCKERmarkers so unresolved THC resource-source adapter matches are machine-readable in boot logs (reason=thc_transport_adapter_unavailable).i2c-hiddmarker emitters now canonicalize status fields (RB_I2C_HIDD_SNAPSHOT,RB_I2C_HIDD_BLOCKER) and warn/coerce unknown values toerrorfor parser-safe output under schema drift.RB_I2C_HIDD_BLOCKERnow also includesgeneration=<n>, aligned to the current scan cycle so blocker and snapshot events are directly correlatable.RB_I2C_HIDD_BLOCKERstatus semantics now also includenot-ready(acpi_symbols_not_ready) anderror(acpi_symbol_scan_error) on the ACPI symbol scan path, aligning HID-consumer readiness reporting with THC producer markers.i2c-hiddscan-state handling now preserves that distinction in snapshots: ACPIWouldBlockyieldsRB_I2C_HIDD_SNAPSHOT status=not-ready reason=acpi_symbols_not_ready(notnot-available), avoiding false “no devices” classification during early init ordering.i2c-hiddnow emitsRB_I2C_HIDD_SNAPSHOTper scan cycle (status,reason,devices,adapters,started,probe_ok,probe_failed) so boot logs expose HID bring-up progress and failure density, not only blocker edges.RB_I2C_HIDD_SNAPSHOTnow also carriesgeneration=<n>, allowing cycle-level correlation with other readiness marker streams.- the same
RB_I2C_HIDD_SNAPSHOTstream now includesstatus=error reason=scan_failedon scan-cycle exceptions, preserving explicit machine-readable failure state even when scan aborts early. - The in-tree bridge now derives adapter speed profile from ACPI-bound devices and includes bounded one-shot controller recovery/reinit on non-addressing transfer failures.
ucsidnow exposes/scheme/ucsisummary/device records with policy-driveninput_criticalclassification, per-node probe policy, bounded AMDI0042 I2C probe telemetry, and PNP0CA0 ACPI_DSMcapability-mask diagnostics (Linux carrier aligned withucsi_acpi.cfunction-mask semantics).ucsidnow also supports a policy/env-gated bounded PNP0CA0_DSMfunction-2 read-call probe (REDBEAR_UCSI_DSM_READ_PROBE/probe_dsm_read) to surface ACPI transport readiness without enabling full UCSI command transport.- when that bounded read probe returns a buffer payload,
ucsidnow surfaces a minimal UCSI header snapshot (version_bcdat offset 0 andcciat offset 4) for early transport-readiness diagnostics. hwdnow opportunistically consumes/scheme/ucsi/summary(when available) and logs UCSI transport-readiness snapshot counts/devices on the ACPI probe path.hwdnow classifies UCSI summary availability asavailable/not-ready/not-available/error, making initfs service-order gaps distinguishable from summary parse/probe failures.hwdnow emits a compactRB_UCSI_SNAPSHOT ...key-value marker line for CI/log scrapers in addition to the human-readable UCSI status logs.ucsidnow emits compactRB_UCSID_SUMMARY ...and per-deviceRB_UCSID_DEVICE ...marker lines so readiness can be scraped directly from daemon logs without scheme reads.hwdnow mirrors per-device compact markers asRB_UCSI_DEVICE ...when/scheme/ucsi/summaryis available, so CI can consume transport-readiness from thehwdboot stream as well.ucsidnow classifiestransport_blockerforinput_criticaldevices that are not transport-ready, and exportstransport_blocked_input_criticalin summary markers for boot-priority triage.ucsid/hwdcompact markers now includehealth=ok|degradedplus dedicatedRB_UCSID_HEALTH/RB_UCSI_HEALTHlines keyed bytransport_blocked_input_critical.RB_UCSID_SUMMARYand mirroredRB_UCSI_SUMMARYnow carrygeneration=<n>so CI can correlatehwdsnapshots with a specificucsidscan cycle and detect stale reads.- generation is now assigned before each
ucsidscan pass and included on per-device markers (RB_UCSID_DEVICE/ mirroredRB_UCSI_DEVICE) so device-level lines are cycle-correlated as well. RB_UCSI_SNAPSHOTis now self-contained withgeneration,health, andtransport_blocked_input_criticalwhen summary is available, while preserving explicitstatus=*for not-ready/not-available/error cases.hwdnow emitsRB_UCSI_SNAPSHOT status=absent ...when no ACPI UCSI candidates are discovered, so CI can distinguish true surface absence from service readiness failures.ucsidcompact markers now emit explicit status on every scan cycle (status=available|absent|not-ready|error) viaRB_UCSID_SUMMARY/RB_UCSID_HEALTH.ucsidnow also emitsRB_UCSID_SUMMARY/RB_UCSID_HEALTHwithstatus=errorandhealth=unknownon scan-cycle failures, so CI can distinguish explicit UCSI scan faults from stale/missing marker streams.- on scan failure,
ucsidnow also resets shared/scheme/ucsi/summarycounters to a cleanstatus=errorstate for that generation (instead of carrying stale counters from the previous successful cycle). ucsidACPI-symbolWouldBlockno longer collapses intostatus=absent; it now emits explicitstatus=not-readymarkers so early-init readiness is not misclassified as true UCSI surface absence./scheme/ucsi/summarynow carries explicit producer status (available|absent|not-ready|error) andhwdconsumes that field when mirroringRB_UCSI_*, preventing falsestatus=availableinterpretations from zeroed summary counters during not-ready/error cycles.hwdnow normalizes UCSI summary status parsing (trims whitespace and accepts case variants) and warns before coercing unknown statuses toerror, improving resilience to producer/schema drift.hwdnow also cross-checks status against summary counters: contradictory payloads (availablewith zero devices, orabsentwith nonzero devices) are warned and coerced to safe marker output (absent/error) instead of being mirrored verbatim.- for
status=not-ready|not-available|error,hwdnow warns if nonzero payload counters/devices are present before emitting fallback status markers, making producer-status drift explicit in logs. ucsidstartup default summary state is now explicitlystatus=not-ready(instead of implicit empty/default status), so early pre-scan reads of/scheme/ucsi/summaryremain unambiguous.- mirrored
hwdmarkers now carry explicit status onRB_UCSI_SUMMARY/RB_UCSI_HEALTH(available|absent|not-ready|not-available|error), keeping status semantics aligned across both producers and fallback paths. - mirrored
RB_UCSI_DEVICEnow carries richer readiness context (i2c_backed, DSM read support/probe flags) to matchucsiddiagnostics from a single boot-log stream. - for
status=not-ready|not-available|error,hwdnow emits fallbackRB_UCSI_SUMMARY/RB_UCSI_HEALTHlines (not justRB_UCSI_SNAPSHOT) so CI can rely on the same marker keys in every status path. - Native THC DMA/report transport is still missing.