Re: [PATCH v6 3/3] arm64: dts: rockchip: Add Orange Pi 5 Pro board support

Dennis Gilmore
2026-04-14T14:07:54Z

On Sat, Apr 11, 2026 at 1:00 PM Alexey Charkov <alchark@gmail.com> wrote:
>
> On Sat, Apr 11, 2026 at 6:47 AM <dennis@ausil.us> wrote:
> >
> > From: Dennis Gilmore <dennis@ausil.us>
> >
> > Add device tree for the Xunlong Orange Pi 5 Pro (RK3588S).
> >
> > - eMMC module, you can optionally solder a SPI NOR in place and turn
> > off the eMMC
> > - PCIe-attached NIC (pcie2x1l1)
> > - PCIe NVMe slot (pcie2x1l2)
> > - AP6256 WiFi (BCM43456) via SDIO with mmc-pwrseq
> > - BCM4345C5 Bluetooth
> > - es8388 audio
> > - USB 2.0 and USB 3.0
> > - Two HDMI ports, the second is connected to the SoC's DP controller
> > driven by a transparent LT8711UXD bridge that has firmware onboard and
> > needs no node defined.
> >
> > Vendors description and links to schematics available:
> > http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-5-Pro.html
>
> Hi Dennis,
>
> The most useful of these is the schematic, so it's best to include a
> direct link to that in a dedicated Link: tag
>
> Link: https://drive.google.com/file/d/1qs1DratHuh7C6J6MEtQIwUsiSrg8qgTi/view

Will change to that, I did not do it because a random Google Drive
link doesn't really indicate it as a source of truth

> [schematic]
>
> > Signed-off-by: Dennis Gilmore <dennis@ausil.us>
> > ---
> > .../display/rockchip/rockchip,dw-dp.yaml | 7 +
> > arch/arm64/boot/dts/rockchip/Makefile | 1 +
> > .../dts/rockchip/rk3588s-orangepi-5-pro.dts | 352 ++++++++++++++++++
> > drivers/gpu/drm/bridge/synopsys/dw-dp.c | 12 +
>
> These should be three separate patches, never lumped together. First
> the binding change, next the driver change. They go together via the
> subsystem tree (likely DRM in this case). Then the DTS addition (or
> change) separately (it goes via the SoC tree).

They were something I was doing as I worked on getting the second HDMI
port working, they ended up not being needed, and I should have
removed it there really should have only been the dts and Makefile. I
should have waited until the morning to review again and send.

> > 4 files changed, 372 insertions(+)
> > create mode 100644 arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> >
> > diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > index 6345f0132d43..079a912d97f1 100644
> > --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > @@ -57,6 +57,13 @@ properties:
> > - const: i2s
> > - const: spdif
> >
> > + hpd-gpios:
> > + maxItems: 1
> > + description:
> > + GPIO used for hot plug detection when the controller's native HPD
> > + input is not connected. If not specified, the controller uses its
> > + internal HPD detection mechanism.
>
> Do you actually need this change? According to the schematic, the
> DP_HPDIN line from the DP-HDMI bridge is routed to the native
> DP0_HPDIN_M0 pin of the DP controller, so it shouldn't require this
> GPIO trick if the pinctrl is configured properly.

No I do not, It was an approach I had experimented with but did not
use and did not mean to include here.

