linux_dts

设备树结构

主要有节点组成(节点里面还可以包含子节点),节点里面可以设备各种属性
(1)属性的值可以是字符串数组、cells(u32整数组成)、二进制数
(2)节点@后,一般表示节点的地址
(3)#address-cells =<1> #size-cells=<1> 分别描述子节点reg属性的 起始地址和地址长度

reg 示例:reg = < address length>
#address-cells =<1> :表示 address 是一个值
#address-cells =<2> :表示 address 是两个个值

#size-cells=<0> :表示没有length
#size-cells=<1>:表示length 是一个值

#address-cells =<2> #size-cells=<1>
子节点reg属性
reg = <0 0 0x1000> :第一个0 表示片选,第二个0 表示相对该片选的基地址,0x1000 为length

(4)compatible 用于和driver 进行匹配

获取节点

参考博客
参考博客

通过of_device_id 结构体数组里面的元素进行匹配(匹配表匹配)
(device_node 表示dts中的一个节点)
用于probe 函数中,根据dev和match_id 匹配,得到of_device_id。然后可以匹配对应的data,这个常用dts有多个compatible能够匹配,但是不同compatible的data不一样,这样就可以根据不同的compatible选择不同的data

extern const struct of_device_id *of_match_node(
	const struct of_device_id *matches, const struct device_node *node);

在这里插入图片描述
在这里插入图片描述

举例
platform_device 下有一个 struce device,这个下面又有一个 struce device_node (这个就是用来和设备树匹配的)
在这里插入图片描述
在这里插入图片描述

类似函数:of_match_device (里面调用的是of_match_node)

const struct of_device_id *of_match_device(const struct of_device_id *matches,
					   const struct device *dev)
{
	if (!matches || !dev->of_node || dev->of_node_reused)
		return NULL;
	return of_match_node(matches, dev->of_node);
}

判断具体设备

当一个驱动要支持多个设备时,就可以通过这个函数判断具体是哪个设备

static inline int of_device_is_compatible(const struct device_node *device,
					  const char *name)
{
	return 0;
}

补充获取节点的api

指定起始搜索device_node 的匹配函数
下面函数和of_match_node 的差异就是可以指定从哪个节点开始搜索
通过对应的of_device_id ,找到匹配到的device_node

static inline struct device_node *of_find_matching_node(
	struct device_node *from,
	const struct of_device_id *matches)
{
	return of_find_matching_node_and_match(from, matches, NULL);
}

补充device_node
它是device结构体下的一个成员(关联的设备树节点),名字叫做of_node
所有的probe函数的参数都是一个platform_device结构体,它里面有一个dev成员(是一个device结构体,表示的就是dts节点对应的一个device

通过alias找到对应的编号

比如SoC上有如果多個i2c控制器,alias的相當於給每個i2c控制器分配一個唯一的編號,如上面的i2c@13880000對應的alias是i2c2,那麼這個編號就是2,將來就可以在/dev下看到名爲i2c-2的設備節點

of_alias_get_id(dev->of_node, drv_data->dev_name);//dev_name: 名字

在內核中可以看到很多地方都會調用of_alias_get_id,他的作用就是根據傳入的device node,在alias中找到對應的唯一編號,如:

参考
参考
举例:
rk dphy 驱动

在这里插入图片描述
比如下面的dev_name 就是 csi2dphy
在这里插入图片描述

下面有三个compatible都一样的节点,然后还有一个aliases中有这三个节点。但是driver 中只能匹配到一个节点,所以就使用of_alias_get_id或得到匹配到的是哪一个节点,返回的是索引。
在这里插入图片描述
aliases 节点下就会有多个dev_name的别名,这样就能获取到对应设备的序号
在这里插入图片描述

通过父节点的属性名字获取子节点

np = of_parse_phandle(dev->of_node, "rockchip,hw", 0);// 通过名字获取该节点下子节点的device_node

根据字符串和索引从device_node对应的节点中(该节点下有一个属性引用了另一个节点)获取另一个device_node。然后使用下面这个函数就可以根据device_node获取对应的platform_device

static inline struct platform_device *of_find_device_by_node(struct device_node *np)
static inline void of_node_put(struct device_node *node)//释放device_node

举例
下面csi2_dphy0节点下rockchip,hw 属性引用了另一个节点csi2_dphy_hw,
在这里插入图片描述在这里插入图片描述
然后下面的代码就可以从csi2_dphy0的driver中获取csi2_dphy_hw 对应的driver中的platform_device
在这里插入图片描述

device_node 相关

判断device_node 是否可用

bool of_device_is_available(const struct device_node *device)

减少device_node 的引用计数

void of_node_put(struct device_node *node)

获取节点属性

根据节点和属性名或者属性值

(1)整形

```c
static inline int of_property_read_u32_array(const struct device_node *np,
					     const char *propname,
					     u32 *out_values, size_t sz)
static inline int of_property_read_u32(const struct device_node *np,
				       const char *propname,
				       u32 *out_value)

(2)字符串

extern int of_property_read_string(const struct device_node *np,
				   const char *propname,
				   const char **out_string);

4 platform 驱动单独的

在这里插入图片描述

5 irq
当配置了多个irq 时,可以用下面这个函数通过名字获取某一个irq号
在这里插入图片描述

在这里插入图片描述

还可以通过下面这个函数获取第几个中断号

extern int platform_get_irq(struct platform_device *, unsigned int);

注册irq

devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
		 unsigned long irqflags, const char *devname, void *dev_id)
{
	return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags,
					 devname, dev_id);
}

include

dts 和 dtsi 中不仅可以include dtsi 文件,还可以include .h 文件

使用预处理

dts dtsi 中也可以定义宏 #if #else 等

#define VM311XS_IN

#ifdef VM311XS_IN
#endif

#if 1
#else
#endif

  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux,可以通过设备树(Device Tree)来配置USB设备的相关参数。以下是一些常见的USB设备树配置: 1. USB主控配置:可以通过以下代码来配置USB主控: ``` usb@<addr> { compatible = "usb-xhci"; reg = <addr> <size> <flags>; interrupts = <irq>; phys = <&phy>; phy-names = "usb3-phy"; clocks = <&clk>; clock-names = "usb"; status = "okay"; }; ``` 其,`<addr>` 是USB主控地址,`<size>` 是地址范围大小,`<flags>` 是地址标志,`<irq>` 是断号,`<phy>` 是USB PHY对象,`<clk>` 是时钟对象。 2. USB从设备配置:可以通过以下代码来配置USB从设备: ``` usb@<addr> { compatible = "usb-gadget"; reg = <addr> <size> <flags>; interrupts = <irq>; status = "okay"; function1 { compatible = "mass-storage"; ... } function2 { compatible = "ethernet"; ... } }; ``` 其,`function1` 和 `function2` 是USB从设备的功能,可以根据需要添加多个功能。每个功能都有自己的配置项。 3. USB PHY配置:可以通过以下代码来配置USB PHY: ``` usb3-phy@<addr> { compatible = "usb-phy"; reg = <addr> <size> <flags>; status = "okay"; }; ``` 其,`<addr>` 是USB PHY地址,`<size>` 是地址范围大小,`<flags>` 是地址标志。 4. USB电源配置:可以通过以下代码来配置USB电源: ``` usb_power: usb-power { compatible = "regulator-fixed"; regulator-name = "vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; }; ``` 其,`regulator-name` 是电源名称,`regulator-min-microvolt` 和 `regulator-max-microvolt` 是电压范围。 这些配置可以根据具体的硬件和需求进行调整。配置后,需要编译设备树,并将其加载到内核

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值