// SPDX-License-Identifier: GPL-2.0 OR MIT // LILYGO T-Display-K230, against MAINLINE Linux. // // openspec/changes/the-board-runs-a-mainline-kernel. This is a SEPARATE // board file from nix/dts/k230-tdisplay.dts, which targets the pinned // vendor Xuantie tree via nix/kernel-src.nix/nix/device-tree.nix and is // unaffected by this file. This one #includes MAINLINE's own // arch/riscv/boot/dts/canaan/k230.dtsi (nix/kernel-mainline-src.nix), which // ships console + SoC-platform nodes only -- no gpio/mmc/usb/i2c/spi/pwm/ // adc/rtc/crypto/thermal node at all (see nix/kernel-mainline.nix's header // for the full accounting). GPIO, SD/MMC and USB nodes below are added by // THIS file, forward-ported from the pinned VENDOR tree's own // arch/riscv/boot/dts/canaan/k230.dtsi (ruyisdk/linux-xuantie-kernel @ // 7d4e1f444f461dbe3833bd99a4640e7b6c2cd529) -- same compatible strings, // register addresses, and interrupt numbers (grounding tier 2: vendor // source read directly, cited by path). Only the clocks/resets phandles // differ, because the vendor tree wires these three nodes to unimplemented // stub clocks (`&dummy_sd`, `&clk_dummy`) that do not exist in mainline's // device tree at all -- mainline's own COMMON_CLK_K230/RESET_K230 drivers // are real, so real phandle+ID pairs are used instead, taken directly from // mainline's own and // (both already pulled in // transitively by k230.dtsi's own top-of-file #includes). // // UNVERIFIED: none of this has been compiled against a booted board. The // exact clock-gate/reset IDs chosen for GPIO/MMC/USB are a best-effort // mapping from the ID names alone (e.g. "AHB_GATE" for the register-bus // clock, "BASE_GATE" for the SDHCI functional clock) -- correct enough to // be syntactically valid u32 phandle args and to let each driver's // mandatory clk_get calls succeed, but NOT independently confirmed against // a working configuration the way nix/dts/k230-tdisplay.dts's vendor-tree // clocks are. A board boot is what settles whether these gate the right // signal. // // Modeled directly on mainline's own arch/riscv/boot/dts/canaan/ // k230-evb.dts (Yangyu Chen, GPL-2.0 OR MIT) for the console/memory/sysclk // shape: aliases.serial0 = &uart0; chosen stdout-path; a `ddr: memory@0` // node; &uart0 enabled; &sysclk given its two input clocks. Two things // changed from that template, both grounded against this project's OWN // existing vendor board file (nix/dts/k230-tdisplay.dts), not guessed: // // 1. Memory size: 0x40000000 (1 GiB), matching // nix/dts/k230-tdisplay.dts's own `ddr: memory@0` node exactly. The // k230-evb reference board has only 512 MiB (0x20000000); ours does // not. // 2. model/compatible strings renamed to this board, following the same // "lilygo,t-display-k230" first-compatible pattern // nix/dts/k230-tdisplay.dts already uses, with a "canaan,kendryte-k230" // fallback (mainline has no "canaan,canmv-k230" compatible string to // fall back to the way the vendor board file does, since that string // is a vendor-tree invention, not upstream). // // Grounding for "UART0 is safe to reuse as-is": neither mainline's // k230.dtsi/k230-evb.dts NOR our own vendor-tree k230.dtsi/k230-tdisplay.dts // reference any pinctrl consumer group for UART0 (`docs/dts-evidence.md`: // "no pinctrl in the Linux device tree at all" on our build) -- physical // IOMUX is entirely U-Boot's FPIOA table in both cases, not something // either device tree programs. Our board's stdout-path is already // "serial0:115200n8" in nix/dts/k230-tdisplay.dts // (docs/research/board-capability-inventory.md: "uart0 is the Linux // console (serial0)"), so this file asks U-Boot for exactly the physical // pin configuration it already provides today, not a new one. The same // reasoning applies to GPIO/SD/USB below: their physical pin muxing is // also entirely U-Boot's FPIOA table's job in the vendor image, and this // file changes none of that -- only the Linux-side controller nodes. /dts-v1/; #include "k230.dtsi" / { model = "LILYGO T-Display-K230 (mainline)"; compatible = "lilygo,t-display-k230", "canaan,kendryte-k230"; aliases { serial0 = &uart0; // Matches nix/dts/k230-tdisplay.dts's own naming: mmc1 is the // physical TF/SD card, mmc0 the RTL8189FTV SDIO Wi-Fi (enabled // below -- see &mmc_sd0's own override comment, task // the-mainline-shell-reaches-parity 6.1). mmc0 = &mmc_sd0; mmc1 = &mmc_sd1; }; chosen { stdout-path = "serial0:115200n8"; }; ddr: memory@0 { device_type = "memory"; // 1 GiB, matching nix/dts/k230-tdisplay.dts's own memory // node -- NOT the 512 MiB k230-evb.dts reference default. reg = <0x0 0x0 0x0 0x40000000>; }; timerx_pulse_in: clock-50000000 { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <50000000>; }; // GPIO/USB/SD-MMC controller nodes mainline's own k230.dtsi does not // carry yet. Reopening `soc` by name (it has no label upstream to // attach to via `&soc`) merges these as siblings of plic/clint/rst/ // pinctrl/sysclk/uart0-4, exactly where the vendor tree's own k230.dtsi // places the equivalent nodes. soc { gpio0: gpio@9140b000 { compatible = "canaan,k230-apb-gpio"; reg = <0x0 0x9140b000 0x0 0x1000>; // gpio-k230 requests these by name; unnamed they are // ignored and unused-clock cleanup gates the bus. clocks = <&sysclk K230_LS_GPIO_APB_GATE>, <&sysclk K230_LS_GPIO_DEBOUNCE_GATE>; clock-names = "bus", "db"; resets = <&rst RST_GPIO_APB>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; gpio0_ports: gpio-port@0 { compatible = "canaan,k230-apb-gpio-port"; reg = <0>; gpio-controller; #gpio-cells = <2>; snps,nr-gpios = <32>; interrupt-controller; #interrupt-cells = <2>; interrupts = <32 IRQ_TYPE_EDGE_RISING>, <33 IRQ_TYPE_EDGE_RISING>, <34 IRQ_TYPE_EDGE_RISING>, <35 IRQ_TYPE_EDGE_RISING>, <36 IRQ_TYPE_EDGE_RISING>, <37 IRQ_TYPE_EDGE_RISING>, <38 IRQ_TYPE_EDGE_RISING>, <39 IRQ_TYPE_EDGE_RISING>, <40 IRQ_TYPE_EDGE_RISING>, <41 IRQ_TYPE_EDGE_RISING>, <42 IRQ_TYPE_EDGE_RISING>, <43 IRQ_TYPE_EDGE_RISING>, <44 IRQ_TYPE_EDGE_RISING>, <45 IRQ_TYPE_EDGE_RISING>, <46 IRQ_TYPE_EDGE_RISING>, <47 IRQ_TYPE_EDGE_RISING>, <48 IRQ_TYPE_EDGE_RISING>, <49 IRQ_TYPE_EDGE_RISING>, <50 IRQ_TYPE_EDGE_RISING>, <51 IRQ_TYPE_EDGE_RISING>, <52 IRQ_TYPE_EDGE_RISING>, <53 IRQ_TYPE_EDGE_RISING>, <54 IRQ_TYPE_EDGE_RISING>, <55 IRQ_TYPE_EDGE_RISING>, <56 IRQ_TYPE_EDGE_RISING>, <57 IRQ_TYPE_EDGE_RISING>, <58 IRQ_TYPE_EDGE_RISING>, <59 IRQ_TYPE_EDGE_RISING>, <60 IRQ_TYPE_EDGE_RISING>, <61 IRQ_TYPE_EDGE_RISING>, <62 IRQ_TYPE_EDGE_RISING>, <63 IRQ_TYPE_EDGE_RISING>; }; }; gpio1: gpio@9140c000 { compatible = "canaan,k230-apb-gpio"; reg = <0x0 0x9140c000 0x0 0x1000>; // gpio-k230 requests these by name; unnamed they are // ignored and unused-clock cleanup gates the bus. clocks = <&sysclk K230_LS_GPIO_APB_GATE>, <&sysclk K230_LS_GPIO_DEBOUNCE_GATE>; clock-names = "bus", "db"; resets = <&rst RST_GPIO_APB>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; gpio1_ports: gpio-port@0 { compatible = "canaan,k230-apb-gpio-port"; reg = <0>; gpio-controller; #gpio-cells = <2>; snps,nr-gpios = <32>; interrupt-controller; #interrupt-cells = <2>; interrupts = <64 IRQ_TYPE_EDGE_RISING>, <65 IRQ_TYPE_EDGE_RISING>, <66 IRQ_TYPE_EDGE_RISING>, <67 IRQ_TYPE_EDGE_RISING>, <68 IRQ_TYPE_EDGE_RISING>, <69 IRQ_TYPE_EDGE_RISING>, <70 IRQ_TYPE_EDGE_RISING>, <71 IRQ_TYPE_EDGE_RISING>, <72 IRQ_TYPE_EDGE_RISING>, <73 IRQ_TYPE_EDGE_RISING>, <74 IRQ_TYPE_EDGE_RISING>, <75 IRQ_TYPE_EDGE_RISING>, <76 IRQ_TYPE_EDGE_RISING>, <77 IRQ_TYPE_EDGE_RISING>, <78 IRQ_TYPE_EDGE_RISING>, <79 IRQ_TYPE_EDGE_RISING>, <80 IRQ_TYPE_EDGE_RISING>, <81 IRQ_TYPE_EDGE_RISING>, <82 IRQ_TYPE_EDGE_RISING>, <83 IRQ_TYPE_EDGE_RISING>, <84 IRQ_TYPE_EDGE_RISING>, <85 IRQ_TYPE_EDGE_RISING>, <86 IRQ_TYPE_EDGE_RISING>, <87 IRQ_TYPE_EDGE_RISING>, <88 IRQ_TYPE_EDGE_RISING>, <89 IRQ_TYPE_EDGE_RISING>, <90 IRQ_TYPE_EDGE_RISING>, <91 IRQ_TYPE_EDGE_RISING>, <92 IRQ_TYPE_EDGE_RISING>, <93 IRQ_TYPE_EDGE_RISING>, <94 IRQ_TYPE_EDGE_RISING>, <95 IRQ_TYPE_EDGE_RISING>; }; }; usb0: usb@91500000 { compatible = "canaan,k230-otg"; reg = <0x0 0x91500000 0x0 0x40000>; ctl-reg = <0x0 0x9158507c>; interrupts = <173 IRQ_TYPE_LEVEL_HIGH>; clocks = <&sysclk K230_HS_USB0_AHB_GATE>; clock-names = "otg"; resets = <&rst RST_USB0>; g-rx-fifo-size = <512>; g-np-tx-fifo-size = <64>; g-tx-fifo-size = <512 1024 64 64 64 64>; status = "disabled"; }; usb1: usb@91540000 { compatible = "canaan,k230-otg"; reg = <0x0 0x91540000 0x0 0x40000>; ctl-reg = <0x0 0x9158509c>; interrupts = <174 IRQ_TYPE_LEVEL_HIGH>; clocks = <&sysclk K230_HS_USB1_AHB_GATE>; clock-names = "otg"; resets = <&rst RST_USB1>; g-rx-fifo-size = <512>; g-np-tx-fifo-size = <64>; g-tx-fifo-size = <512 1024 64 64 64 64>; status = "disabled"; }; mmc_sd0: sdhci0@91580000 { compatible = "canaan,k230-dw-mshc"; reg = <0x0 0x91580000 0x0 0x1000>; interrupts = <142 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "sdhci0irq"; clocks = <&sysclk K230_HS_SD0_BASE_GATE>, <&sysclk K230_HS_SD0_AHB_GATE>; clock-names = "core", "bus"; resets = <&rst RST_SDIO0>; max-frequency = <200000000>; bus-width = <8>; sdhci,auto-cmd12; dma-noncoherent; // Enabled below (task the-mainline-shell-reaches-parity // 6.1): the RTL8189FTV SDIO Wi-Fi function this board // wires here (nix/dts/k230-tdisplay.dts's own &mmc_sd0, // "The RTL8189FTV, over SDIO."). The five-clock claim the // patched sdhci driver requests is the &mmc_sd0 override at // the end of this file. // UNVERIFIED against a booted board: no SDIO enumeration, // register trace or module bind has been observed; see // docs/research/mainline-wifi-port.md. status = "okay"; }; mmc_sd1: sdhci1@91581000 { compatible = "canaan,k230-dw-mshc"; reg = <0x0 0x91581000 0x0 0x1000>; interrupts = <144 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "sdhci1irq"; clocks = <&sysclk K230_HS_SD1_BASE_GATE>, <&sysclk K230_HS_SD1_AHB_GATE>; clock-names = "core", "bus"; resets = <&rst RST_SDIO1>; max-frequency = <50000000>; bus-width = <4>; sdhci,auto-cmd12; dma-noncoherent; mshc_ctrl_r = <0x00>; status = "disabled"; }; // The on-chip RTC. Address and compatible string from // docs/research/board-capability-inventory.md's own citation of // the vendor k230.dtsi (`rtc@0x91000c00`, no status property // there, so enabled by default -- mainline's k230.dtsi has no // such node at all yet, hence adding it here). The driver // (nix/patches/mainline/rtc-k230.c) takes an optional "pclk", so // probe succeeds here without one; the DRM DT supplies the PMU // APB gate so unused-clock cleanup cannot gate it. rtc: rtc@91000c00 { compatible = "canaan,k230-rtc"; reg = <0x0 0x91000c00 0x0 0x100>; status = "okay"; }; // PMU INT0 power key (openspec/changes/ // the-mainline-shell-reaches-parity task 4.1). Reg ranges, // compatible string and IRQ number are the same ones this // project's own VENDOR-kernel board file already uses // (nix/dts/k230-tdisplay.dts): the PMU block itself // (0x91000000, 0xc00 bytes -- ending exactly where &rtc // above begins, both inside the same PMU register region) // and the PWR/sysctl_power block (0x91103000, 0x1000 bytes, // matching the vendor k230.dtsi's own sysctl_power@91103000 // node). IRQ 175 comes from the vendor driver's own header // comment (nix/patches/k230-pmu-pwrkey.c): "route PMU // KEY_EDGE to CPU IRQ 175", mirroring the RT-Thread PMU // pwrkey driver -- UNVERIFIED against a booted board, same // as every other interrupt number in this file. The driver // (nix/patches/mainline/k230-pmu-pwrkey.c) takes an optional // "pclk" for the PMU APB gate it shares with &rtc above; // claimed directly here (not deferred to the DRM DT) since // the power key is a console-level feature. pmu_pwrkey: pmu-pwrkey@91000000 { compatible = "canaan,k230-pmu-pwrkey"; reg = <0x0 0x91000000 0x0 0xc00>, <0x0 0x91103000 0x0 0x1000>; reg-names = "pmu", "pwr"; interrupts = <175 IRQ_TYPE_LEVEL_HIGH>; clocks = <&sysclk K230_PMU_APB_GATE>; clock-names = "pclk"; wakeup-source; status = "okay"; }; // Temperature sensor (openspec/changes/ // the-mainline-shell-reaches-parity task 7.1). Reg from the // pinned vendor k230.dtsi's own tsensor@91107000 node // (/nix/store/hn11x8zd5linl193d8q0k9k99b46zqbm-linux-xuantie- // k230-src/arch/riscv/boot/dts/canaan/k230.dtsi): no // interrupt there (the driver polls TS_DATA), and the // vendor's "hardlock = <2>" property is a dual-OS RTOS/Linux // register-access mutex with no mainline binding or driver // use, so it is dropped here, same as this file already // drops other vendor-only dual-OS properties. The driver // (nix/patches/mainline/canaan_thermal.c) takes an optional // "ts" clock for the sensor's own rate clock // (K230_SYSCTL_TEMP_SENSOR_RATE, include/dt-bindings/clock/ // canaan,k230-clk.h), claimed directly here for the same // unused-clock-cleanup reason as &pmu_pwrkey and &rtc above. tsensor: tsensor@91107000 { compatible = "canaan,k230-tsensor"; reg = <0x0 0x91107000 0x0 0x800>; clocks = <&sysclk K230_SYSCTL_TEMP_SENSOR_RATE>; clock-names = "ts"; status = "okay"; }; // Peripheral DMA controller (task 5.1 follow-up: the mainline // forward-port of drivers/dma/k230_peridma.c, this project's own // nix/patches/mainline/k230-peridma.c). Address, #dma-cells, // dma-channels/dma-requests and interrupt number copied verbatim // from the vendor tree's own k230.dtsi `pdma@0x80804000` node -- // same register block, same PLIC line (203), same driver (the // vendor .c file ported essentially unchanged; see that file's // own header comment for the API deltas). clocks: // K230_SHRM_PDMA_AXI_GATE is mainline's ID for the exact clock // the vendor DT's `pdma_aclk_gate` node programs -- confirmed // byte-for-byte against both sources, not inferred: // // - vendor k230_clock_provider.dtsi's `pdma_aclk_gate` node: // clk-gate-reg-offset = <0x5C>, clk-gate-reg-bit-enable = <3>. // - mainline drivers/clk/clk-k230.c: // `K230_CLK_GATE_FORMAT(shrm_pdma_axi_gate, // K230_SHRM_PDMA_AXI_GATE, 0x5C, 3, 0, 0, ...)` -- same // register offset, same bit, parented from // shrm_axim_clk_gate the same way the vendor's gate is // parented from shrm_axim_clk_gate's own vendor-tree // equivalent. // - include/dt-bindings/clock/canaan,k230-clk.h: // `K230_SHRM_PDMA_AXI_GATE` = 130. // // The driver claims this clock itself via devm_clk_get_enabled() // in probe() (no clock-names property needed -- the driver calls // devm_clk_get(..., NULL), matching the vendor's own single // unnamed-clock probe call) -- the AGENTS.md "claim every clock" // lesson: this gate is otherwise unused by anything else in this // tree and mainline's unused-clock cleanup would strip it. pdma: pdma@80804000 { compatible = "canaan,k230-pdma"; reg = <0x0 0x80804000 0x0 0x400>; interrupts = <203 IRQ_TYPE_LEVEL_HIGH>; clocks = <&sysclk K230_SHRM_PDMA_AXI_GATE>, <&sysclk K230_SHRM_APB_GATE>, <&sysclk K230_SHRM_AXI_SLAVE_GATE>, <&sysclk K230_SHRM_SRAM_GATE>; #dma-cells = <4>; dma-channels = <8>; dma-requests = <35>; status = "okay"; }; // Audio (task 5.1, openspec/changes/the-mainline-shell-reaches- // parity). Addresses, compatible strings and dai-link phandles // copied from the vendor tree's own k230.dtsi (i2s@0x9140f000, // audio@0x9140f400, inno_codec@0x9140e000) and // nix/dts/k230-tdisplay.dts's own `sound` node -- same hardware, // same wiring, only clocks/compatible differ: // // - i2s: compatible is the vendor's // "canaan,snps,designware-i2s", bound by the forward-ported // sound/soc/dwc_canaan/canaan-dwc-i2s.c // (nix/patches/mainline/dwc_canaan/, // CONFIG_CANAAN_SND_DESIGNWARE_I2S) -- NOT mainline's own // generic "snps,designware-i2s"/sound/soc/dwc/dwc-i2s.c, which // this DT node used until a board boot showed starting ALSA // playback against it freezes the whole SoC (even with // clk_ignore_unused/pd_ignore_unused). The IP register map is // the same Synopsys DesignWare I2S core either way, but the // two drivers' i2s_start()/dw_i2s_hw_params() register // programming differs in K230-critical ways -- see // canaan-dwc-i2s.c's own header comment and // docs/research/mainline-audio-port.md for the finding. Every // other property on this node (reg, dmas/dma-names, clocks/ // clock-names) is unchanged: checked directly against the // vendor's own k230.dtsi i2s node, which carries no other // canaan,-prefixed property this driver reads. // - clocks: K230_LS_AUDIO_DEV_RATE (mainline's split rate // clock, vendor's single composite "audio_dev_clk"), // clock-names "i2sclk" matching dw_configure_dai_by_dt()'s // hardcoded clk_id. Its own clock-tree parent IS // K230_LS_AUDIO_DEV_GATE (drivers/clk/clk-k230.c: // ls_audio_dev_rate's hw parent is // &ls_audio_dev_gate.clk.hw), so claiming this one clock // cascade-enables the gate too through the common clock // framework's own parent-enable chain -- no second clock // needed on this node. // - dmas/dma-names: now carried forward from the vendor's own // `dmas = <&pdma 1 0xfff 0 0x14>, <&pdma 1 0xfff 0 0x15>;` // (k230.dtsi) exactly -- args are ; 0x14/0x15 are AUDIO_TX/AUDIO_RX in // the driver's enum ch_peri_dev_sel_t. The &pdma node above // now exists and registers a driver for "canaan,k230-pdma", // so dma_request_chan()'s of_dma phandle resolution can // succeed. Still deliberately NOT carrying an `interrupts` // property on this i2s node itself: the vendor's own // k230.dtsi i2s node has none either, and this SoC's real // PLIC line for the I2S IP itself (as opposed to the PDMA // controller, whose line IS known -- 203, above) is not // established in any source this project has. dw_i2s_probe() // takes the dmaengine_pcm branch either way now that a DMA // provider exists, so no interrupt property is needed for // this node to bind. i2s: i2s@9140f000 { compatible = "canaan,snps,designware-i2s"; reg = <0x0 0x9140f000 0x0 0x400>; dmas = <&pdma 1 0xfff 0 0x14>, <&pdma 1 0xfff 0 0x15>; dma-names = "tx", "rx"; clocks = <&sysclk K230_LS_AUDIO_DEV_RATE>; clock-names = "i2sclk"; status = "okay"; }; // The SAI register block (canaan_k230_audio.c, "canaan,k230-audio") // -- the digital mux between the Inno codec and the raw external // I2S pads. A separate register range and a separate clock branch // from the i2s node above: K230_LS_AUDIO_APB_GATE's parent is // ls_apb_src_rate, not ls_audio_dev_gate, so it does NOT // cascade-enable from the i2s node's clock claim and needs its // own, here. clock-names "apb" matches // canaan_k230_audio.c's devm_clk_get_optional_enabled() call. audio: audio@9140f400 { compatible = "canaan,k230-audio"; reg = <0x0 0x9140f400 0x0 0xc00>; clocks = <&sysclk K230_LS_AUDIO_APB_GATE>; clock-names = "apb"; status = "okay"; }; // The on-die Inno codec. K230_LS_CODEC_ADC_RATE/_DAC_RATE // cascade-enable K230_LS_CODEC_ADC_GATE/_DAC_GATE the same way // the i2s node's clock does above (drivers/clk/clk-k230.c: // ls_codec_adc_rate's/ls_codec_dac_rate's hw parent is their // matching _gate); K230_LS_CODEC_APB_GATE does not cascade from // either (its parent is ls_apb_src_rate) and is claimed // explicitly, clock-names "apb", matching // sound/soc/codecs/inno_k230.c's forward-ported probe. inno_codec: inno_codec@9140e000 { compatible = "canaan,k230-inno-codec"; reg = <0x0 0x9140e000 0x0 0x1000>; clocks = <&sysclk K230_LS_CODEC_APB_GATE>, <&sysclk K230_LS_CODEC_ADC_RATE>, <&sysclk K230_LS_CODEC_DAC_RATE>; clock-names = "apb", "adc", "dac"; status = "okay"; }; }; // The machine (card) driver. Same compatible, model string and // phandles as nix/dts/k230-tdisplay.dts's own `sound` node. // canaan,external-i2s-output-default is deliberately absent, matching // that file's own choice: boot through the Inno codec by default, the // external-I2S route is opt-in at runtime via the "External I2S Output // Switch" ALSA control. See nix/patches/canaan-audio-external-i2s- // switch.patch and nix/patches/mainline/canaan_k230_inno.c. sound { compatible = "canaan,k230-audio-inno"; canaan,model = "K230_I2S_INNO"; canaan,k230-i2s-controller = <&i2s>; canaan,k230-audio-codec = <&inno_codec>; status = "okay"; }; }; &uart0 { status = "okay"; }; &sysclk { clocks = <&osc24m>, <&timerx_pulse_in>; clock-names = "osc24m", "timer-pulse-in"; }; // The RTL8189FTV, over SDIO (task the-mainline-shell-reaches-parity 6.1). // no-1-8-v/rx_delay_line/tx_delay_line match nix/dts/k230-tdisplay.dts's own // &mmc_sd0 exactly (grounding tier 2: vendor source read directly). This // board's vendor DT wires no card-detect or Wi-Fi power/reset GPIO for this // function -- the RTL8189FTV module itself is read-only grep-confirmed absent // of a GPIO path in nix/dts/k230-tdisplay.dts, so none is added here either. // non-removable/cap-sdio-irq/keep-power-in-suspend are NOT in the vendor // source; they are the standard Linux mmc-core properties for a permanently // attached SDIO function with no card-detect line (see Documentation/ // devicetree/bindings/mmc/mmc-controller.yaml), added here because mainline's // generic SDHCI core -- unlike the vendor's own driver -- will otherwise poll // a nonexistent card-detect GPIO/pin for this function. UNVERIFIED against a // booted board: see docs/research/mainline-wifi-port.md. &mmc_sd0 { status = "okay"; no-1-8-v; rx_delay_line = <0x0d>; tx_delay_line = <0xc0>; non-removable; cap-sdio-irq; keep-power-in-suspend; }; / { sd_ref_clk: sd-ref-clock { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <100000000>; clock-output-names = "sd_ref"; }; }; // The TF/SD card: this milestone's rootfs device. Matches // nix/dts/k230-tdisplay.dts's own &mmc_sd1 overrides exactly // (no-1-8-v, cap-sd-highspeed, mshc_ctrl_r already set above). &mmc_sd1 { status = "okay"; no-1-8-v; cap-sd-highspeed; }; &gpio0 { status = "okay"; }; &gpio1 { status = "okay"; }; &usb0 { status = "okay"; }; &usb1 { status = "okay"; }; // The K230 upstream clock contract includes the SD AXI, card/block and // timer gates. The SDHCI max-clock source ("core") is the controller's // 100 MHz reference, as vendor k230.dtsi's dummy_sd: binding the 333 MHz // base gate there made the driver divide by 8 and run the card at 12.5 MHz // (6.1 vs 23.3 MB/s, docs/evidence/mainline-sd-throughput/). The base gate // stays claimed under "base". // Every mainline kernel patches the SD driver to claim all five. &mmc_sd1 { clocks = <&sd_ref_clk>, <&sysclk K230_HS_SD1_AHB_GATE>, <&sysclk K230_HS_SD1_BASE_GATE>, <&sysclk K230_HS_SD1_AXI_GATE>, <&sysclk K230_HS_SD1_CARD_GATE>, <&sysclk K230_HS_SD1_TIMER_GATE>; clock-names = "core", "bus", "base", "axi", "block", "timer"; }; // Same five-clock claim for the RTL8189FTV's SDIO controller (task // the-mainline-shell-reaches-parity 6.1). nix/patches/mainline/ // k230-sdhci-clocks.patch's dwcmshc_probe()/devm_clk_bulk_get() path is // generic over every "canaan,k230-dw-mshc" instance, not SD1-specific (the // three extra clk_bulk_data entries are requested by whichever device probes // the shared driver) -- so &mmc_sd0 needs the identical override, not a // smaller one. Every mainline kernel applies that patch (nix/kernel-mainline.nix). &mmc_sd0 { clocks = <&sd_ref_clk>, <&sysclk K230_HS_SD0_AHB_GATE>, <&sysclk K230_HS_SD0_BASE_GATE>, <&sysclk K230_HS_SD0_AXI_GATE>, <&sysclk K230_HS_SD0_CARD_GATE>, <&sysclk K230_HS_SD0_TIMER_GATE>; clock-names = "core", "bus", "base", "axi", "block", "timer"; }; // The RTC sits in the PMU block behind the PMU APB gate, which mainline // otherwise gates as unused; the RTC driver enables it from probe. &rtc { clocks = <&sysclk K230_PMU_APB_GATE>; clock-names = "pclk"; };