> > phys:
> > maxItems: 1
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
> > index 4d384f153c13..c99dca2ae9e7 100644
> > --- a/arch/arm64/boot/dts/rockchip/Makefile
> > +++ b/arch/arm64/boot/dts/rockchip/Makefile
> > @@ -214,6 +214,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6c.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-odroid-m2.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5b.dtb
> > +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5-pro.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-cm5-base.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-radxa-cm5-io.dtb
> > dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-roc-pc.dtb
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> > new file mode 100644
> > index 000000000000..84c83aa69f63
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> > @@ -0,0 +1,352 @@
> > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> > +
> > +/dts-v1/;
> > +
> > +#include "rk3588s-orangepi-5.dtsi"
> > +
> > +/ {
> > + model = "Xunlong Orange Pi 5 Pro";
> > + compatible = "xunlong,orangepi-5-pro", "rockchip,rk3588s";
> > +
> > + aliases {
> > + mmc0 = &sdhci;
> > + mmc1 = &sdmmc;
> > + mmc2 = &sdio;
> > + };
> > +
> > + dp-con {
> > + compatible = "dp-connector";
>
> You don't have a physical DP connector on the board, so this node
> doesn't describe actual hardware, and is thus a no-go. What you have
> instead is an HDMI type A connector routed via an onboard DP to HDMI
> bridge, so you should describe exactly that in the device tree (a node
> for the HDMI connector, a node for the bridge, a node for the DP
> controller, and endpoints connected from the controller to the bridge,
> from the bridge to the connector). Please refer to the device tree for
> Radxa Rock 5 ITX, which has a similar setup (but a different bridge
> IC).
>
> I don't think your LT8711UXD has existing binding or driver entry, so
> a one-line patch will likely be needed to
> Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml,
> and a separate one to drivers/gpu/drm/bridge/simple-bridge.c. Separate
> ones :)

Will add in v7

> > + port {
> > + dp_con_in: endpoint {
> > + remote-endpoint = <&dp0_out_con>;
> > + };
> > + };
> > + };
> > +
> > + analog-sound {
> > + compatible = "simple-audio-card";
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&hp_detect>;
> > + simple-audio-card,bitclock-master = <&masterdai>;
> > + simple-audio-card,format = "i2s";
> > + simple-audio-card,frame-master = <&masterdai>;
> > + simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
> > + simple-audio-card,mclk-fs = <256>;
> > + simple-audio-card,name = "rockchip,es8388";
> > + simple-audio-card,routing =
> > + "Headphones", "LOUT1",
> > + "Headphones", "ROUT1",
> > + "LINPUT1", "Microphone Jack",
> > + "RINPUT1", "Microphone Jack",
> > + "LINPUT2", "Onboard Microphone",
> > + "RINPUT2", "Onboard Microphone";
> > + simple-audio-card,widgets =
> > + "Microphone", "Microphone Jack",
> > + "Microphone", "Onboard Microphone",
> > + "Headphone", "Headphones";
> > +
> > + simple-audio-card,cpu {
> > + sound-dai = <&i2s2_2ch>;
> > + };
> > +
> > + masterdai: simple-audio-card,codec {
> > + sound-dai = <&es8388>;
> > + system-clock-frequency = <12288000>;
> > + };
> > + };
> > +
> > + pwm-leds {
> > + compatible = "pwm-leds";
> > +
> > + led-0 {
> > + color = <LED_COLOR_ID_BLUE>;
> > + function = LED_FUNCTION_STATUS;
> > + linux,default-trigger = "heartbeat";
> > + max-brightness = <255>;
> > + pwms = <&pwm15 0 1000000 0>;
> > + };
> > +
> > + led-1 {
> > + color = <LED_COLOR_ID_GREEN>;
> > + function = LED_FUNCTION_ACTIVITY;
> > + linux,default-trigger = "heartbeat";
> > + max-brightness = <255>;
> > + pwms = <&pwm3 0 1000000 0>;
> > + };
> > + };
> > +
> > + fan: pwm-fan {
> > + compatible = "pwm-fan";
> > + #cooling-cells = <2>;
> > + cooling-levels = <0 50 100 150 200 255>;
> > + fan-supply = <&vcc5v0_sys>;
> > + pwms = <&pwm2 0 20000000 0>;
> > + };
> > +
> > + vcc3v3_dp: regulator-vcc3v3-dp {
> > + compatible = "regulator-fixed";
> > + enable-active-high;
> > + gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
>
> Please don't forget to add explicit pinctrl nodes for each GPIO pin
> you use (here and in other places like this). These GPIOs happen to
> work on Linux without configuring their pin control first, but that is
> pure luck and coincidence due to how the respective Linux subsystems
> are wired together, and if you ever need to use this device tree in
> e.g. U-boot (which also derives its DTS from the Linux kernel tree) it
> will break there.

Will do

> > + regulator-always-on;
> > + regulator-boot-on;
>
> Does it have to be always-on, boot-on? This looks like a hack to work
> around the fact that you didn't define the bridge node, which uses
> this as its supply. Please model the dependencies explicitly - most
> likely that will let you drop these attributes.

without these the the dp to HDMI bridge does not power up, and HPD
does not work,

> > + regulator-max-microvolt = <3300000>;
> > + regulator-min-microvolt = <3300000>;
>
> It's two separate regulators on your schematic, one DCDC at 1.25V and
> the other a load switch at 3.3V, driving six separate voltage inputs
> of the DP bridge. They are both controlled by the same GPIO pin
> though, so _maybe_ it's okay to have just one "virtual" node like this
> to model them together. Would be great for the DT maintainers to weigh
> in on this.
>
> > + regulator-name = "vcc3v3_dp";
> > + vin-supply = <&vcc_3v3_s3>;
> > + };
> > +
> > + vcc3v3_phy1: regulator-vcc3v3-phy1 {
> > + compatible = "regulator-fixed";
> > + enable-active-high;
> > + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
> > + regulator-boot-on;
>
> See above
>
> > + regulator-max-microvolt = <3300000>;
> > + regulator-min-microvolt = <3300000>;
> > + regulator-name = "vcc3v3_phy1";
> > + startup-delay-us = <50000>;
> > + vin-supply = <&vcc_3v3_s3>;
> > + };
> > +
> > + vcc5v0_otg: regulator-vcc5v0-otg {
> > + compatible = "regulator-fixed";
> > + enable-active-high;
> > + gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&vcc5v0_otg_en>;
> > + regulator-max-microvolt = <5000000>;
> > + regulator-min-microvolt = <5000000>;
> > + regulator-name = "vcc5v0_otg";
> > + vin-supply = <&vcc5v0_sys>;
> > + };
> > +
> > + sdio_pwrseq: sdio-pwrseq {
> > + compatible = "mmc-pwrseq-simple";
> > + clocks = <&hym8563>;
> > + clock-names = "ext_clock";
> > + post-power-on-delay-ms = <200>;
> > + reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_LOW>;
>
> This GPIO also needs a pinctrl
>
> > + };
> > +
> > + typea_con: usb-a-connector {
> > + compatible = "usb-a-connector";
> > + data-role = "host";
> > + label = "USB3 Type-A";
> > + power-role = "source";
> > + vbus-supply = <&vcc5v0_otg>;
> > + };
> > +};
> > +
> > +&dp0 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&dp0m0_pins>;
>
> This switches your HPD pin to the native DP controller handling
> (DP0_HPDIN_M0), so the GPIO bits you've patched into the controller
> driver aren't even used, and it doesn't look like you tested that code
> path.

