Linux驱动编程【OF函数操作】

目录

一、标准属性

二、根节点下的compatible属性

三、Linux内核的OF操作函数

四、OF函数实验

一、标准属性

        1、compatible属性(兼容的)

       值是字符串列表,用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序

        2、model属性

       属性值也是一个字符串,一般model属性描述模块信息,比如名字之类

        3、status属性

       属性值也是一个字符串,用来描述一个设备的状态

        4、#address-cells和#size-cells属性

       两个属性值都是无符号32位整型,#address-cells和#size-cells可以用在任何拥有节点的设备中,用于描述节点的地址信息,#address-cells决定了子节点reg属性中地址信息所占用的字长(32位),#size-cells属性值决定了子节点reg属性中长度信息所占用的字长

        #address-cells = <1>;

        #size-cells = <1>;

        子节点:  reg = <cell1 cell2>

                        reg = <0x02198000 0x4000>

        5、ranges属性

       代表地址映射,如果是null则表示没有地址映射

        6、device_type属性

       用来描述设备的Fcode //CPU、memory节点

二、根节点下的compatible属性

       内核启动的时候会检查是否支持此平台

       不使用设备树时,通过传递machine id 来判断内核是否支持此平台

       使用设备树时,不使用机器ID,而是使用根节点下的compatible属性

三、Linux内核的OF操作函数

       1、驱动如何获取到节点信息。在驱动中使用OF函数获取设备树属性内容。

       2、驱动要想获取到设备树内容,首先要找到节点

                ①、of_find_node_by_name

                ②、of_find_node_by_type

                ③、of_find_node_by_path

                ④、of_find_compatible_node

       3、提取属性值的OF函数

        节点的属性信息里面保存了驱动所需要的内容,因此对于属性值的提取非常重要, Linux 内核中使用结构体 property 表示属性

struct property {
    char *name; /* 属性名字 */
    int length; /* 属性长度 */
    void *value; /* 属性值 */
    struct property *next; /* 下一个属性 */
    unsigned long _flags;
    unsigned int unique_id;
    struct bin_attribute attr;
};

               ①、of_find_property函数

                用于查找指定的属性

               ②、of_property_count_elems_of_size 函数

                用于获取属性中元素的数量

                ③、of_property_read_u32_index 函数

                从属性中获取指定标号的 u32 类型数据值(无符号 32位),比如某个属性有多个 u32 类型的值,那么就可以使用此函数来获取指定标号的数据值

                ④、of_property_read_u8_array 函数

                of_property_read_u16_array 函数

                of_property_read_u32_array 函数

                of_property_read_u64_array 函数

                这 4 个函数分别是读取属性中 u8、 u16、 u32 和 u64 类型的数组数据,比如大多数的 reg 属性都是数组数据,可以使用这 4 个函数一次读取出 reg 属性中的所有数据

                ⑤、of_property_read_u8 函数

                of_property_read_u16 函数

                of_property_read_u32 函数

                of_property_read_u64 函数

        有些属性只有一个整形值,这四个函数就是用于读取这种只有一个整形值的属性,分别用于读取 u8、 u16、 u32 和 u64 类型属性值

                ⑥、of_property_read_string 函数

                用于读取属性中字符串值

                ⑦、of_n_addr_cells 函数

                函数用于获取#address-cells 属性值

                ⑧、of_n_size_cells 函数

                函数用于获取#size-cells 属性值

四、OF函数实验

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>

static int __init dtsof_init(void)
{
	int ret = 0;
	struct device_node *bl_nd = NULL;
	struct property    *comppro = NULL;
	const char *str;
	u32 def_val = 0;
	u32 elemsize = 0;
	u32 *brival;
	int i;
	/* 1. find backlight node */
	bl_nd = of_find_node_by_path("/backlight");
	if(bl_nd == NULL) {	/*failed*/
		ret = -EINVAL; 
		goto fail_finded;
	}
	comppro = of_find_property(bl_nd, "compatible", NULL);
	if(comppro == NULL) {
		ret = -EINVAL; 
		goto fail_finpro;
	} else {
		printk("compatible=%s\n", (char *)comppro->value);
	}
	/* 2. read string */
	ret = of_property_read_string(bl_nd, "status", &str);
	if(ret < 0) {
		goto fail_rs;
	} else {
		printk("status=%s\r\n", str);
	}
	/* 3. read number */
	ret = of_property_read_u32(bl_nd, "default-brightness-level", &def_val);
	if(ret < 0) {
		goto fail_read32;
	} else {
		printk("default-brightness-level=%d\r\n", def_val);
	}
	/* 4. read arr[] */
	elemsize = of_property_count_elems_of_size(bl_nd, "brightness-levels", sizeof(u32));
	if(elemsize < 0) {
		ret = -EINVAL;
		goto fail_readele;
	} else {
		printk("brightness-levels=%d\r\n", elemsize);
	}
	/* 5. kmalloc */
	brival = kmalloc(elemsize * sizeof(u32), GFP_KERNEL);
	if(!brival) {
		ret = EINVAL;
		goto fail_mem;
	}
	ret = of_property_read_u32_array(bl_nd, "brightness-levels", brival, elemsize);
	if(ret < 0) {
		goto fail_read32array;
	} else {
		for(i = 0; i < elemsize; i++)
		printk("brightness-levels[%d] = %d\r\n", i, *(brival + i));
	}
	kfree(brival);
	return 0;

fail_read32array:	
	kfree(brival);
fail_mem:
fail_readele:
fail_read32:
fail_rs:
fail_finpro:
fail_finded:
	return ret;
}

static void __exit dtsof_exit(void)
{
	printk("dtsof_exit\n");
}
module_init(dtsof_init);
module_exit(dtsof_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZHANG");

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值