设备树中的一些常用配置
中断interrupts
中断一般分2中情况写
interrupt-parent = <&gpio2>;
interrupts = <29 0>;
中断控制器是GPIO2,然后使用它的29号中断。(这里的29号,就是指29号引脚),0是指触发的方式(上升沿、下降沿等)。
interrupts = <0 37 1>;
interrupts = <GIC_SPI 37 1>;
interrupts = <GIC_PPI 37 1>;
先看几个缩写
IPI:inter-processer interrupt 中断号0~15
PPI:per processor interrupts 中断号16~31
SPI:shared processor interrupts 中断号 32 ~32+224
SGI:software generated interrupts (SGI).
ARM GIC-v2支持三种类型的中断:
SGI:软件触发中断(Software Generated Interrupt),通常用于多核间通讯,最多支持16个SGI中断,硬件中断号从ID0~ID15。SGI通常在Linux内核中被用作IPI中断(inter-processor interrupts),并会送达到系统指定的CPU上。
PPI:私有外设中断(Private Peripheral Interrupt),是每个CPU私有的中断。最多支持16个PPI中断,硬件中断号从ID16~ID31。PPI通常会送达到指定的CPU上,应用场景有CPU本地时钟。
SPI:公用外设中断(Shared Peripheral Interrupt),最多可以支持988个外设中断,硬件中断号从ID32~ID1019。
三个参数的时候:
include\dt-bindings\Interrupt-controller\arm-gic.h -》》 SPI:0 PPI:1
第一个参数表示是IPI、PPI、SPI、SGI其中的一个
第二个参数表示:是第一个参数里面的第几个,一般计算方法 值 = 硬件中断号 - 32 因为我们大部分使用SPI
第三个参数表示:中断触发的类型。(上升沿、下降沿等)
中断类型值
#define IRQ_TYPE_NONE 0
#define IRQ_TYPE_EDGE_RISING 1
#define IRQ_TYPE_EDGE_FALLING 2
#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING |IRQ_TYPE_EDGE_RISING)
#define IRQ_TYPE_LEVEL_HIGH 4
#define IRQ_TYPE_LEVEL_LOW 8
ranges
a {
compatible = "xxx-bus";
ranges = <0x0 0x2000000 0x10000>;
#address-cells = <1>;
#size-cells = <1>;
b@0 {
reg = <0x100 0x100>;//0x2000100 size 0x100
};
b@1 {
reg = <0x200 0x100>;//0x2000200 size 0x100
};
c {
compatible = "xxx-bus2";
ranges = <0x0 0x1000 0x1000>;
b@2 {
reg = <0x100 0x200>;//0x2001100 size 0x200
};
}
}
ranges属性值的格式 <local地址, parent地址, size>
第一个参数有点类似当前括号中的0地址,有点相对的感觉
实际的地址得层层剥离才能得知最终的地址
resets
clock: clock0 {
compatible = "hisilicon,hi3559av100-clock", "syscon";
#clock-cells = <1>;
#reset-cells = <2>;
#address-cells = <1>;
#size-cells = <1>;
reg = <0x0 0x12010000 0x0 0x10000>;
};
------------------------------------------------------
mdio: mdio@101c03c0 {
compatible = "hisilicon,hisi-gemac-mdio";
reg = <0x101c03c0 0x20>;
clocks = <&clock HI3559AV100_ETH_CLK>;
resets = <&clock 0x174 14>;
reset-names = "phy_reset";
#address-cells = <1>;
#size-cells = <0>;
};
higmac: ethernet@101c0000 {
resets = <&clock 0x174 0>,
<&clock 0x174 4>;
reset-names = "port_reset",
"macif_reset";
mac-address = [00 00 00 00 00 00];
};
mdio的reset操作在resets属性中标明
使用clock的控制器,去clock这个基地址0x12010000查数据手册,
再查0x174这个偏移地址是啥,再看他的14bit是复位外接FEPHY0 的软复位请求
像gmac这个有2个复位bit
bit0 GMAC0 的软复位请求。
bit4 MAC_IF0 的软复位请求
cells
amba {
compatible = "arm,amba-bus";
#address-cells = <1>;
#size-cells = <1>;
uart0: uart@12100000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x12100000 0x1000>;
cpus {
#address-cells = <2>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0x0 0x0>;
cells 后面带<>表示uint32类型的值 address和size 配合使用一般描述reg信息,且描述子节点的reg分布
address描述占几个坑,代表了uart0 地址占一个坑,长度占一个坑
cpu0 中的reg就代表了两个都是地址,没有长度,是个64位的地址
reg的内容不一定是设备的实际地址需要结合父节点的ranges搭配使用
常用的接口
my_power_key {
compatible = "test_key";
interrupt-parent = <&r_pio>;
interrupts = <0 3 IRQ_TYPE_EDGE_BOTH>;
sw1 {
key_name="xxx"
key_code=123
interrupts = <0 3 IRQ_TYPE_EDGE_BOTH>;
}
sw2{
interrupts = <0 4 IRQ_TYPE_EDGE_BOTH>;
}
};
struct device_node *np = of_find_node_by_path("/my_power_key");//获取设备树节点信息
irq_no = irq_of_parse_and_map(np, 0);//获取中断号这里的irqno配合request_irq接口使用
这个irq既不等于设备树里写的那个,也不等于数据手册里面写的中断号;值等于cat proc/intterrupys
of_find_node_by_path
irq_of_parse_and_map
struct resource res = {
0};
ret = of_address_to_resource(np, 0, &res);
of_address_to_resource 获取设备树种reg的地址–》res.start
假如返回-22,请确保该节点的符节点下列设置是否正确
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x00000000 0x0 0xffffffff>;
通过res得到size记得+1,base_size = res.end - res.start + 1 ; 要加1个字节
原因res在填充的时候-1了; r->start = taddr; r->end = taddr + size - 1;