// SPDX-License-Identifier: GPL-2.0
/*
* Nintendo Switch (Tegra X1 "ODIN" / ODNX02-A2) — mainline device tree.
*
* Stage 1: enough hardware to boot, talk, and mount a root filesystem.
* - CPU / GIC / timers / PMC come from tegra210.dtsi
* - console on UART-A (the retail Switch has no wired UART, so this is only
* useful for a modded board; the real console is the USB gadget below)
* - microSD (sdmmc1) so the ext4 root can be mounted
* - XUSB device controller (xudc) so the switchroot initramfs can create the
* configfs ACM gadget that gives us /dev/ttyGS0 — the only practical
* console on a retail unit
*
* Deliberately NOT here yet (stage 2/3): the MAX77620 PMIC + its regulators,
* the BCM4356 over PCIe, the DSI panel and the PWM backlight. Fixed regulators
* stand in for the PMIC so stage 1 does not depend on a driver that has not
* been validated yet.
*
* Note the path references such as &{/mmc@700b0000}: tegra210.dtsi defines
* these nodes without labels, so they can only be addressed by absolute path.
*/
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/gpio/tegra-gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/mfd/max77620.h>
#include "tegra210.dtsi"
/ {
model = "Nintendo Switch (ODNX02-A2)";
compatible = "nintendo,switch", "nvidia,tegra210";
aliases {
serial0 = &uarta;
mmc0 = "/mmc@700b0000";
};
chosen {
/*
* No stdout-path here: the obvious target (serial0 = &uarta) is
* disabled on this board, so pointing stdout-path at it just leaves
* the kernel without a console. The console is selected explicitly
* with console=tty0 on the kernel command line instead.
*
* access=m2 is what the switchroot initramfs greps for; usb_logging
* makes it create the ACM gadget. Keep both: without usb_logging the
* unit boots silent, and without access=m2 it will not hand over.
*/
bootargs = "console=tty0 keep_bootcon loglevel=7 rootwait rw access=m2 usb_logging auto_rootdev_disable";
#address-cells = <2>;
#size-cells = <2>;
/*
* The framebuffer hekate/U-Boot already set up, so a failed boot is
* not silent. of_platform looks for exactly this (a "simple-framebuffer"
* child of /chosen) and simpledrm binds to it, giving fb0 -> fbcon ->
* console=tty0 on the built-in display, before any display driver runs.
*
* Geometry is the panel's native orientation: 720x1280 with the DC
* rotating 90 degrees (nvidia,out-rotation = 90 in the L4T tree), so
* the scanout buffer is portrait. Address/size match the L4T kernel
* command line (tegra_fbmem=0x400000@0xf5a00000) and switch-fb.c.
*/
framebuffer@f5a00000 {
compatible = "simple-framebuffer";
reg = <0x0 0xf5a00000 0x0 0x00400000>;
width = <720>;
height = <1280>;
stride = <2880>;
format = "a8r8g8b8";
};
};
/*
* Keep the allocator off the framebuffer region: it lives inside the
* memory@80000000 range but belongs to the bootloader.
*
* Deliberately NOT "no-map": simpledrm ioremaps this range, and keeping it
* in the linear map removes a way for that mapping to fail.
*/
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
framebuffer@f5a00000 {
reg = <0x0 0xf5a00000 0x0 0x00400000>;
};
/*
* The same 2 MB region at 0xb0000000 that the L4T device tree
* reserves (there as compatible = "nvidia,ramoops"). The kernel has
* no console on this board and dies before userspace, so pstore is
* the only way to see the boot log: PSTORE_CONSOLE streams it into
* this buffer continuously, so a hang is recorded too, not just a
* panic. The boot script copies it to the SD for reading on a PC.
*/
ramoops@b0000000 {
compatible = "ramoops";
reg = <0x0 0xb0000000 0x0 0x00200000>;
record-size = <0x20000>; /* 128 KiB panic/dmesg record */
console-size = <0x80000>; /* 512 KiB continuous log */
pmsg-size = <0x20000>; /* 128 KiB */
max-reason = <2>; /* KMSG_DUMP_OOPS */
};
};
memory@80000000 {
device_type = "memory";
/*
* 2 GiB, matching the L4T device tree ("reg = <0x0 0x80000000 0x0
* 0x80000000>"). Do NOT widen this to the module's physical 4 GiB:
* Tegra X1 does not map DRAM as one contiguous 4 GiB block from
* 0x80000000, so a 4 GiB node hands the kernel memory it cannot
* address and it dies during memblock/paging init — before any
* console exists, which is a completely silent failure.
* U-Boot patches this node with the real banks when it boots Linux.
*/
reg = <0x0 0x80000000 0x0 0x80000000>;
};
/*
* 32.768 kHz clock feeding the PMC. tegra210.dtsi's pmc@7000e400
* references &clk32k_in, so every T210 board has to provide it or dtc
* fails with "Reference to non-existent node or label".
*/
clk32k_in: clock-32k {
compatible = "fixed-clock";
clock-frequency = <32768>;
#clock-cells = <0>;
};
/*
* PSCI + CPU enable-method.
*
* tegra210.dtsi declares the CPUs but provides NEITHER an enable-method nor
* a /psci node -- every T210 board has to add both (see tegra210-p3450-0000
* and tegra210-smaug). Without them arm64 never sets cpu_ops, and SMP
* bring-up dereferences a NULL pointer before console init: a completely
* silent death with nothing in the printk buffer and no output anywhere.
* This was the reason the first boots produced nothing at all.
*
* bl31.bin (ATF, loaded by hekate) provides the SMC-based PSCI service.
*/
cpus {
cpu@0 {
enable-method = "psci";
};
cpu@1 {
enable-method = "psci";
};
cpu@2 {
enable-method = "psci";
};
cpu@3 {
enable-method = "psci";
};
};
/*
* The arm64 arch timer needs the counter frequency from either CNTFRQ_EL0
* (programmed by firmware) or this property. tegra210.dtsi omits it, and
* this U-Boot does not set CNTFRQ_EL0 -- the L4T bootstack instead relies
* on the device tree, which is why the L4T tree carries
* clock-frequency = <0x124f800>.
*
* Without it arch_timer_detect_rate() fails, the kernel has no clock, and
* calibrate_delay() spins forever waiting for a jiffy that never arrives.
* That is a silent hang -- and with no timer there is no lockup detection,
* so no panic and no pstore dump either. It matches every observation,
* including why the identical kernel boots fine under QEMU (which provides
* the counter) and why it never reached userspace here.
*
* 19200000 Hz (19.2 MHz) is the T210 system counter.
*/
timer {
clock-frequency = <19200000>;
};
psci {
compatible = "arm,psci-1.0";
method = "smc";
};
/* Stage-1 stand-ins for the MAX77620 rails. */
vdd_3v3_sys: regulator-vdd-3v3-sys {
compatible = "regulator-fixed";
regulator-name = "vdd_3v3_sys";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vdd_1v8_sys: regulator-vdd-1v8-sys {
compatible = "regulator-fixed";
regulator-name = "vdd_1v8_sys";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
vdd_1v05_pex: regulator-vdd-1v05-pex {
compatible = "regulator-fixed";
regulator-name = "vdd_1v05_pex";
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
regulator-always-on;
};
/*
* MicroSD. This is the card the root filesystem lives on, so it is the
* single most important peripheral for stage 1.
*/
mmc@700b0000 {
status = "okay";
bus-width = <4>;
/*
* Card detect. The L4T tree gives this node
* cd-gpios = <0x5c 0xc9 0x00> plus cd-inverted: phandle 0x5c is the
* GPIO controller and 0xc9 == 201 == TEGRA_GPIO(Z, 1), active low.
* Mainline's own T210 board (Jetson Nano, tegra210-p3450-0000) uses
* exactly the same pin for SDMMC1.
*
* Without it the SDHCI controller falls back to its own card-detect
* bit, which is not wired on this board. It reports "no card", no
* mmcblk0 is ever created, and the kernel dies at
* "VFS: Unable to mount root fs on unknown-block(0,0)".
*/
cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
disable-wp;
/*
* The SD pads run at 3.3 V and there is no way to switch them: the
* rails below are regulator-fixed stand-ins, not the real MAX77620.
* So report 3.3 V for the I/O rail too -- otherwise the core asks
* for a 1.8 V UHS signal the hardware cannot produce -- and mark
* 1.8 V unsupported so the card stays at high speed.
*/
no-1-8-v;
vmmc-supply = <&vdd_3v3_sys>;
vqmmc-supply = <&vdd_3v3_sys>;
};
/* USB-C port: device mode (the console). */
padctl@7009f000 {
status = "okay";
avdd-pll-utmip-supply = <&vdd_1v8_sys>;
avdd-pll-uerefe-supply = <&vdd_1v05_pex>;
dvdd-pex-pll-supply = <&vdd_1v05_pex>;
hvdd-pex-pll-e-supply = <&vdd_1v8_sys>;
pads {
usb2 {
status = "okay";
lanes {
usb2-0 {
nvidia,function = "xusb";
status = "okay";
};
usb2-1 {
nvidia,function = "xusb";
status = "okay";
};
usb2-2 {
nvidia,function = "xusb";
status = "okay";
};
};
};
pcie {
status = "okay";
lanes {
pcie-0 {
nvidia,function = "pcie-x1";
status = "okay";
};
pcie-1 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-2 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-3 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-4 {
nvidia,function = "pcie-x4";
status = "okay";
};
};
};
};
ports {
/*
* The USB-C port. It is the console, so it must come up as
* a *device*. mode "otg" (or "peripheral") is mandatory to
* pair with usb-role-switch, which the driver requires --
* without that property it returns -EINVAL and the whole
* padctl fails to probe:
*
* usb2-0: usb-role-switch not found for otg mode
* tegra-xusb-padctl: failed to setup XUSB ports: -22
*
* role-switch-default-mode = "peripheral" makes the port
* default to the device role without needing an ID pin or
* an external role-switch driver.
*/
usb2-0 {
status = "okay";
mode = "otg";
usb-role-switch;
role-switch-default-mode = "peripheral";
vbus-supply = <&vdd_3v3_sys>;
};
usb2-1 {
status = "okay";
mode = "host";
};
usb2-2 {
status = "okay";
mode = "host";
};
};
};
usb@700d0000 {
status = "okay";
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>;
/*
* The driver looks this PHY up by name: tegra_xudc_probe() builds
* "usb2-%d" and calls devm_phy_optional_get(), then registers its
* VBUS notifier on the usb_phy it finds. Because the lookup is
* *optional*, a wrong name here fails silently: usbphy[0] stays
* NULL, the notifier is never registered, xudc->device_mode never
* becomes true, and the device never connects to a host -- the
* gadget binds and /dev/ttyGS0 appears, but nothing enumerates.
*/
phy-names = "usb2-0";
/*
* The published USB gadget that /sbin/init builds is what we
* actually want here, not a role switch.
*/
dr_mode = "peripheral";
};
usb@70090000 {
status = "okay";
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
<&{/padctl@7009f000/pads/usb2/lanes/usb2-1}>,
<&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>;
phy-names = "usb2-0", "usb2-1", "usb2-2";
};
/*
* PCIe, for the BCM4356 WiFi.
*
* The L4T tree puts the WiFi on PCIe port 1 (`pci@2,0`), one lane, on the
* padctl's `pcie-0` lane, and leaves port 0 unused with
* `nvidia,sw-link-disable`. Mainline wants exactly three supplies on T210
* -- see tegra_pcie_get_regulators() in drivers/pci/controller/pci-tegra.c,
* which matches "nvidia,tegra210-pcie" and asks for hvddio-pex,
* dvddio-pex and vddio-pex-ctl and nothing else.
*
* Without this node the controller stays disabled, nothing is logged
* about PCIe at all, and there is no wlan0.
*/
pcie@1003000 {
/*
* Disabled again. switchroot's mainline tree enables both ports and
* carries lanes pcie-1..pcie-4, and both of those were gaps here --
* but adding them did NOT make the endpoint answer config cycles.
* The kernel still panics on the first config read:
*
* SError Interrupt ... pci_generic_config_read
* tegra_pcie_config_read / tegra_pcie_probe
*
* So the missing lanes were not the cause. What is established, for
* whoever picks this up:
*
* - the controller must be enabled, and it trains the link
* - the BCM4356 is powered from MAX77620 sd3/ldo1/ldo7; ldo1
* ("vdd-pex") is off in L4T until a consumer enables it, and that
* is what made the link train at all
* - the gating pins (wifi_en_ph0, wifi_rst_ph1) are muxed and driven
* - the endpoint still does not respond, so the next lead is a
* proper reset pulse on wifi_rst after the rails are stable,
* rather than driving it high from the first instant
*
* The ports, lanes and supplies below are kept so re-enabling is one
* line once the endpoint is understood.
*/
status = "disabled";
hvddio-pex-supply = <&vdd_1v8_sys>;
dvddio-pex-supply = <&vdd_1v05_pex>;
vddio-pex-ctl-supply = <&vdd_1v8_sys>;
pinctrl-names = "default";
pinctrl-0 = <&wifi_pins>;
pci@1,0 {
status = "okay";
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
phy-names = "pcie-0", "pcie-1", "pcie-2", "pcie-3";
nvidia,num-lanes = <4>;
};
pci@2,0 {
status = "okay";
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
phy-names = "pcie-0";
nvidia,num-lanes = <1>;
};
};
/*
* The BCM4356 is gated by two dedicated Tegra pins, and nothing
* configures them in mainline. Both show up unconfigured in the pinctrl
* debugfs pinconf dump, the chip is therefore never enabled and never
* released from reset, and PCIe reports "link 1 down, ignoring" -- the
* controller is fine, the device is dead.
*
* mainline's pinctrl-tegra210.c knows both pins by name (they are real
* PINGROUP entries). Mux them as GPIO outputs; the hogs below then drive
* them high. The L4T tree configures the same two pins the same way.
*/
pinmux@700008d4 {
wifi_pins: wifi-pins {
wifi-en-ph0 {
nvidia,pins = "wifi_en_ph0";
nvidia,function = "rsvd0";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,open-drain = <TEGRA_PIN_DISABLE>;
};
wifi-rst-ph1 {
nvidia,pins = "wifi_rst_ph1";
nvidia,function = "rsvd0";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,open-drain = <TEGRA_PIN_DISABLE>;
};
};
/*
* i2c3 leaves the SoC on the gen3_i2c pins. The vendor DT and
* switchroot's both configure these two; switchroot does it via
* a single pinmux_default group applied by the pinmux node, we
* do it per device. Without it the bus is left tri-stated, the
* touchscreen at 0x49 never acknowledges, and probe fails with
* -110.
*/
i2c3_pins: i2c3-pins {
gen3-i2c-scl-pf0 {
nvidia,pins = "gen3_i2c_scl_pf0";
nvidia,function = "i2c3";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,io-high-voltage = <TEGRA_PIN_DISABLE>;
};
gen3-i2c-sda-pf1 {
nvidia,pins = "gen3_i2c_sda_pf1";
nvidia,function = "i2c3";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,io-high-voltage = <TEGRA_PIN_DISABLE>;
};
};
/*
* The touchscreen's interrupt pin. It is deliberately not used
* as an interrupt (see the node below), but it still has to be
* terminated: the vendor DT configures it as a GPIO input with
* a pull-up, and leaving it floating is what made the
* level-low interrupt assert continuously.
*/
touch_pins: touch-pins {
touch-int-px1 {
nvidia,pins = "touch_int_px1";
nvidia,function = "rsvd0";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
};
/*
* The Joy-Con rail UARTs. These are ordinary pinmux pins, not
* padctl lanes, so configuring them cannot disturb the USB/PCIe
* lanes the console depends on. uartb carries the right Joy-Con,
* uartc the left; switchroot's DT uses the same pins and
* functions.
*/
uartb_pins: uartb-pins {
uart2-tx-pg0 {
nvidia,pins = "uart2_tx_pg0";
nvidia,function = "uartb";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
};
uart2-rx-pg1 {
nvidia,pins = "uart2_rx_pg1";
nvidia,function = "uartb";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
uart2-rts-pg2 {
nvidia,pins = "uart2_rts_pg2";
nvidia,function = "uartb";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
};
uart2-cts-pg3 {
nvidia,pins = "uart2_cts_pg3";
nvidia,function = "uartb";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
};
uartc_pins: uartc-pins {
uart3-tx-pd1 {
nvidia,pins = "uart3_tx_pd1";
nvidia,function = "uartc";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
};
uart3-rx-pd2 {
nvidia,pins = "uart3_rx_pd2";
nvidia,function = "uartc";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
uart3-rts-pd3 {
nvidia,pins = "uart3_rts_pd3";
nvidia,function = "uartc";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
};
uart3-cts-pd4 {
nvidia,pins = "uart3_cts_pd4";
nvidia,function = "uartc";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
};
};
gpio@6000d000 {
wifi-en-hog {
gpio-hog;
gpios = <TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
output-high;
line-name = "wifi-en";
};
wifi-rst-hog {
gpio-hog;
gpios = <TEGRA_GPIO(H, 1) GPIO_ACTIVE_HIGH>;
output-high;
line-name = "wifi-rst";
};
};
/*
* The PMIC, and the real reason the PCIe link never trained.
*
* The BCM4356 is powered from three MAX77620 rails: sd3 ("vdd-1v8"),
* ldo1 ("vdd-pex") and ldo7 ("vdd-gen-pll-edp"). In the L4T tree the
* PCIe controller takes them as hvddio-pex / dvddio-pex / vddio-pex-ctl
* and the padctl takes them as avdd-pll-uerefe / dvdd-pex-pll, and
* enabling them is what powers the chip.
*
* Crucially, ldo1 and ldo7 have neither regulator-boot-on nor
* regulator-always-on in L4T: they are *off* until a consumer asks for
* them. Our device tree stood in for these with regulator-fixed
* regulators, which the kernel treats as always-on but which never touch
* the PMIC -- so ldo1 and ldo7 stayed off, the chip stayed unpowered, and
* PCIe reported "link 1 down" regardless of what the gating pins did.
*
* These three rails are declared regulator-always-on as a bring-up
* shortcut. It keeps every existing consumer on its regulator-fixed
* stand-in -- so a PMIC that fails to probe cannot break the working USB
* or SD paths -- while actually switching the PEX rails on. Wiring the
* consumers to these rails directly is the tidier follow-up once the
* PMIC is proven.
*
* The interrupt is GIC SPI 86: the L4T node carries
* "interrupts = <0x00 0x56 0x00>" with the parent inherited (the GIC),
* and 0x56 is 86. Mainline's own T210 board, tegra210-p2894, uses
* <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH> for the same PMIC.
*/
i2c@7000d000 {
status = "okay";
clock-frequency = <400000>;
/*
* Deliberately NO pinctrl state here. An earlier attempt added one
* (pwr_i2c_scl_py3 / pwr_i2c_sda_py4 -> "i2cpmu") copying L4T, and
* it broke the PMIC outright:
*
* max77620 0-003c: Failed to read CID: -110
* max77620 0-003c: probe with driver max77620 failed with error -110
*
* Without it the PMIC probes fine, because U-Boot has already left
* the power-I2C pins in a working state and the Tegra pinmux driver
* only writes pins a DT state names. Overriding them was strictly
* worse.
*/
max77620: max77620@3c {
compatible = "maxim,max77620";
reg = <0x3c>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
pinctrl-names = "default";
pinctrl-0 = <&max77620_default>;
/*
* Copied from the L4T tree. gpio2 and gpio3 are not plain
* GPIOs on this board: they are FPS outputs, and the 3.3 V
* rail the WiFi I/O needs is gated by that sequencer, not
* by software. Leaving the PMIC's pinmux and fps nodes out
* (as the first attempt did) leaves the sequencer
* unconfigured and that rail off.
*/
max77620_default: pinmux {
gpio0 {
pins = "gpio0";
function = "gpio";
};
gpio1 {
pins = "gpio1";
function = "gpio";
};
gpio2 {
pins = "gpio2";
function = "fps-out";
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
maxim,active-fps-power-up-slot = <0>;
maxim,active-fps-power-down-slot = <7>;
};
gpio3 {
pins = "gpio3";
function = "fps-out";
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
maxim,active-fps-power-up-slot = <4>;
maxim,active-fps-power-down-slot = <2>;
};
gpio4 {
pins = "gpio4";
function = "32k-out1";
};
gpio5-7 {
pins = "gpio5", "gpio6", "gpio7";
function = "gpio";
};
};
/* Children are matched by node name: fps%d. */
fps {
fps0 {
maxim,shutdown-fps-time-period-us = <5120>;
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
};
fps1 {
maxim,shutdown-fps-time-period-us = <5120>;
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
maxim,device-state-on-disabled-event = <MAX77620_FPS_INACTIVE_STATE_SLEEP>;
};
fps2 {
maxim,shutdown-fps-time-period-us = <5120>;
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
};
};
regulators {
max77620_sd3: sd3 {
regulator-name = "vdd-1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
};
max77620_ldo1: ldo1 {
regulator-name = "vdd-pex";
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
regulator-always-on;
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
};
max77620_ldo7: ldo7 {
regulator-name = "vdd-gen-pll-edp";
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
regulator-always-on;
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
};
/*
* The touchscreen's analogue rail -- the vendor DT
* calls it "vdd-tp-2v9", and this is the same
* ldo6. Not always-on: the stmfts driver enables
* it itself through its "avdd" supply. It *is*
* boot-on, matching the vendor, so the rail is
* live before the driver's first I2C access.
* FPS_SRC_NONE keeps the PMIC's FPS machinery
* from gating it behind a power-up slot.
*/
avdd_touchscreen: ldo6 {
regulator-name = "AVDD_TOUCHSCREEN";
regulator-min-microvolt = <2900000>;
regulator-max-microvolt = <2900000>;
regulator-boot-on;
regulator-always-on;
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
};
};
};
};
/*
* Touchscreen. An STMicroelectronics FTS controller at 0x49 on i2c3,
* interrupting on PX1. The wiring, the rails and the IRQ-enable
* register come from switchroot's DT (reference/switchroot-mainline/).
*
* The controller powers up with its interrupt generation masked, which
* is why interrupt-enable-reg is needed at all: without it the reset
* command's status event never arrives and the driver times out. That
* support is patches/kernel-stmfts-switch.patch.
*
* The native axes are 1280x720 while the panel is 720x1280 -- the
* digitiser is rotated relative to the display, hence swapped-x-y.
* The driver applies it through touchscreen_report_pos().
*
* No pinctrl state here, for the same reason i2c@7000d000 has none:
* the bootloader leaves the pins muxed, and adding a state is what
* broke the PMIC on the other bus.
*/
i2c@7000c500 {
status = "okay";
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c3_pins>;
touchscreen@49 {
compatible = "st,stmfts";
reg = <0x49>;
/*
* No "interrupts" here, on purpose. The pin is level-low
* and nothing terminates it, so the interrupt asserts
* continuously: the handler then runs non-stop, eats the
* controller's ready event before the reset can read it,
* and starves the poll loop on the mutex. The symptom is
* a probe that fails with -110 after ~90 seconds.
*
* The pin is still configured (touch_pins above) so it
* is not left floating, and everything is driven by the
* driver's poll thread instead. Re-enable this once PX1
* is understood.
*/
pinctrl-names = "default";
pinctrl-0 = <&touch_pins>;
/*
* No "interrupt-enable-reg" either. switchroot's patch
* 0011 used it (0x2c = 0x48) to make the controller
* signal its status event by interrupt, but this driver
* polls the event FIFO instead, and this part answers
* that write with an error event.
*/
avdd-supply = <&avdd_touchscreen>;
vdd-supply = <&vdd_touchscreen>;
touchscreen-size-x = <1280>;
touchscreen-size-y = <720>;
touchscreen-swapped-x-y;
};
};
/*
* Joy-Con rails. These are UARTs and the controllers speak HID over
* them -- a path mainline's hid-nintendo does not cover (that one is
* USB/Bluetooth). The driver is drivers/joycon.c, installed into the
* tree by install_switch_joycon().
*
* Deliberately no nvidia,invert-txd / nvidia,invert-rts, unlike
* switchroot's DT: mainline's serial-tegra.c does not implement those
* properties (TEGRA_UART_IRDA_CSR is defined there and never used).
* Testing without inversion first, since if the rails talk the property
* was vestigial -- and the IRDA_CSR bit layout would otherwise have to
* come from the vendor driver rather than be guessed.
*/
serial@70006040 {
status = "okay";
compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
pinctrl-names = "default";
pinctrl-0 = <&uartb_pins>;
/* right Joy-Con */
joycon {
compatible = "nintendo,joycon-uart";
charge-gpios = <&gpio TEGRA_GPIO(K, 3) GPIO_ACTIVE_HIGH>;
};
};
serial@70006200 {
status = "okay";
compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
pinctrl-names = "default";
pinctrl-0 = <&uartc_pins>;
/* left Joy-Con */
joycon {
compatible = "nintendo,joycon-uart";
charge-gpios = <&gpio TEGRA_GPIO(CC, 3) GPIO_ACTIVE_HIGH>;
};
};
/*
* Display. The panel is a JDI LPM062M326A (720x1280 DSI) -- identified
* from switchroot's mainline device tree, along with the wiring, the
* rails and the backlight below. The vendor kernel keeps the panel's
* timings and init sequence in C, which is why none of this could be
* derived from the L4T device tree.
*
* See reference/switchroot-mainline/README.md and
* device-tree/panel-jdi-lpm062m326a.c.
*/
pwm@7000a000 {
status = "okay";
};
backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm 0 35000>;
pwm-names = "backlight";
brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 51 52 53 54 55 56 57 58
59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86
87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
default-brightness-level = <80>;
/* Backlight enable, PV1 -- the L4T tree calls this lcd-bl-en. */
enable-gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
};
/* Panel rails, from the L4T tree and switchroot's DT. */
pavdd: regulator-pavdd {
compatible = "regulator-fixed";
regulator-name = "pavdd";
regulator-min-microvolt = <5400000>;
regulator-max-microvolt = <5400000>;
gpio = <&gpio TEGRA_GPIO(I, 0) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
navdd: regulator-navdd {
compatible = "regulator-fixed";
regulator-name = "navdd";
regulator-min-microvolt = <5400000>;
regulator-max-microvolt = <5400000>;
gpio = <&gpio TEGRA_GPIO(I, 1) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
vdd_dsi_csi: regulator-dsi-csi {
compatible = "regulator-fixed";
regulator-name = "AVDD_DSI_CSI_1V2";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
gpio = <&max77620 7 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-always-on;
regulator-boot-on;
};
/*
* The touchscreen's digital rail, gated by PJ7. The driver switches it
* through its "vdd" supply, but it is also always-on: the probe fails
* (see patches/kernel-stmfts-switch.patch), and on failure the driver
* disables its supplies, which powers the controller down and takes
* 0x49 off the bus. Keeping VIO up leaves the chip addressable with
* i2ctransfer after a failed probe, which is how the protocol below
* was worked out. Revert to a plain switched rail once the driver
* probes cleanly.
*/
vdd_touchscreen: regulator-touchscreen {
compatible = "regulator-fixed";
regulator-name = "vdd_touchscreen";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&gpio TEGRA_GPIO(J, 7) GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-always-on;
};
};
/*
* The DC and the DSI are children of host1x@50000000 in tegra210.dtsi, so they
* must be addressed by full path or by label.
*
* Writing `dsi@54300000` at the root instead -- as this tree did at first --
* creates a *second*, disconnected node, because a device tree merges by path.
* The real DSI then stays "disabled", the panel never attaches, and the result
* is a DRM device with no connectors: card0 and renderD128 but no DSI-1.
*/
&{/host1x@50000000/dc@54200000} {
status = "okay";
};
&dsia {
status = "okay";
avdd-dsi-csi-supply = <&vdd_dsi_csi>;
panel@0 {
compatible = "jdi,lpm062m326a";
reg = <0>;
reset-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
vdd1-supply = <&pavdd>;
vdd2-supply = <&navdd>;
backlight = <&backlight>;
};
};