Right, I had not meant to include. It was something I had worked on in
refactoring it and went a different route.

>
> > + status = "okay";
> > +};
> > +
> > +&dp0_in {
> > + dp0_in_vp1: endpoint {
> > + remote-endpoint = <&vp1_out_dp0>;
> > + };
> > +};
> > +
> > +&dp0_out {
> > + dp0_out_con: endpoint {
> > + remote-endpoint = <&dp_con_in>;
>
> This will need to be rewritten once you add the proper bridge chain
> leading up to the HDMI type A connector.

Yep

> > + };
> > +};
> > +
> > +&i2c1 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&i2c1m4_xfer>;
> > + status = "okay";
> > +};
> > +
> > +&i2c3 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&i2c3m0_xfer>;
> > + status = "okay";
> > +
> > + es8388: audio-codec@11 {
> > + compatible = "everest,es8388", "everest,es8328";
> > + reg = <0x11>;
> > + #sound-dai-cells = <0>;
> > + AVDD-supply = <&vcc_3v3_s0>;
>
> Are you sure? Schematic says VCCA_3V3_S0, which is a different
> regulator (PLDO4 output of the PMIC)
>
> > + DVDD-supply = <&vcc_1v8_s0>;
>
> Schematic says VCCA_1V8_S0, which is a different regulator (PLDO1
> output of the PMIC)
>
> > + HPVDD-supply = <&vcc_3v3_s0>;
>
> Schematic says VCCA_3V3_S0
>
> > + PVDD-supply = <&vcc_3v3_s0>;
>
> Schematic says VCCA_1V8_S0

I will rename these. It was what was used in the original orange pi 5
boards and was carried over, but looking at their schematics, they are
labeled the same so changing makes sense. after digging in the Pi 5
Pro names two of the regulators differently to the 5 and 5b. and the
naming of the current ones does not match the schematic

>
> > + assigned-clock-rates = <12288000>;
> > + assigned-clocks = <&cru I2S2_2CH_MCLKOUT>;
> > + clocks = <&cru I2S2_2CH_MCLKOUT>;
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&i2s2m1_mclk>;
> > + };
> > +};
> > +
> > +&i2c4 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&i2c4m3_xfer>;
> > + status = "okay";
> > +};
> > +
> > +&i2s2_2ch {
> > + pinctrl-0 = <&i2s2m1_lrck &i2s2m1_sclk
> > + &i2s2m1_sdi &i2s2m1_sdo>;
> > + status = "okay";
> > +};
> > +
> > +&package_thermal {
> > + polling-delay = <1000>;
> > +
> > + cooling-maps {
> > + map0 {
> > + trip = <&package_fan0>;
> > + cooling-device = <&fan THERMAL_NO_LIMIT 1>;
> > + };
> > +
> > + map1 {
> > + trip = <&package_fan1>;
> > + cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
> > + };
> > + };
> > +
> > + trips {
> > + package_fan0: package-fan0 {
> > + hysteresis = <2000>;
> > + temperature = <55000>;
> > + type = "active";
> > + };
> > +
> > + package_fan1: package-fan1 {
> > + hysteresis = <2000>;
> > + temperature = <65000>;
> > + type = "active";
> > + };
> > + };
> > +};
> > +
> > +/* NVMe */
> > +&pcie2x1l1 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&pcie30x1m1_1_clkreqn &pcie30x1m1_1_waken>;
> > + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
>
> The GPIO also needs a pinctrl
Will fix

