Migrating device tree for Udooneo from 4.1 to 6.6 : Display (LVDS)

Discussion in 'UDOO NEO' started by CartonDu, Oct 10, 2025.

  1. CartonDu

    CartonDu UDOOer

    Joined:
    Apr 23, 2018
    Messages:
    7
    Likes Received:
    0
    Hi,

    I’m migrating a device from Yocto thud to scarthgap and moving from a custom 4.1 kernel (fmntf/linux_kernel 4.1.15_2.x-udoo) to linux-fslc-imx 6.6. Hardware is Udooneo Extended (iMX6SoloX) with the stock 7" LVDS panel (UMSH-8596MD-20T w/ DS90CF364 + ST1332 touch).

    Goal: run X11 with etnaviv (hardware accelerate) because the newer imx-viv-gpu doesn’t support X11 for our Electron apps.

    What works:
    • Screen backlight and splash are visible during early boot.
    • Touch works.
    Problem:
    • At a certain point during boot the LVDS image gets heavy tearing/grey lines. X starts but the same tearing appears. Looks like a mode/driver handover problem.
    What I’m attaching (below):
    • current device-tree fragment (imx6sx-udoo-neo-lvds7.dtsi).
    • some useful logs and outputs I captured (dmesg, Xorg log, /dev/dri listing).
    Current device-tree fragment (imx6sx-udoo-neo-lvds7.dtsi) which is mostly the same as the one from kernel 4.1:
    Code:
    / {
       reg_lcd_pwr: regulator-lcdpwr {
           compatible = "regulator-fixed";
           regulator-name = "LCD POWER";
           gpio = <&gpio4 27 GPIO_ACTIVE_LOW>;
           enable-active-high;
           regulator-boot-on;
           regulator-always-on;
           status = "okay";
       };
    
       backlight_regulator: regulator-backlight {
           compatible = "regulator-fixed";
           regulator-name = "LCD BACKLIGHT BL_ON";
           gpio = <&gpio6 3 GPIO_ACTIVE_LOW>;
           enable-active-high;
           regulator-boot-on;
           regulator-always-on;
       };
    };
    
    &lcdif2 {
       display = <&display1>;
       disp-dev = "ldb";
       status = "okay";
       display1: display@1 {
           bits-per-pixel = <16>;
           bus-width = <18>;
       };
    };
    
    &ldb {
       pinctrl-names = "default";
       pinctrl-0 = <&pinctrl_ldb_0>;
       lcd-supply = <&reg_lcd_pwr
                       &backlight_regulator>;
       status = "okay";
       lvds-channel@0 {
           fsl,data-mapping = "spwg";
           fsl,data-width = <18>;
           crtc = "lcdif2";
           status = "okay";
           display-timings {
               native-mode = <&timing1>;
               timing1: LDB-WVGA {
                   clock-frequency = <33660000>;
                   hactive = <800>;
                   vactive = <480>;
                   hback-porch = <56>;
                   hfront-porch = <50>;
                   vback-porch = <23>;
                   vfront-porch = <20>;
                   hsync-len = <150>;
                   vsync-len = <2>;
               };
           };
       };
    };
    
    &i2c1 {
       touchscreen: st1232@55 {
           compatible = "sitronix,st1232";
           reg = <0x55>;
           interrupt-parent = <&gpio6>;
           interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
           pinctrl-0 = <&pinctrl_st1232>;
           pinctrl-names = "default";
           gpios = <&gpio6 5 GPIO_ACTIVE_LOW>;
       };
    };
    
    &dcic2 {
       dcic_id = <1>;
       dcic_mux = "dcic-lvds";
       status = "okay";
    };
    
    &lcdif1 {    /* Disable HDMI */
       status = "disabled";
    };
    
    &i2c3 {        /* Disable HDMI */
       status = "disabled";
    };
    Here's some logs and outputs:

    Code:
    user@host:~# dmesg | grep -E "etnaviv|drm|mxsfb"
    [    1.236707] etnaviv etnaviv: bound 1800000.gpu (ops 0xc0d7c0b8)
    [    1.244047] etnaviv-gpu 1800000.gpu: model: GC400, revision: 4645
    [    1.250843] etnaviv-gpu 1800000.gpu: Need to move linear window on MC1.0, disabling TS
    [    1.259865] [drm] Initialized etnaviv 1.4.0 20151214 for etnaviv on minor 0
    [    1.267241] Error: Driver 'mxsfb' is already registered, aborting...
    [    2.141557] mxsfb 2224000.lcdif: supply lcd not found, using dummy regulator
    [    2.237241] mxsfb 2224000.lcdif: registered mxc display driver ldb
    [    2.342101] mxsfb 2224000.lcdif: initialized
    user@host:~# ls /dev/dri/
    by-path  card0    renderD128
    user@host:~# ls /usr/lib/xorg/modules/drivers/modesetting_drv.so
    /usr/lib/xorg/modules/drivers/modesetting_drv.so
    user@host:~# grep -E "(EE|WW|etnaviv|modesetting|DRM)" /var/log/Xorg.0.log
    [   110.902] Current Operating System: Linux pad2 6.6.101-lf-6.6.y-lf-6.6.y-g36cee4c51e9a #1 PREEMPT Fri Aug  8 14:52:48 UTC 2025 armv7l
       (WW) warning, (EE) error, (NI) not implemented, (??) unknown.
    [   110.944] (WW) The directory "/usr/share/fonts/X11/misc" does not exist.
    [   110.944] (WW) The directory "/usr/share/fonts/X11/TTF" does not exist.
    [   110.944] (WW) The directory "/usr/share/fonts/X11/OTF" does not exist.
    [   110.944] (WW) The directory "/usr/share/fonts/X11/Type1" does not exist.
    [   110.944] (WW) The directory "/usr/share/fonts/X11/100dpi" does not exist.
    [   110.945] (WW) The directory "/usr/share/fonts/X11/75dpi" does not exist.
    [   110.966] (II) Platform probe for /sys/devices/platform/etnaviv/drm/card0
    [   111.079]     falling back to /sys/devices/platform/etnaviv/drm/card0
    [   111.416] (WW) Falling back to old probe method for fbdev
    [   111.707] (II) Initializing extension MIT-SCREEN-SAVER
    [   114.495] (II) XINPUT: Adding extended input device "st1232-touchscreen" (type: TOUCHSCREEN, id 6)
    user@host:~# glxinfo | grep -E "OpenGL renderer|OpenGL vendor"
    Error: unable to open display
    user@host:~# export DISPLAY=:0
    user@host:~# glxinfo | grep -E "OpenGL renderer|OpenGL vendor"
    Error: unable to open display :0
    What I expect:
    • a stable LVDS framebuffer handed to KMS/etnaviv and a working X11 modesetting driver with hw accel (no tearing).
    What I’ve already tried:
    • Using etnaviv (driver loads; /dev/dri/card0 exists).
    • Confirmed modesetting driver is present.
    • Left LVDS node mostly identical to old 4.1 .dtsi.
    Questions / hints I think are relevant (please point out if I’m wrong):
    1. Is the tearing likely caused by a DT timing mismatch or by a double-driver handover (mxsfb vs. etnaviv/modesetting)? I see Error: Driver 'mxsfb' is already registered, aborting....
    2. Do I need to enable/disable specific kernel CONFIGs (fbdev vs drm/KMS) or build etnaviv as builtin vs module for a clean handover?
    3. Are there DT properties I’m missing for the LDB -> lcdif2 CRTC mapping (crtc name, fsl,data-mapping, pixelclock) that would cause visible tearing?
    4. Anything obvious in the dts that will break atomic modeset / KMS?
    What I can provide on request:
    • uname -a, kernel .config, full dmesg, lsmod, cat /proc/fb, cat /sys/class/drm/*/status, and the full Xorg.0.log.
    Thanks for any pointers. I’m new to modern KMS/DT handover so please tell me bluntly if I misunderstood something.

    Hope someone is still active here :)
     
  2. CartonDu

    CartonDu UDOOer

    Joined:
    Apr 23, 2018
    Messages:
    7
    Likes Received:
    0
    I had to move away from meta-freescale and Freescale/NXP kernels. I'm using now linux-stable_6.12.bb from layer meta-linux-mainline (scarthgap) with following DTSI:
    Code:
    / {
        reg_lcd_pwr: lcd_pwr {
            compatible = "regulator-fixed";
            regulator-name = "LCD POWER";
            gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
            enable-active-high;
            regulator-boot-on;
        };
    
        backlight_lvds: backlight {
            compatible = "gpio-backlight";
            gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>;
            default-on;
        };
    
        panel_lvds: panel-lvds {
            compatible = "umsh,8596md-20t", "panel-lvds";
            width-mm = <152>;
            height-mm = <91>;
            data-mapping = "jeida-18";
            power-supply = <&reg_lcd_pwr>;
            backlight = <&backlight_lvds>;
            status = "okay";
    
            panel-timing {
                clock-frequency = <33600000>;
                hactive = <800>;
                vactive = <480>;
                hback-porch = <56>;
                hfront-porch = <50>;
                vback-porch = <23>;
                vfront-porch = <20>;
                hsync-len = <150>;
                vsync-len = <2>;
    
                hsync-active = <0>;
                vsync-active = <0>;
                de-active = <1>;
                pixelclk-active = <0>;
            };
    
            port {
                panel_in: endpoint {
                    remote-endpoint = <&lvds_bridge_out>;
                };
            };
        };
    };
    
    &gpu { /* Vivante GC400T */
        status = "okay";
    };
    
    &lcdif1 {
        status = "okay";
    
        port {
            lcdif_out: endpoint {
                remote-endpoint = <&lvds_bridge_in>;
            };
        };
    };
    
    &clks {
        assigned-clocks = <&clks IMX6SX_CLK_PLL5_VIDEO>,
                    <&clks IMX6SX_CLK_LDB_DI0_SEL>,
                    <&clks IMX6SX_CLK_LCDIF1_PRED>,
                    <&clks IMX6SX_CLK_LCDIF1_PODF>;
        assigned-clock-parents = <0>,
                    <&clks IMX6SX_CLK_PLL5_VIDEO_DIV>,
                    <0>,
                    <0>;
        assigned-clock-rates = <940800000>,
                    <0>,
                    <33600000>,
                    <33600000>;
    };
    
    &gpr {
        status = "okay";
    
        lvds_bridge: bridge@18 {
            status = "okay";
    
            clocks = <&clks IMX6SX_CLK_LDB_DI0_SEL>;
            clock-names = "ldb";
    
            ports {
                #address-cells = <1>;
                #size-cells = <0>;
    
                port@0 {
                    reg = <0>;
                    lvds_bridge_in: endpoint {
                        remote-endpoint = <&lcdif_out>;
                    };
                };
    
                port@1 {
                    reg = <1>;
                    lvds_bridge_out: endpoint {
                        remote-endpoint = <&panel_in>;
                    };
                };
            };
        };
    };
    
    &i2c1 { /* ST1332 or ST1633 Touch IC */
        touchscreen: st1232@55 {
            compatible = "sitronix,st1232";
            reg = <0x55>;
            interrupt-parent = <&gpio6>;
            interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
            pinctrl-0 = <&pinctrl_st1232>;
            pinctrl-names = "default";
            gpios = <&gpio6 5 GPIO_ACTIVE_LOW>;
        };
    };
    
    &lcdif2 { /* Disable HDMI */
        status = "disabled";
    };
    
    &i2c3 { /* Disable hdmi-transmitter */
        status = "disabled";
    };
    and following patch:
    Code:
    diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi
    index bbf792ac4896..c133299f48fc 100644
    --- a/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi
    +++ b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi
    @@ -202,7 +202,7 @@ hdmi-transmitter@70 {
             ports {
                 port {
                     hdmi: endpoint {
    -                    remote-endpoint = <&lcdc>;
    +
                     };
                 };
             };
    @@ -216,18 +216,6 @@ &i2c4 { /* Onboard Motion sensors */
         status = "disabled";
     };
     
    -&lcdif1 {
    -    pinctrl-names = "default";
    -    pinctrl-0 = <&pinctrl_lcd>;
    -    status = "okay";
    -
    -    port {
    -        lcdc: endpoint {
    -            remote-endpoint = <&hdmi>;
    -        };
    -    };
    -};
    -
     &iomuxc {
         pinctrl_bt_reg: btreggrp {
             fsl,pins =
    --
    2.44.4
    
    Thanks to Bootlin and especially Louis C. who managed to find this solution.
     
  3. James Herrera

    James Herrera New Member

    Joined:
    Jan 9, 2026
    Messages:
    1
    Likes Received:
    0
    Could you share your recipe for building this?
     
  4. jerry marlowe

    jerry marlowe New Member

    Joined:
    Feb 9, 2026
    Messages:
    1
    Likes Received:
    0
  5. CartonDu

    CartonDu UDOOer

    Joined:
    Apr 23, 2018
    Messages:
    7
    Likes Received:
    0
    Sorry guys. I didn't expected any answer actually. Need to enable my notifications.
    I will share on Monday the recipe.
     
  6. CartonDu

    CartonDu UDOOer

    Joined:
    Apr 23, 2018
    Messages:
    7
    Likes Received:
    0
    I've made a small tutorial with the help of Claude which I can share here. It's Markdown so feel free to paste in an another editor to read it in good conditions.


    Code:
    # LVDS 7" display support on UDOO NEO (mainline Linux 6.12)
    
    This enables an 800x480 LVDS panel (e.g. UMSH-8596MD-20T) on the UDOO NEO
    Extended using **mainline Linux 6.12.x** (tested on 6.12.77).
    
    The upstream `imx6sx-udoo-neo.dtsi` hardwires `lcdif1` to the HDMI transmitter.
    We need to remove that binding, then add our own LVDS device-tree overlay.
    
    ---
    
    ## 1. Kernel patch: free lcdif1 from HDMI
    
    Apply this patch to the kernel source. It removes the `lcdif1 <-> hdmi`
    endpoint link in the upstream `imx6sx-udoo-neo.dtsi`, freeing LCDIF1 for
    the LVDS bridge.
    
    ```diff
    diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi
    index bbf792ac4896..c133299f48fc 100644
    --- a/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi
    +++ b/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo.dtsi
    @@ -202,7 +202,7 @@ hdmi-transmitter@70 {
             ports {
                 port {
                     hdmi: endpoint {
    -                    remote-endpoint = <&lcdc>;
    +
                     };
                 };
             };
    @@ -216,18 +216,6 @@ &i2c4 { /* Onboard Motion sensors */
         status = "disabled";
     };
    
    -&lcdif1 {
    -    pinctrl-names = "default";
    -    pinctrl-0 = <&pinctrl_lcd>;
    -    status = "okay";
    -
    -    port {
    -        lcdc: endpoint {
    -            remote-endpoint = <&hdmi>;
    -        };
    -    };
    -};
    -
     &iomuxc {
         pinctrl_bt_reg: btreggrp {
             fsl,pins =
    ```
    
    ---
    
    ## 2. Device tree include: `imx6sx-udoo-neo-lvds7.dtsi`
    
    Add this file to `arch/arm/boot/dts/nxp/imx/` and `#include` it from your
    board `.dts`.
    
    It sets up the full display pipeline:
    **LCDIF1 -> LDB (LVDS bridge) -> panel** with a GPIO-controlled backlight
    and an optional Sitronix ST1232 touchscreen on I2C1.
    
    ```dts
    / {
        reg_lcd_pwr: lcd_pwr {
            compatible = "regulator-fixed";
            regulator-name = "LCD POWER";
            gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
            enable-active-high;
            regulator-boot-on;
        };
    
        backlight_lvds: backlight {
            compatible = "gpio-backlight";
            gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>;
            default-on;
        };
    
        panel_lvds: panel-lvds {
            compatible = "umsh,8596md-20t", "panel-lvds";
            width-mm = <152>;
            height-mm = <91>;
            data-mapping = "jeida-18";
            power-supply = <&reg_lcd_pwr>;
            backlight = <&backlight_lvds>;
            status = "okay";
    
            panel-timing {
                clock-frequency = <33600000>;
                hactive = <800>;
                vactive = <480>;
                hback-porch = <56>;
                hfront-porch = <50>;
                vback-porch = <23>;
                vfront-porch = <20>;
                hsync-len = <150>;
                vsync-len = <2>;
    
                hsync-active = <0>;
                vsync-active = <0>;
                de-active = <1>;
                pixelclk-active = <0>;
            };
    
            port {
                panel_in: endpoint {
                    remote-endpoint = <&lvds_bridge_out>;
                };
            };
        };
    };
    
    &gpu { /* Vivante GC400T */
        status = "okay";
    };
    
    &lcdif1 {
        status = "okay";
    
        assigned-clocks = <&clks IMX6SX_CLK_PLL5_VIDEO>,
                    <&clks IMX6SX_CLK_LDB_DI0_SEL>,
                    <&clks IMX6SX_CLK_LCDIF1_PRED>,
                    <&clks IMX6SX_CLK_LCDIF1_PODF>;
        assigned-clock-parents = <0>,
                    <&clks IMX6SX_CLK_PLL5_VIDEO_DIV>,
                    <0>,
                    <0>;
        assigned-clock-rates = <940800000>,
                    <0>,
                    <33600000>,
                    <33600000>;
    
        port {
            lcdif_out: endpoint {
                remote-endpoint = <&lvds_bridge_in>;
            };
        };
    };
    
    &gpr {
        status = "okay";
    
        lvds_bridge: bridge@18 {
            status = "okay";
    
            clocks = <&clks IMX6SX_CLK_LDB_DI0_SEL>;
            clock-names = "ldb";
    
            ports {
                #address-cells = <1>;
                #size-cells = <0>;
    
                port@0 {
                    reg = <0>;
                    lvds_bridge_in: endpoint {
                        remote-endpoint = <&lcdif_out>;
                    };
                };
    
                port@1 {
                    reg = <1>;
                    lvds_bridge_out: endpoint {
                        remote-endpoint = <&panel_in>;
                    };
                };
            };
        };
    };
    
    &i2c1 { /* ST1232 or ST1633 Touch IC */
        touchscreen: st1232@55 {
            compatible = "sitronix,st1232";
            reg = <0x55>;
            interrupt-parent = <&gpio6>;
            interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
            pinctrl-0 = <&pinctrl_st1232>;
            pinctrl-names = "default";
            gpios = <&gpio6 5 GPIO_ACTIVE_LOW>;
        };
    };
    
    &lcdif2 { /* Disable HDMI */
        status = "disabled";
    };
    
    &i2c3 { /* Disable hdmi-transmitter */
        status = "disabled";
    };
    ```
    
    ---
    
    ## 3. Pinctrl: required pad configuration
    
    The LVDS GPIOs (backlight, panel power, touchscreen) need their pads
    configured. Add this to your `&iomuxc` node:
    
    ```dts
    &iomuxc {
        pinctrl_ldb_0: ldbctrlgrp-0 {
            fsl,pins = <
                MX6SX_PAD_SD1_DATA1__GPIO6_IO_3     0x80000000  // BL_ON
                MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27 0x80000000  // PANEL_ON
            >;
        };
    
        pinctrl_st1232: st1232grp-0 {
            fsl,pins = <
                MX6SX_PAD_SD1_DATA2__GPIO6_IO_4  0x80000000  // TOUCH_INT
                MX6SX_PAD_SD1_DATA3__GPIO6_IO_5  0x80000000  // TOUCH_RST
            >;
        };
    };
    ```
    
    ---
    
    ## 4. Kernel config options (relevant subset)
    
    Make sure these are enabled for the display pipeline:
    
    ```
    CONFIG_DRM=y
    CONFIG_DRM_FBDEV_EMULATION=y
    CONFIG_DRM_PANEL_LVDS=m
    CONFIG_DRM_PANEL_SIMPLE=m
    CONFIG_DRM_FSL_LDB=m
    CONFIG_DRM_LVDS_CODEC=m
    CONFIG_DRM_ETNAVIV=m
    CONFIG_DRM_MXSFB=m
    CONFIG_DRM_IMX_LCDIF=m
    CONFIG_FB_DEVICE=y
    CONFIG_LCD_CLASS_DEVICE=y
    CONFIG_BACKLIGHT_CLASS_DEVICE=m
    CONFIG_BACKLIGHT_GPIO=m
    CONFIG_INPUT_TOUCHSCREEN=y
    CONFIG_TOUCHSCREEN_ST1232=y
    ```
    
    ---
    
    ## 5. Yocto recipe: `linux-udoo_6.12.bb`
    
    If you build with Yocto/OE, here is a cleaned recipe. It requires the
    [meta-linux-mainline](https://github.com/pidge/meta-linux-mainline) layer
    for `linux-stable.inc`.
    
    Place the `.dtsi`, `.dts`, `.patch` and `defconfig` files under
    `recipes-kernel/linux/linux-udoo/`.
    
    ```bitbake
    require recipes-kernel/linux/linux-stable.inc
    
    FILESEXTRAPATHS:prepend := "${THISDIR}/${BPN}:"
    
    COMPATIBLE_MACHINE = "(udooneo)"
    
    # To upgrade: copy LINUX_VPATCH + SRCREV from meta-linux-mainline/linux-stable_6.12.bb
    LINUX_VMAJOR = "6"
    LINUX_VMINOR = "12"
    LINUX_VPATCH = "77"
    SRCREV = "6f232446a62980e51f537db1c655e686d869b9ed"
    
    SRC_URI:append = " \
        file://imx6sx-udoo-neo-lvds7.dtsi \
        file://imx6sx-udoo-neo-lvds7.dts \
        file://defconfig \
        file://0001-Remove-lcdif1-and-hdmi-transmitter-endpoint.patch \
    "
    
    KBUILD_DEFCONFIG:udooneo = ""
    KERNEL_LOCALVERSION:udooneo = "-udooneo-lvds"
    
    # Install dtsi/dts into kernel tree after patches are applied
    do_patch:append() {
        install -m 0644 ${WORKDIR}/imx6sx-udoo-neo-lvds7.dtsi \
            ${S}/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo-lvds7.dtsi
    
        install -m 0644 ${WORKDIR}/imx6sx-udoo-neo-lvds7.dts \
            ${S}/arch/arm/boot/dts/nxp/imx/imx6sx-udoo-neo-lvds7.dts
    }
    
    do_recompile_dtb() {
        cd ${B}
        oe_runmake nxp/imx/imx6sx-udoo-neo-lvds7.dtb
    }
    
    addtask recompile_dtb before do_compile after do_configure
    ```
    
    The board `.dts` (`imx6sx-udoo-neo-lvds7.dts`) would look like:
    
    ```dts
    // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
    /dts-v1/;
    
    #include "imx6sx-udoo-neo.dtsi"
    #include "imx6sx-udoo-neo-lvds7.dtsi"
    
    / {
        model = "UDOO NEO Extended with LVDS";
        compatible = "udoo,neoextended", "fsl,imx6sx";
    
        memory@80000000 {
            device_type = "memory";
            reg = <0x80000000 0x40000000>;
        };
    };
    
    &uart3 { /* Bluetooth */
        status = "okay";
    };
    ```
    
    Don't forget to add the pinctrl definitions from section 3 - either inline
    in the `.dts` or in a separate `.dtsi`.
    
    ---
    
    Tested on UDOO NEO Extended with a 7" LVDS panel (UMSH-8596MD-20T / URT UMSH-8596MD-20T compatible) on mainline Linux 6.12.77.
    
     
  7. CartonDu

    CartonDu UDOOer

    Joined:
    Apr 23, 2018
    Messages:
    7
    Likes Received:
    0
    Also, if you are using U-Boot, be aware that commit 99a94c368c9056acf8107ae4163efbb1cbe34d42 introduced a bug. You may see about half of your UDOONEO boards panic during boot.
    As a result, with U-Boot you are limited to version 2022.07 or earlier.
    If you need a newer version, you can apply this patch which reverts part of the faulty commit:

    Code:
    From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
    From: Carton <myemail@notdisclosed.com>
    Date: Tue, 25 Mar 2026 10:00:00 +0000
    Subject: [PATCH] board: udoo neo: fix PMIC device name and restore voltage
     programming
    Upstream-Status: Inappropriate
    
    Commit 99a94c368c9 ("udoo_neo: Move to DM for REGULATOR/PMIC/I2C
    drivers") migrated from the legacy PMIC framework to DM but introduced
    two bugs:
    
    1. pmic_get() is called with "pfuze3000@8" but the DT node is named
       "pmic@8", so the lookup always fails with -ENODEV and the function
       silently returns without configuring anything.
    
    2. The voltage programming (VDD_ARM, VDD_SOC, DDR, standby voltages,
       ramp rates, VGEN2) was removed during the migration. Without these
       settings the board runs on PFUZE3000 power-on defaults, causing
       memory corruption and instability.
    
    Fix the device name and restore the full voltage configuration using the
    DM pmic_reg_read/pmic_reg_write API, matching the values from the
    original POWER_LEGACY implementation.
    
    Signed-off-by: Carton <myemail@notdisclosed.com>
    ---
     board/udoo/neo/neo.c | 53 +++++++++++++++++++++++++++++++++++++++++++-
     1 file changed, 52 insertions(+), 1 deletion(-)
    
    diff --git a/board/udoo/neo/neo.c b/board/udoo/neo/neo.c
    index d99d93b44ae..4d2322ae04e 100644
    --- a/board/udoo/neo/neo.c
    +++ b/board/udoo/neo/neo.c
    @@ -78,9 +78,9 @@ int dram_init(void)
     int power_init_board(void)
     {
         struct udevice *dev;
    -    int ret, dev_id, rev_id;
    +    int ret, dev_id, rev_id, reg;
     
    -    ret = pmic_get("pfuze3000@8", &dev);
    +    ret = pmic_get("pmic@8", &dev);
         if (ret == -ENODEV)
             return 0;
         if (ret != 0)
    @@ -90,8 +90,58 @@ int power_init_board(void)
         rev_id = pmic_reg_read(dev, PFUZE3000_REVID);
         printf("PMIC: PFUZE3000 DEV_ID=0x%x REV_ID=0x%x\n", dev_id, rev_id);
     
    +    /* disable Low Power Mode during standby mode */
         pmic_clrsetbits(dev, PFUZE3000_LDOGCTL, 0, 1);
     
    +    /* set all switchers to APS mode (auto power save) */
    +    pmic_reg_write(dev, PFUZE3000_SW1AMODE, 0xc);
    +    pmic_reg_write(dev, PFUZE3000_SW1BMODE, 0xc);
    +    pmic_reg_write(dev, PFUZE3000_SW2MODE, 0xc);
    +    pmic_reg_write(dev, PFUZE3000_SW3MODE, 0xc);
    +
    +    /* set SW1A standby voltage 0.975V */
    +    reg = pmic_reg_read(dev, PFUZE3000_SW1ASTBY);
    +    reg &= ~0x3f;
    +    reg |= PFUZE3000_SW1AB_SETP(9750);
    +    pmic_reg_write(dev, PFUZE3000_SW1ASTBY, reg);
    +
    +    /* set SW1B standby voltage 0.975V */
    +    reg = pmic_reg_read(dev, PFUZE3000_SW1BSTBY);
    +    reg &= ~0x3f;
    +    reg |= PFUZE3000_SW1AB_SETP(9750);
    +    pmic_reg_write(dev, PFUZE3000_SW1BSTBY, reg);
    +
    +    /* set SW1A/VDD_ARM_IN step ramp up time from 16us to 4us/25mV */
    +    pmic_clrsetbits(dev, PFUZE3000_SW1ACONF, 0xc0, 0x40);
    +
    +    /* set SW1B/VDD_SOC_IN step ramp up time from 16us to 4us/25mV */
    +    pmic_clrsetbits(dev, PFUZE3000_SW1BCONF, 0xc0, 0x40);
    +
    +    /* set VDD_ARM_IN to 1.350V */
    +    reg = pmic_reg_read(dev, PFUZE3000_SW1AVOLT);
    +    reg &= ~0x3f;
    +    reg |= PFUZE3000_SW1AB_SETP(13500);
    +    pmic_reg_write(dev, PFUZE3000_SW1AVOLT, reg);
    +
    +    /* set VDD_SOC_IN to 1.350V */
    +    reg = pmic_reg_read(dev, PFUZE3000_SW1BVOLT);
    +    reg &= ~0x3f;
    +    reg |= PFUZE3000_SW1AB_SETP(13500);
    +    pmic_reg_write(dev, PFUZE3000_SW1BVOLT, reg);
    +
    +    /* set DDR_1_5V to 1.350V */
    +    reg = pmic_reg_read(dev, PFUZE3000_SW3VOLT);
    +    reg &= ~0x0f;
    +    reg |= PFUZE3000_SW3_SETP(13500);
    +    pmic_reg_write(dev, PFUZE3000_SW3VOLT, reg);
    +
    +    /* set VGEN2_1V5 to 1.5V and enable */
    +    reg = pmic_reg_read(dev, PFUZE3000_VLDO2CTL);
    +    reg &= ~0x0f;
    +    reg |= PFUZE3000_VLDO_SETP(15000);
    +    reg |= 0x10;
    +    pmic_reg_write(dev, PFUZE3000_VLDO2CTL, reg);
    +
         return 0;
     }
     
    --
    2.44.4
    
     

Share This Page