PCIe总线-RK3588 PCIe驱动设备树介绍(九)

1.简介

在Linux内核中设备树中,定义了一系列属性,用来描述PCIe总线。比如"bus-range"属性,描述PCIe某个domain的总线编号范围,比如"ranges"属性,描述PCIe地址转换。下面将分别介绍这些属性。

2.设备类型

由于PCIe总线有一些特有的属性,需要在驱动初始化的时候内核自动解析。因此需要在设备树定义设备类型,如下所示。当设备类型为"pci"时,内核就知道这是一个PCI Host Brage。

[arch/arm64/boot/dts/rockchip/rk3588.dtsi]
pcie3x4: pcie@fe150000 {
    ......
    device_type = "pci";
    ......
}

Linux内核调用__of_node_is_type函数解析设备类型。

[drivers/of/base.c]
static bool __of_node_is_type(const struct device_node *np, const char *type)
{
	const char *match = __of_get_property(np, "device_type", NULL);

	return np && match && type && !strcmp(match, type);
}

3.PCI域

在Linux内核中,一个PCI设备,通常使用domain number:bus number:device number.function number(比如0000:00:00.0)描述。domain number表示PCI域的编号,bus number表示总线编号,device number表示设备编号,function number表示功能编号,bus number、device number和function number也称之为BDF。PCI域用来给PCI Host Brage编号,有几个PCI Host Brage,就有几个PCI域。通常情况下,各个PCI域之间不能直接通信。在设备树中,PCI域使用"linux,pci-domain"属性描述。

[arch/arm64/boot/dts/rockchip/rk3588.dtsi]
pcie3x4: pcie@fe150000 {
    ......
    linux,pci-domain = <0>;
    ......
}

Linux内核调用of_get_pci_domain_nr函数解析PCI域编号。

[drivers/pci/of.c]
int of_get_pci_domain_nr(struct device_node *node)
{
	u32 domain;
	int error;

	error = of_property_read_u32(node, "linux,pci-domain", &domain);
	if (error)
		return error;

	return (u16)domain;
}

4.速度和Link Width

PCIe总线的最大速度由"max-link-speed"属性描述,Link Width由"num-lanes"描述。真实的速度和Link Width由RC、PCIe桥和EP协商决定。

[arch/arm64/boot/dts/rockchip/rk3588.dtsi]
pcie3x4: pcie@fe150000 {
    ......
    max-link-speed = <3>;
    num-lanes = <4>;
    ......
}

Linux内核中可使用下面的接口解析"max-link-speed""num-lanes"属性。

[drivers/pci/of.c]
int of_pci_get_max_link_speed(struct device_node *node)
{
	u32 max_link_speed;

	if (of_property_read_u32(node, "max-link-speed", &max_link_speed) ||
	    max_link_speed == 0 || max_link_speed > 4)
		return -EINVAL;

	return max_link_speed;
}

[drivers/pci/controller/pcie-rockchip.c]
err = of_property_read_u32(node, "num-lanes", &rockchip->lanes);

5.ranges

"ranges"属性定义了CPU地址到PCI地址的转换关系(outbound memory)。在PCI设备枚举的时候,PCI主机会根据ranges属性,设置对应的memory region,同时将PCI地址设置到PCI设备的寄存器中,当枚举完成后,CPU可以直接通过地址访问PCI设备。"dma-ranges"属性则与"ranges"属性相反,定义PCI地址到CPU地址的转换关系(inbound memory)。

"#address-cells"定于使用几个cell描述PCI地址,"#size-cells"定义使用几个cell描述地址长度。因此"ranges"属性和"dma-ranges"属性描述的地址意义如下所示。

[arch/arm64/boot/dts/rockchip/rk3588.dtsi]
pcie3x4: pcie@fe150000 {
    ......
    #address-cells = <3>
    #size-cells = <2>;
    /*           PCI地址标志  PCI地址高32位  PCI地址低32位 CPU地址高32位  CPU地址低32位 地址长度高32位 地址长度低32位 */
	ranges = <    0x00000800     0x0       0xf0000000     0x0        0xf0000000     0x0       0x100000
			      0x81000000     0x0       0xf0100000     0x0        0xf0100000     0x0       0x100000
			      0x82000000     0x0       0xf0200000     0x0        0xf0200000     0x0       0xe00000
			      0xc3000000     0x9       0x00000000     0x9        0x00000000     0x0       0x40000000>;
    ......
};