> > + supports-clkreq;
> > + vpcie3v3-supply = <&vcc_3v3_s3>;
> > + status = "okay";
> > +};
> > +
> > +/* NIC */
> > +&pcie2x1l2 {
> > + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
>
> The GPIO also needs a pinctrl
Will fix

> > + vpcie3v3-supply = <&vcc3v3_phy1>;
> > + status = "okay";
> > +};
> > +
> > +&pinctrl {
> > + bluetooth {
> > + bt_wake_gpio: bt-wake-pin {
> > + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
> > + };
> > +
> > + bt_wake_host_irq: bt-wake-host-irq {
> > + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>;
> > + };
> > + };
> > +
> > + usb {
> > + vcc5v0_otg_en: vcc5v0-otg-en {
> > + rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
> > + };
> > + };
> > +
> > + wlan {
> > + wifi_host_wake_irq: wifi-host-wake-irq {
> > + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
> > + };
> > + };
> > +};
> > +
> > +&pwm15 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&pwm15m2_pins>;
> > + status = "okay";
> > +};
> > +
> > +&pwm2 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&pwm2m1_pins>;
> > + status = "okay";
> > +};
> > +
> > +&pwm3 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&pwm3m2_pins>;
> > + status = "okay";
> > +};
> > +
> > +&sdhci {
> > + status = "okay";
> > +};
> > +
> > +&sdio {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + bus-width = <4>;
> > + cap-sd-highspeed;
> > + cap-sdio-irq;
> > + keep-power-in-suspend;
> > + max-frequency = <150000000>;
> > + mmc-pwrseq = <&sdio_pwrseq>;
> > + no-mmc;
> > + no-sd;
> > + non-removable;
> > + sd-uhs-sdr104;
> > + status = "okay";
> > +
> > + ap6256: wifi@1 {
> > + compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
> > + reg = <1>;
> > + interrupt-names = "host-wake";
> > + interrupt-parent = <&gpio0>;
> > + interrupts = <RK_PA0 IRQ_TYPE_LEVEL_HIGH>;
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&wifi_host_wake_irq>;
> > + };
> > +};
> > +
> > +&uart9 {
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&uart9m2_xfer &uart9m2_ctsn &uart9m2_rtsn>;
> > + uart-has-rtscts;
> > + status = "okay";
> > +
> > + bluetooth {
> > + compatible = "brcm,bcm4345c5";
> > + clocks = <&hym8563>;
> > + clock-names = "lpo";
> > + device-wakeup-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
> > + interrupt-names = "host-wakeup";
> > + interrupt-parent = <&gpio0>;
> > + interrupts = <RK_PC5 IRQ_TYPE_LEVEL_HIGH>;
> > + max-speed = <1500000>;
> > + pinctrl-names = "default";
> > + pinctrl-0 = <&bt_wake_host_irq &bt_wake_gpio>;
> > + shutdown-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
> > + vbat-supply = <&vcc_3v3_s3>;
> > + vddio-supply = <&vcc_1v8_s3>;
> > + };
> > +};
> > +
> > +&usb_host0_xhci {
> > + dr_mode = "host";
> > +};
> > +
> > +&usbdp_phy0 {
> > + rockchip,dp-lane-mux = <0 1>;
>
> I'm wondering if the DP controller's "out" endpoint should go to the
> PHY instead of directly to the connector/bridge. That would describe
> the hardware better.

This was initially added to make sure that the type A port worked
because it uses lanes 2/3, and I needed to make sure 0/1, which route
to the dp were allocated. The DP PHY is already tied to the controller
via the phys property on &dp0 (inherited from rk3588s.dtsi), and the
lane mux is set via rockchip,dp-lane-mux on &usbdp_phy0. This matches
the convention used by rk3588-evb2-v10, rk3588s-coolpi-4b, and
rk3588s-indiedroid-nova — routing the dp0_out endpoint through the PHY
would diverge from the existing binding and all in-tree users.

> > +};
> > +
> > +&vp1 {
> > + vp1_out_dp0: endpoint@a {
> > + reg = <ROCKCHIP_VOP2_EP_DP0>;
> > + remote-endpoint = <&dp0_in_vp1>;
> > + };
> > +};
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > index fd23ca2834b0..b58f57b69b22 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > @@ -8,6 +8,7 @@
> > */
> > #include <linux/bitfield.h>
> > #include <linux/clk.h>
> > +#include <linux/gpio/consumer.h>
> > #include <linux/iopoll.h>
> > #include <linux/irq.h>
> > #include <linux/media-bus-format.h>
> > @@ -330,6 +331,8 @@ struct dw_dp {
> > u8 pixel_mode;
> >
> > DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
> > +
> > + struct gpio_desc *hpd_gpiod;
> > };
> >
> > enum {
> > @@ -481,6 +484,9 @@ static bool dw_dp_hpd_detect(struct dw_dp *dp)
> > {
> > u32 value;
> >
> > + if (dp->hpd_gpiod)
> > + return gpiod_get_value_cansleep(dp->hpd_gpiod);
> > +
> > regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
> >
> > return FIELD_GET(HPD_STATE, value) == DW_DP_HPD_STATE_PLUG;
> > @@ -2002,6 +2008,12 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> > return ERR_CAST(dp->regmap);
> > }
> >
> > + dp->hpd_gpiod = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);
>
> Not tested, not needed, why bother?..

this is not needed

> Best regards,
> Alexey

Thanks for the feedback

Dennis