pinctl设备树(of函数)

        下面是自己关于设备树的一些理解,如果有错误,后面在进行修改。

一、操作系统在启动器件对设备树的处理

        设备树分为两层,pinctl端和client端,在uboot引导kernel启动之后,kernel启动的时候就会去去读设备树,获取其中的相关信息储存起来,实际的情况如下所示。

         上面的两个图是衔接的,只是图太大,所以分开进行截图了。

         上面的两个图也是衔接的,图太大了,就分开截取。

二、开发板目录查看对应的pinctl、group、pin、复用情况等。

         如上图目录所示,在“/sys/kernel/debug/pinctrl”目录下可以看到生成的连个pinctl:“20e0000.iomuxc”、“2290000.iomuxc-snvs”,绿色框里的设备使用如下图所示:

pins 单个引脚信息
pingroups引脚的组信息
pinmux-pins单个引脚的复用信息
Pinctrl的虚拟文件作用
pinmux-functionsfunction下的group(支持该function的group)
pinconf-pins单个引脚的配置
pinconf-groups引脚组的配置
pinconf-config可以通过写它修改指定设备、指定状态下、指定(组)引脚的config值

        使用上面的三个文件,就可以查看到不同的设备信息。

(1)进入“20e0000.iomuxc”或者“2290000.iomuxc-snvs”目录,可以看到下图所示的目录,可以使用“cat”命令打印其中的某些目录,就可以看到group、pin等信息。

 (2)使用“”命令打印引脚的复用信息

         从上面的图中就可以看到设备树中设置的pin引脚是否复用。

(3)下面三个文件是查看对应的pin状态的指令,具体的参考韦东山老师笔记。

 (4)对设备树的信息和结构体的pin配置信息的关系

        利用设备树中的信息,生成pinctl需要的结构体配置信息的方法有两种。

第一种:

        获取设备树中的信息,对应pinctl中pin配置的结构体信息在内核驱动中已经写死,只是根绝设备树中的配置进行选择,然后根据在设备树中获取pin引脚配置的参数,对相应的引脚设置。

第二种:

        通过在获取设备树中pin的配置信息,然后根据获取的pin信息,对pin信息存储的结构体进行创建,然后根绝设备树中对应的pin引脚配置参数,进行引脚的配置。

三、设备树编辑注意事项

        如下图所示,“pinctrl_hog_1”名称与“:”冒号之间是不能有空格的,如果有空格就会报错。

四、设备树的基础知识

        (1)设备树文件可以包含“NAME.dtsi”头文件,也可以包含其他c文件的头文件“dt-bindings/input/input.h”,这种c文件的头文件包含可能是因为要用里面的宏定义,设备树头文件也就是后缀为“.dtsi”的文件的包含作用,一般里面都是关于芯片的统一的内容,因为同一家芯片厂商的芯片的参数内容都是一样的,只是不同的芯片参数的数值不同而已,所以将这些相同的芯片参数封装为一个“.dtsi”的头文件。

        (2)设备树结点定义,“标签:  结点名@寄存器首地址{}”,在设备树头文件“imx6ull.dtsi”里面定义的结点,可以继续进行内容的追加,格式如下图所示,自己添加的结点一般放在设备树的最后面。

 五、设备树中两个特殊结点

        两个特殊结点分别为“chosen”和“aliases”。

(1)aliases(翻译:别名)结点

         aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。不过我们一般会在节点命名的时候会加上 label,然后通过&label来访问节点,这样也很方便,而且设备树里面大量的使用&label 的形式来访问节点。

(2)chosen结点

        chosen 并不是一个真实的设备, chosen 节点主要是为了 uboot Linux 内核传递数据,重
点是 bootargs 参数。一般 .dts 文件中 chosen 节点通常为空或者内容很少, imx6ull-alientek
emmc.dts chosen 节点内容如下所示:

 详细细节参考正点原子imx6ull指南手册。

六、结点的特殊属性

        (1)地址格式指定,手地址的格式,地址长度格式,这里都是指定一个参数。

address-cells = <1>;
size-cells = <1>;

        (2)地址参数指定属性,指定了首地址和地址的长度。注意他的属性是由父节点里面设置的指定的,子节点中指定的影响他的子节点。

reg = <0x02008000 0x4000>;

其他属性参考正点手册

七、设备结点的of获得函数

        这个函数在写驱动的时候,使用的还是比较多的,of函数的头文件在自己的乌班图中的路径为:“./Linux-4.9.88/include/linux/of.h”。下面将介绍一下常用的of函数,其他的可以参考正点的文档。

       设备都是以节点的形式“挂”到设备树上的,因此要想获取这个设备的其他属性信息,必 须先获取到这个设备的节点。Linux 内核使用 device_node 结构体来描述一个节点,此结构体定义在文件 include/linux/of.h 中,定义如下:

49 struct device_node {
50 const char *name; /* 节点名字 */
51 const char *type; /* 设备类型 */
52 phandle phandle;
53 const char *full_name; /* 节点全名 */
54 struct fwnode_handle fwnode;
55
56 struct property *properties; /* 属性 */
57 struct property *deadprops; /* removed 属性 */
58 struct device_node *parent; /* 父节点 */
59 struct device_node *child; /* 子节点 */
60 struct device_node *sibling;
61 struct kobject kobj;
62 unsigned long _flags;
63 void *data;
64 #if defined(CONFIG_SPARC)
65 const char *path_component_name;
66 unsigned int unique_id;
67 struct of_irq_controller *irq_trans;
68 #endif
69 };

        (1)查找设设备树中结点的函数

 

 

 

         (2)查找父/子类结点的OF函数

         (3)提取属性值property结构体的of函数

35 struct property {
36     char *name; /* 属性名字 */
37     int length; /* 属性长度 */
38     void *value; /* 属性值 */
39     struct property *next; /* 下一个属性 */
40     unsigned long _flags;
41     unsigned int unique_id;
42     struct bin_attribute attr;
43 };

 

 

int of_property_read_u8_array(const struct device_node *np,
                              const char *propname, 
                              u8 *out_values, 
                              size_t sz)
int of_property_read_u16_array(const struct device_node *np,
                               const char *propname, 
                               u16 *out_values, 
                               size_t sz)
int of_property_read_u32_array(const struct device_node *np,
                               const char *propname, 
                               u32 *out_values,
                               size_t sz)
int of_property_read_u64_array(const struct device_node *np,
                               const char *propname, 
                               u64 *out_values,
                               size_t sz)

 

 

/**
 *	of_get_parent - Get a node's parent if any
 *	@node:	Node to get parent
 *
 *	Returns a node pointer with refcount incremented, use
 *	of_node_put() on it when done.
 */
struct device_node *of_get_parent(const struct device_node *node)
{
	struct device_node *np;
	unsigned long flags;

	if (!node)
		return NULL;

	raw_spin_lock_irqsave(&devtree_lock, flags);
	np = of_node_get(node->parent);
	raw_spin_unlock_irqrestore(&devtree_lock, flags);
	return np;
}
EXPORT_SYMBOL(of_get_parent);
//得到设备树中的gpio结点,通过设备结点中的name
static inline int of_get_named_gpio(struct device_node *np,
                                   const char *propname, int index)
{
	return of_get_named_gpio_flags(np, propname, index, NULL);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值