Why modifying the device tree in uboot will cause subsequent access to the device tree to fail?

162 Views Asked by At

when i use gd->fdt_blob and fdt_status_okay() to modyfy fdt in uboot, may case rockchip display driver can not found props in subnode of '/display-subsystem/route'

here what i do in uboot, and i will call lt8911_fixup_dts() before display driver init:

static int lt8911_fixup_dts(struct udevice *dev)
{
    struct lt8911_plat *plat = dev_get_platdata(dev);
    ofnode dsi_node, vp_node;
    ofnode port, dsi_ports, ep;
    const struct device_node *dsi_devnode, *vp_devnode;
    const struct device_node *ep_devnode;
    const char *dsi_path, *vp_path;
    const void *blob = gd->fdt_blob;
    int offset, ep_offset;
    u32 reg, ep_reg;

    debug("%s\n", __func__);
    if(plat->use_lt8911_bridge) {
        dsi_node = ofnode_path("/dsi@fe070000");
        vp_node = ofnode_path("/video-phy@fe860000");
        if (!ofnode_valid(dsi_node) | !ofnode_valid(vp_node))
            return -ENODEV;

        dsi_devnode = ofnode_to_np(dsi_node);
        vp_devnode = ofnode_to_np(vp_node);
        dsi_ports = ofnode_find_subnode(dsi_node, "ports");
        if (!ofnode_valid(dsi_ports))
            return -ENODEV;

        ofnode_for_each_subnode(port, dsi_ports) {
            if (ofnode_read_u32(port, "reg", &reg))
                continue;
            if (reg != PORT_DIR_IN)
                continue;
            debug("port name:%s, reg:%d\n", port.np->full_name, reg);

            //dsi@fe070000/ports/port@0
            ofnode_for_each_subnode(ep, port) {
                if(ofnode_read_u32(ep, "reg", &ep_reg)) {
                    continue;
                }
                if(ep_reg != DSI_IN_VP1)
                    continue;
                ep_devnode =  ofnode_to_np(ep);
                ep_offset = fdt_path_offset(blob, ep_devnode->full_name);
                if(ep_offset < 0) {
                    printf("get dsi0_in_vp1 node offset failed:%s\n", fdt_strerror(ep_offset));
                    return -1;
                }
                printf("dsi1_in_vp1:%s, reg:%d, offset:%d\n", ep_devnode->full_name, ep_reg, ep_offset);
                fdt_status_okay((void *)blob, ep_offset);   //&dsi1_in_vp1 { status = "okay"};
            }
        }

        dsi_path = dsi_devnode->full_name;
        offset = fdt_path_offset(blob, dsi_path);
        if(offset < 0) {
            printf("get dsi0 node offset failed:%s\n", fdt_strerror(offset));
            return -1;
        }
        debug("dsi1:%s\n", dsi_path);
        fdt_status_okay((void *)blob, offset);      //&dsi1 { status = "okay"};

        vp_path = vp_devnode->full_name;
        offset = fdt_path_offset(blob, vp_path);
        if(offset < 0) {
            printf("get video_phy0 node offset failed:%s\n", fdt_strerror(offset));
            return -1;
        }
        debug("video-phy1:%s\n", vp_path);
        fdt_status_okay((void *)blob, offset);      //&video_phy1 { status = "okay"};
    } else {
        dsi_node = ofnode_path("/dsi@fe060000");
        vp_node = ofnode_path("/video-phy@fe850000");
        if (!ofnode_valid(dsi_node) | !ofnode_valid(vp_node))
            return -ENODEV;

        dsi_devnode = ofnode_to_np(dsi_node);
        vp_devnode = ofnode_to_np(vp_node);

        dsi_ports = ofnode_find_subnode(dsi_node, "ports");
        if (!ofnode_valid(dsi_ports))
            return -ENODEV;

        ofnode_for_each_subnode(port, dsi_ports) {
            if (ofnode_read_u32(port, "reg", &reg))
                continue;
            if (reg != PORT_DIR_IN)
                continue;
            debug("port name:%s, reg:%d\n", port.np->full_name, reg);

            //dsi@fe060000/ports/port@0
            ofnode_for_each_subnode(ep, port) {
                if(ofnode_read_u32(ep, "reg", &ep_reg)) {
                    continue;
                }
                if(ep_reg != DSI_IN_VP1)
                    continue;

                ep_devnode =  ofnode_to_np(ep);
                ep_offset = fdt_path_offset(blob, ep_devnode->full_name);
                if(ep_offset < 0) {
                    printf("get dsi0_in_vp1 node offset failed:%s\n", fdt_strerror(ep_offset));
                    return -1;
                }
                debug("dsi0_in_vp1:%s, reg:%d\n", ep_devnode->full_name, ep_reg);
                fdt_status_okay((void *)blob, ep_offset);   //&dsi0_in_vp1 { status = "okay"};
            }
        }

        dsi_path = dsi_devnode->full_name;
        offset = fdt_path_offset(blob, dsi_path);
        if(offset < 0) {
            printf("get dsi0 node offset failed:%s\n", fdt_strerror(offset));
            return -1;
        }
        debug("dsi0:%s\n", dsi_path);
        fdt_status_okay((void *)blob, offset);      //&dsi0 { status = "okay"};

        vp_path = vp_devnode->full_name;
        offset = fdt_path_offset(blob, vp_path);
        if(offset < 0) {
            printf("get video_phy0 node offset failed:%s\n", fdt_strerror(offset));
            return -1;
        }
        debug("video-phy0:%s\n", vp_path);
        fdt_status_okay((void *)blob, offset);      //&video_phy0 { status = "okay"};
    }
    printf("lt8911 fixup dts success\n");
    return 0;
}

here is code in rockchip_display.c:

/*
 * traverse the following nodes:
 * route-dsi0/route-dsi1/route-edp/route-hdmi/route-lvds/route-rgb
 */
route_node = ofnode_path("/display-subsystem/route");
ofnode_for_each_subnode(node, route_node) {  
    if (!ofnode_is_available(node))
        continue;
    phandle = ofnode_read_u32_default(node, "connect", -1);
    if (phandle < 0) {
        printf("Warn: can't find connect node's handle\n");
        continue;
    }
}

and the error log:

rockchip_display_probe enter
node path:/display-subsystem/route/route-dsi0, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-dsi1, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-edp, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-hdmi, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-lvds, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-rgb, phandle:-1
Warn: can't find connect node's handle
rockchip_display_probe enter
node path:/display-subsystem/route/route-dsi0, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-dsi1, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-edp, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-hdmi, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-lvds, phandle:-1
Warn: can't find connect node's handle
node path:/display-subsystem/route/route-rgb, phandle:-1
Warn: can't find connect node's handle

I would be very grateful if you could give me some help

in kernel dts, i turned off the following nodes by default:

&dsi0 {
    status = "disabled";
};

&dsi0_in_vp0 {
    status = "disabled";
};

&dsi0_in_vp1 {
    status = "disabled";
};

&dsi1 {
    status = "disabled";
};

&dsi1_in_vp0 {
    status = "disabled";
};

&dsi1_in_vp1 {
    status = "disabled";
};
&video_phy0 {
    status = "disabled";
};

&video_phy1 {
    status = "disabled";
};

And i want open these node(dsi1/dsi1_in_vp1/video_phy1) in uboot, so i call function of lt8911_fixup_dts(), in order for the following display link to work normal in uboot and kernel: vop->vp1->dsi1->lt8911->edp panel

0

There are 0 best solutions below