内核子系统运用---设备树

设备树中的一些常用配置

中断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;

Supongo que te gusta

Origin blog.csdn.net/weixin_41884251/article/details/109774160
Recomendado
Clasificación