[arch/arm64/boot/dts/renesas/r8a774b1.dtsi]
pciec0: pcie@fe000000 {
    ......
    #address-cells = <3>;
    #size-cells = <2>;
    /* Map all possible DDR as inbound ranges */
    /*          PCI地址标志  PCI地址高32位  PCI地址低32位 CPU地址高32位  CPU地址低32位 地址长度高32位 地址长度低32位 */
    dma-ranges = <0x42000000      0        0x40000000        0        0x40000000       0       0x80000000>;
    ......
};

PCI地址标志由8部分组成,其二进制位域的意义如下所示,PCIe总线中,只有pss有意义。

npt000ss bbbbbbbb dddddfff rrrrrrrr

n: relocatable region flag (doesn't play a role here)
p: prefetchable (cacheable) region flag
t: aliased address flag (doesn't play a role here)
ss: space code
    00: configuration space
    01: I/O space
    10: 32 bit memory space
    11: 64 bit memory space
bbbbbbbb: The PCI bus number. PCI may be structured hierarchically. 
          So we may have PCI/PCI bridges which will define sub busses.
ddddd: The device number, typically associated with IDSEL signal connections.
fff: The function number. Used for multifunction PCI devices.
rrrrrrrr: Register number; used for configuration cycles.

因此pcie3x4节点中"ranges"属性定义的4个地址段意义如下:

  1. 一个配置空间,从PCI地址0xf0000000开始,大小为1MB,将映射到Host CPU的0xf0000000地址处,具体的地址根据访问设备的BDF动态映射。
  2. 一个IO空间,从PCI地址0xf0100000开始,大小为1MB,将映射到Host CPU的0xf0100000地址处。
  3. 一个32位非预取内存空间,从PCI地址0xf0200000开始,大小为14MB,将映射到Host CPU的0xf0200000地址处。
  4. 一个64位预取内存空间,从PCI地址0x900000000开始,大小为14GB,将映射到Host CPU的0x900000000地址处。

因此pciec0节点中"dma-ranges"属性定义的地址段意义如下:

  1. 从Host CPU的角度看,一个32位非预取内存空间,从PCI地址0x40000000开始,大小为2GB,将映射到Host CPU内存0x40000000地址处。这样设置后,EP的DMA可以直接访问Host CPU的内存。

Linux内核中使用下面定义的函数解析"ranges"属性和"dma-ranges"属性。其中of_bus_pci_match匹配PCI总线,of_bus_pci_get_flags解析PCI地址标志。

[drivers/of/address.c]
static struct of_bus of_busses[] = {
#ifdef CONFIG_PCI
	/* PCI */
	{
		.name = "pci",
		.addresses = "assigned-addresses",
		.match = of_bus_pci_match,
		.count_cells = of_bus_pci_count_cells,
		.map = of_bus_pci_map,
		.translate = of_bus_pci_translate,
		.has_flags = true,
		.get_flags = of_bus_pci_get_flags,
	},
#endif /* CONFIG_PCI */
    ......
};

6.中断

PCIe总线中,涉及INTx、MSI、MSI-X中断。INTx中断需要在设备树中配置映射关系。MSI和MSI-X中断需要配置和ITS的映射关系。

6.1.INTx中断

由于很多PCI设备只使用INTA中断,若中断很频繁时,这些中断都将集中到INTA上,导致中断效率降低。因此需要将PCI插槽上的INTx中断以旋转(swizzling)方式连接到中断控制器上的不同中断引脚上。设备树需要一种将每个PCI中断信号映射到中断控制器输入的方法。"#interrupt-cells""interrupt-map""interrupt-map-mask"属性用于描述中断映射。"#interrupt-cells"属性表示描述中断需要几个cell,"interrupt-map-mask"表示PCI插槽(包含了device id信息)和INTx中断编号的掩码,"interrupt-map"表示INTx和中断控制器的映射关系。

如下图所示,phys.hi phys.mid phys.low分别表示PCI插槽位置信息,由于在PCIe总线中,INTx中断使用消息机制实现,不需要中断引脚,因此PCI插槽位置信息可以设置为0。INTx对应的一列分别表示INTA、INTB、INTC、INTD中断。"interrupt-map-mask""interrupt-map"的前4列相与得到最终的PCI插槽位置信息和INTx类型。因此下面分别将INTA、INTB、INTC、INTD映射到pcie3x4_intc中断控制器的0、1、2、3号中断上,实质上pcie3x4_intc是一个虚拟的中断控制器,父中断控制器为GIC,其使用260号中断向GIC提交中断。

[arch/arm64/boot/dts/rockchip/rk3588.dtsi]
pcie3x4: pcie@fe150000 {
    ......
    interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>,
                <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>,
                <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
                <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
                <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>;
    interrupt-names = "sys", "pmc", "msg", "legacy", "err";
    #interrupt-cells = <1>;
    /*                   phys.hi phys.mid phys.low  INTx */
    interrupt-map-mask = <  0        0        0      7>;
    /*            phys.hi phys.mid phys.low  INTx 映射的中断控制器  中断编号 */
    interrupt-map = <0        0        0      1    &pcie3x4_intc   0>,  /* INTA */
                    <0        0        0      2    &pcie3x4_intc   1>,  /* INTB */
                    <0        0        0      3    &pcie3x4_intc   2>,  /* INTC */
                    <0        0        0      4    &pcie3x4_intc   3>;  /* INTD */
    ......
    pcie3x4_intc: legacy-interrupt-controller {
        interrupt-controller;
        #address-cells = <0>;
        #interrupt-cells = <1>;
        interrupt-parent = <&gic>;
        interrupts = <GIC_SPI 260 IRQ_TYPE_EDGE_RISING>;
    };
    ......
}

6.2.MSI和MSI-X中断

GICv3及以上版本实现了ITS(Interrupt Translation Service)。因此在ARM架构上,可基于ITS实现MSI或MSI-X中断。设备树使用"msi-map"属性描述MSI或MSI-X中断和msi-controller的映射关系。"msi-map"属性的第一个数据表示MSI Data,即MSI中断向量起始编号,需要配置到PCIe设备的配置空间中,第二个数据引用msi-controller节点,msi-controller位于gic节点内,第三个数据表示PCIe设备起始16位的Requester ID(BDF),第四个数据表示中断数量,下面申请了4096个中断。

[arch/arm64/boot/dts/rockchip/rk3588.dtsi]
pcie3x4: pcie@fe150000 {
    ......
    /*        MSI Data  msi-controller  Requester ID  length  */
    msi-map = <0x0000      &its1          0x0000      0x1000>;
    ......
};

[arch/arm64/boot/dts/rockchip/rk3588s.dtsi]
gic: interrupt-controller@fe600000 {
    compatible = "arm,gic-v3";
    #interrupt-cells = <3>;
    #address-cells = <2>;
    #size-cells = <2>;
    ranges;
    interrupt-controller;

    reg = <0x0 0xfe600000 0 0x10000>, /* GICD */
            <0x0 0xfe680000 0 0x100000>; /* GICR */
    interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
    its0: msi-controller@fe640000 {
        compatible = "arm,gic-v3-its";
        msi-controller;
        #msi-cells = <1>;
        reg = <0x0 0xfe640000 0x0 0x20000>;
    };
    its1: msi-controller@fe660000 {
        compatible = "arm,gic-v3-its";
        msi-controller;
        #msi-cells = <1>;
        reg = <0x0 0xfe660000 0x0 0x20000>;
    };
};

参考资料

  1. PCIEXPRESS体系结构导读
  2. PCI Express technology 3.0
  3. PCI Express® Base Specification Revision 5.0 Version 1.0
  4. Rockchip RK3588 TRM
  5. https://elinux.org/Device_Tree_Usage#PCI_Host_Bridge
  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于微信小程序的家政服务预约系统采用PHP语言和微信小程序技术,数据库采用Mysql,运行软件为微信开发者工具。本系统实现了管理员和客户、员工三个角色的功能。管理员的功能为客户管理、员工管理、家政服务管理、服务预约管理、员工风采管理、客户需求管理、接单管理等。客户的功能为查看家政服务进行预约和发布自己的需求以及管理预约信息和接单信息等。员工可以查看预约信息和进行接单。本系统实现了网上预约家政服务的流程化管理,可以帮助工作人员的管理工作和帮助客户查询家政服务的相关信息,改变了客户找家政服务的方式,提高了预约家政服务的效率。 本系统是针对网上预约家政服务开发的工作管理系统,包括到所有的工作内容。可以使网上预约家政服务的工作合理化和流程化。本系统包括手机端设计和电脑端设计,有界面和数据库。本系统的使用角色分为管理员和客户、员工三个身份。管理员可以管理系统里的所有信息。员工可以发布服务信息和查询客户的需求进行接单。客户可以发布需求和预约家政服务以及管理预约信息、接单信息。 本功能可以实现家政服务信息的查询和删除,管理员添加家政服务信息功能填写正确的信息就可以实现家政服务信息的添加,点击家政服务信息管理功能可以看到基于微信小程序的家政服务预约系统里所有家政服务的信息,在添加家政服务信息的界面里需要填写标题信息,当信息填写不正确就会造成家政服务信息添加失败。员工风采信息可以使客户更好的了解员工。员工风采信息管理的流程为,管理员点击员工风采信息管理功能,查看员工风采信息,点击员工风采信息添加功能,输入员工风采信息然后点击提交按钮就可以完成员工风采信息的添加。客户需求信息关系着客户的家政服务预约,管理员可以查询和修改客户需求信息,还可以查看客户需求的添加时间。接单信息属于本系统里的核心数据,管理员可以对接单的信息进行查询。本功能设计的目的可以使家政服务进行及时的安排。管理员可以查询员工信息,可以进行修改删除。 客户可以查看自己的预约和修改自己的资料并发布需求以及管理接单信息等。 在首页里可以看到管理员添加和管理的信息,客户可以在首页里进行家政服务的预约和公司介绍信息的了解。 员工可以查询客户需求进行接单以及管理家政服务信息和留言信息、收藏信息等。
数字社区解决方案是一套综合性的系统,旨在通过新基建实现社区的数字化转型,打通智慧城市建设的"最后一公里"。该方案以国家政策为背景,响应了国务院、公安部和中央政法会议的号召,强调了社会治安防控体系的建设以及社区治理创新的重要性。 该方案的建设标准由中央综治办牵头,采用"9+X"模式,通过信息采集、案(事)件流转等手段,实现五级信息中心的互联互通,提升综治工作的可预见性、精确性和高效性。然而,当前社区面临信息化管理手段不足、安全隐患、人员动向难以掌握和数据资源融合难等问题。 为了解决这些问题,数字社区建设目标提出了"通-治-服"的治理理念,通过街道社区、区政府、公安部门和居民的共同努力,实现社区的平安、幸福和便捷。建设思路围绕"3+N"模式,即人工智能、物联网和数据资源,结合态势感知、业务分析和指挥调度,构建起一个全面的数据支持系统。 数字社区的治理体系通过"一张图"实现社区内各维度的综合态势可视化,"一套表"进行业务分析,"一张网"完成指挥调度。这些工具共同提升了社区治理的智能化和效率。同时,数字社区还提供了包括智慧通行、智慧环保、居家养老和便民服务等在内的多样化数字服务,旨在提升居民的生活质量。 在硬件方面,数字社区拥有IOT物联网边缘网关盒子和AI边缘分析盒子,这些设备能够快速集成老旧小区的物联设备,实现传统摄像设备的智能化改造。平台优势体现在数字化能力中台和多样化的应用,支持云、边、端的协同工作,实现模块化集成。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值