Linux驱动开发—— of_property_read_u8

在使用設備樹的時候, 有時會遇到下面的問題.

在設備樹中配置的屬性如下:

fusb301,init-mode = <0x20>;

但是在驅動中讀出的卻是:

    rc = of_property_read_u8(dev_node,
                "fusb301,init-mode", &data->init_mode);

加打印發現, 讀出的值是0, 並不是0x20.

使用下面的命令將對應的節點從內存中pull出來:

adb pull "/sys/firmware/devicetree/base/soc/i2c@7af6000/fusb301@25/fusb301,init-mode"

這是一個二進制文件, 使用二進制閱讀工具打開:

可以看到, 0x20存放在高字節, 即設備樹編譯工具是按大端格式組織數據的, 但是使用of_property_read_u8卻是按小端格式.

然後做了如下實驗:

添加屬性:

fusb301,test = <0x12345678>;

在驅動中解析這個字段:

    u8 value8;
    u16 value16;
    u32 value32;

    of_property_read_u8(dev_node,"fusb301,test", &value8);
    of_property_read_u16(dev_node,"fusb301,test", &value16);
    of_property_read_u32(dev_node,"fusb301,test", &value32);

    printk("%s: value8: %x, value16: %x, value32: %x\n", __func__, value8, value16, value32);

輸出的log如下:

fusb301_parse_dt: value8: 12, value16: 1234, value32: 12345678

可以驗證我們的猜想.

那麼如何解決這個問題呢?

通過閱讀內核代碼發現, 內核中其實有說明:

 1 /**
 2  * of_property_read_u8_array - Find and read an array of u8 from a property.
 3  *
 4  * @np:        device node from which the property value is to be read.
 5  * @propname:    name of the property to be searched.
 6  * @out_values:    pointer to return value, modified only if return value is 0.
 7  * @sz:        number of array elements to read
 8  *
 9  * Search for a property in a device node and read 8-bit value(s) from
10  * it. Returns 0 on success, -EINVAL if the property does not exist,
11  * -ENODATA if property does not have a value, and -EOVERFLOW if the
12  * property data isn't large enough.
13  *
14  * dts entry of array should be like:
15  *    property = /bits/ 8 <0x50 0x60 0x70>;
16  *
17  * The out_values is modified only if a valid u8 value can be decoded.
18  */
19 int of_property_read_u8_array(const struct device_node *np,
20             const char *propname, u8 *out_values, size_t sz)
21 {
22     const u8 *val = of_find_property_value_of_size(np, propname,
23                         (sz * sizeof(*out_values)));
24 
25     if (IS_ERR(val))
26         return PTR_ERR(val);
27 
28     while (sz--)
29         *out_values++ = *val++;
30     return 0;
31 }
32 EXPORT_SYMBOL_GPL(of_property_read_u8_array);

 

然後我做了如下實驗:

添加如下幾個屬性:

        fusb301,test8 = /bits/ 8 <0x12>;
        fusb301,test16 = /bits/ 16 <0x1234>;
        fusb301,test32 = <0x12345678>;

修改驅動, 解析這些字段:

    u8 value8;
    u16 value16;
    u32 value32;

    of_property_read_u8(dev_node,"fusb301,test8", &value8);
    of_property_read_u16(dev_node,"fusb301,test16", &value16);
    of_property_read_u32(dev_node,"fusb301,test32", &value32);

    printk("%s: value8: %x, value16: %x, value32: %x\n", __func__, value8, value16, value32);

輸出的log如下:

fusb301_parse_dt: value8: 12, value16: 1234, value32: 12345678

 

完.

posted @ 2016-11-08 20:10  摩斯电码  阅读(8803)  评论(0编辑  收藏  举报