动态修改设备树(不建议使用这种方法)


前言

针对uboot已经加载完设备树的情况下,在uboot阶段对设备的内容进行动态的修改。


一、设备树

主要是针对gpio这个属性中的RK_PA6进行修改

	//这个电主要是供usb 的 vbus电,其中gpio是使能脚,这里修改的就是使能脚
	vcc5v0_host: vcc5v0-host-regulator {
		compatible = "regulator-fixed";
		regulator-name = "vcc5v0_host";
		regulator-boot-on;
		regulator-always-on;
		regulator-min-microvolt = <5000000>;
		regulator-max-microvolt = <5000000>;
		enable-active-high;
		gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
		vin-supply = <&vcc5v0_usb>;
		pinctrl-names = "default";
		pinctrl-0 = <&vcc5v0_host_en>;
	};

二、代码及log

2.1 代码

int usb_otg_vbus_dtb_overlay(int switch_usb_port)
{
    const char *vbus_node_path = "/vcc5v0-host-regulator";          //设备树vbus节点路径
    const void *fdt_blob = gd->fdt_blob;                            //设备树的handle,用作get_prop
    void *fdt = (void *)gd->fdt_blob;                               //设备树的handle,用作set_prop
    int vbus_node_offset;                                           //vbus的节点 offset
    const char *prop_name = "gpio";                                 //需要在vbus节点获取的属性
    int prop_len;                                                   //gpio这个属性值的数量
    const u32 *prop;                                                //获取gpio这个属性值数组
    fdt32_t tmp_prop[3] = {0, 0, 0};                                //存储获取到的属性值

	vbus_node_offset = fdt_path_offset(fdt_blob, vbus_node_path);
	if (vbus_node_offset < 0) {
        printf("path:%s not exist \n", vbus_node_path);
    }

    prop = fdt_getprop(fdt_blob, vbus_node_offset, prop_name, &prop_len);
    if (prop_len < 0) {
        printf("%s, Failed to get property length\n", __func__);
    } else {
        for (int i = 0; i < prop_len / sizeof(u32); i++) {
        	//大小端转换,不然数值看不出来(对不上RK_PA6这些数值)
            fdt32_t tmp = cpu_to_fdt32(prop[i]);
            printf("%s %u:%u \n", __func__, prop[i], tmp);
            tmp_prop[i] = tmp;
        }
    }
    
    //这里根据switch_usb_port类型使用gpio0中不同的pin脚
    if (switch_usb_port == USE_USB2_PORT) {
        tmp_prop[1] = RK_PA7;
    } else if (switch_usb_port == USE_USB1_PORT) {
        tmp_prop[1] = RK_PA6;
    }
    
    //修改设备树内容
    //这里需要先转一遍,再写入,不然会大小端会出错的(导致整个设备树乱掉)
    for (int i = 0; i < prop_len / sizeof(u32); i++) {
        tmp_prop[i] = fdt32_to_cpu(tmp_prop[i]);
    }
    const void *new_prop = tmp_prop;
	int ret = fdt_setprop_inplace(fdt, vbus_node_offset, prop_name, new_prop, prop_len);
	if (ret < 0) {
		printf("%s libfdt fdt_setprop(): %s\n", __func__, fdt_strerror(ret));
	}

    //这部分查看修改效果
    prop = fdt_getprop(fdt_blob, vbus_node_offset, prop_name, &prop_len);
    if (prop_len < 0) {
        printf("--%s, Failed to get property length\n", __func__);
    } else {
        for (int i = 0; i < prop_len / sizeof(u32); i++) {
            fdt32_t tmp = cpu_to_fdt32(prop[i]);
            printf("--%s %u:%u \n", __func__, prop[i], tmp);
        }
    }    

    return 0;
}

注意事项:
1.关于大小端转换,读取出来的设备树内容需要使用cpu_to_fdt32来转换一下才可以正常读出。写入的数据也需要使用fdt32_to_cpu进行转换一下才可以正常写入,否则设备树会乱掉,然后出现各种错误。
2.不建议新增属性值,新增属性值会增大设备树的大小,导致出现未知错误。
3.建议使用带inplace尾缀的api进行操作。

2.2 log确认

在代码后面有一属性复读的操作,可得到如下log
在这里插入图片描述

2.3 效果确认

使用万用表进行电压的确认。
修改前,该usb口做host vbus电压是正常供应5V
修改后,该usb口做host vbus电压是为0,因为使能脚被改变了,所以vbus没有被使能供电。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值