某平台pcie设备的(host)controller驱动框架及其phy驱动框架(一)

博客围绕某平台pcie设备展开,介绍了相关结构定义,详细阐述了controller驱动框架,包括入口函数、定义platform driver等多个步骤,还提及了phy驱动框架,为pcie设备驱动开发提供了技术参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NOTE:Kernel version: 5.4.24
File Path:drivers/pci/controller/dwc/pci-xxx.c(省略返回值判断)

1、相关结构的定义

struct xxx_pcie {
	struct dw_pcie		*pci;
	int			clkreq_gpio;
	int			dis_gpio;
	int			reset_gpio;
	bool			gpio_active_high;
	struct clk		*pcie_bus;
	struct clk		*pcie_phy;
	struct clk		*pcie_phy_pclk;
	...
	struct regmap		*iomuxc_gpr;
	struct regmap		*hsiomix;
	u32			controller_id;
	
	struct reset_control	*pciephy_reset;
	struct reset_control	*pciephy_perst;
	struct reset_control	*apps_reset;
	struct reset_control	*turnoff_reset;
	struct reset_control	*clkreq_reset;

	u32			tx_deemph_gen1;
	u32			tx_deemph_gen2_3p5db;
	u32			tx_deemph_gen2_6db;
	u32			tx_swing_full;
	u32			tx_swing_low;
	u32			hsio_cfg;
	u32			ext_osc;
	u32			local_addr;
	u32			hard_wired;
	u32			dma_unroll_offset;
	int			link_gen;
	struct regulator	*vpcie;
	void __iomem		*phy_base;
	void __iomem		*hsmix_base;

	struct device		*pd_pcie;		/* power domain for pcie */
	struct device		*pd_pcie_per;	/* power domain for pcie csr access */
	struct device		*pd_pcie_phy;	/* power domain for pcie phy */
	struct device		*pd_hsio_gpio;	/* power domain for hsio gpio used by pcie */
	...

	const struct xxx_pcie_drvdata *drvdata;
	struct regulator	*epdev_on;
	struct phy		*phy;
};
struct dw_pcie {
	struct device		*dev;
	void __iomem		*dbi_base;
	void __iomem		*dbi_base2;
	/* Used when iatu_unroll_enabled is true */
	void __iomem		*atu_base;
	u32			num_viewport;
	u8			iatu_unroll_enabled;
	struct pcie_port	pp;
	struct dw_pcie_ep	ep;
	const struct dw_pcie_ops *ops;
	unsigned int		version;
};
struct xxx_pcie_drvdata {
	enum xxx_pcie_variants variant;
	u32 flags;
	int dbi_length;
};
struct pcie_port {
	struct device		*dev;
	u8			root_bus_nr;
	void __iomem		*dbi_base;
	u64			cfg0_base;
	void __iomem		*va_cfg0_base;
	u32			cfg0_size;
	u64			cfg1_base;
	void __iomem		*va_cfg1_base;
	u32			cfg1_size;
	resource_size_t		io_base;
	phys_addr_t		io_bus_addr;
	u32			io_size;
	u64			mem_base;
	phys_addr_t		mem_bus_addr;
	u32			mem_size;
	int			cpu_addr_offset;
	struct resource		*cfg;
	struct resource		*io;
	struct resource		*mem;
	struct resource		*busn;
	int			irq;
	u32			lanes;
	u32			num_viewport;
	struct pcie_host_ops	*ops;
	int			msi_irq;
	struct irq_domain	*irq_domain;
	u64			msi_target;
	u8			iatu_unroll_enabled;
	unsigned int		msi_enable[MAX_MSI_CTRLS];
	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
};

2、controller驱动框架

NOTE: 下述代码凡是对返回值判断均用...代替;而......表示省略部分代码。

7)编写xxx_pcie_host_init函数

static int xxx_pcie_host_init(struct pcie_port *pp)
{
	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
	struct xxx_pcie *xxx_pcie = to_xxx_pcie(pci);
	
	if (gpio_is_valid(xxx_pcie->dis_gpio))
		gpio_set_value_cansleep(xxx_pcie->dis_gpio, 1);
	
	xxx_pcie_assert_core_reset(xxx_pcie);		//在本文件中实现
	xxx_pcie_init_phy(xxx_pcie);				//phy的初始化
	xxx_pcie_deassert_core_reset(xxx_pcie);		//在本文件中实现
	xxx_setup_phy_mpll(xxx_pcie);				//设置phy的mpll
	
	if (!(IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)
		&& (xxx_pcie->hard_wired == 0))) {
		......
		......
	}
	
	return 0;
}

6)定义pcie_port的操作函数xxx_pcie_host_ops

static const struct dw_pcie_host_ops xxx_pcie_host_ops = {
	.host_init = xxx_pcie_host_init,
};

5)probe函数调用的主要函数

5_1)static int xxx_pcie_attach_pd(struct device *dev)
	{
		struct xxx_pcie *xxx_pcie = dev_get_drvdata(dev);
		struct device_link *link;
		
		xxx_pcie->pd_pcie = dev_pm_domain_attach_by_name(dev, "pcie");
		...
		link = device_link_add(dev, xxx_pcie->pd_pcie,
			DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
		...
	
		xxx_pcie->pd_pcie_phy = dev_pm_domain_attach_by_name(dev, "pcie_phy");
		...
		link = device_link_add(dev, xxx_pcie->pd_pcie_phy,
			DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
			
		return 0;	
	}
5_2)static int xxx_add_pcie_port(struct xxx_pcie *xxx_pcie, struct platform_device *pdev)
	{
		struct dw_pcie *pci = xxx_pcie->pci;
		struct pcie_port *pp = &pci->pp;
		int ret;
		
		/*5.2.1 获取msi中断号*/
		if (IS_ENABLED(CONFIG_PCI_MSI)) {
			pp->msi_irq = platform_get_irq_byname(pdev, "msi");
			...
		}
		
		/*5.2.2 指向pcie_port的操作函数*/
		pp->ops = &xxx_pcie_host_ops;
		
		ret = dw_pcie_host_init(pp);
		...
		
		return 0;
	}
5_3)static void pci_xxx_set_msi_en(struct pcie_port *pp)
	{
		struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
		u16 val;
		
		if (pci_msi_enabled()) {
			dw_pcie_dbi_ro_wr_en(pci);
			val = dw_pcie_readw_dbi(pci, PCIE_RC_xxx_MSI_CAP + PCI_MSI_FLAGS);
			val |= PCI_MSI_FLAGS_ENABLE;
			dw_pcie_writew_dbi(pci, PCIE_RC_xxx_MSI_CAP + PCI_MSI_FLAGS, val);
			dw_pcie_dbi_ro_wr_dis(pci);
		}
	}

4)编写xxx_pcie_probe和xxx_pcie_shutdown函数

4_1)xxx_pcie_probe函数;
static int xxx_pcie_probe(struct platform_device *pdev)
{
	struct xxx_pcie *xxx_pcie;
	struct dw_pcie *pci;
	struct device *dev = &pdev->dev;
	struct device_node *np;
	struct resource *dbi_base;
	struct device_node *node = dev->of_node;
	int ret;
	
	
	/*1、分配内存*/
	xxx_pcie = devm_kzalloc(dev, sizeof(*xxx_pcie), GFP_KERNEL);
	...
	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
	...
	
	pci->dev = dev;
	pci->ops = &dw_pcie_ops;
	
	/*2、填充xxx_pcie*/
	xxx_pcie->pci = pci;
	xxx_pcie->drvdata = of_device_get_match_data(dev);
	
	/*2.1 获取平台pcie phy*/
	xxx_pcie->phy = devm_phy_get(dev, "pcie-phy");
	...
	
	/*2.2 如果有使用HSIO MIX,则获取其基址*/
	np = of_parse_phandle(node, "fsl,xxx8mp-hsio-mix", 0);
	if(np) {
		struct resource res;
		ret = of_address_to_resource(np, 0, &res);
		...
		xxx_pcie->hsmix_base = devm_ioremap_resource(dev, &res);
		...
	}
	
	/*2.3 获取dbi物理地址并ioremap*/
	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
	...
	
	/*2.4 获取hsio-cfg、ext_osc、local-addr、hard-wired等信息。如果获取不到,就设置为0*/
	if (of_property_read_u32(node, "hsio-cfg", &xxx_pcie->hsio_cfg))
		xxx_pcie->hsio_cfg = 0;
	if (of_property_read_u32(node, "ext_osc", &xxx_pcie->ext_osc) < 0)
		xxx_pcie->ext_osc = 0;
	if (of_property_read_u32(node, "local-addr", &xxx_pcie->local_addr))
		xxx_pcie->local_addr = 0;
	if (of_property_read_u32(node, "hard-wired", &xxx_pcie->hard_wired))
		xxx_pcie->hard_wired = 0;
	
	/*2.5 获取GPIO相关信息*/
	xxx_pcie->clkreq_gpio = of_get_named_gpio(node, "clkreq-gpio", 0);
	...
	xxx_pcie->dis_gpio = of_get_named_gpio(node, "disable-gpio", 0);
	...
	xxx_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
	...
	xxx_pcie->gpio_active_high = of_property_read_bool(node, "reset-gpio-active-high");
	...
	xxx_pcie->epdev_on = devm_regulator_get(&pdev->dev,"epdev_on");
	...
	
	/*2.6 获取clock相关信息*/
	xxx_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
	...
	xxx_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
	...
	xxx_pcie->pcie = devm_clk_get(dev, "pcie");
	...
	xxx_pcie->pciephy_perst = devm_reset_control_get_exclusive(dev, "pciephy_perst");
	...
	xxx_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
	...
	xxx_pcie->clkreq_reset = devm_reset_control_get_optional_exclusive(dev, "clkreq");
	...
	
	/*2.7 获取GPR配置寄存器range*/
	if (xxx_pcie->iomuxc_gpr == NULL) {
		xxx_pcie->iomuxc_gpr = syscon_regmap_lookup_by_compatible("fsl,xxxq-iomuxc-gpr");
		...
	}
	
	/*2.8 关于PCIe PHY Tx的设置*/
	if (of_property_read_u32(node, "fsl,tx-deemph-gen1", &xxx_pcie->tx_deemph_gen1))
		xxx_pcie->tx_deemph_gen1 = 0;
	if (of_property_read_u32(node, "fsl,tx-deemph-gen2-3p5db", &xxx_pcie->tx_deemph_gen2_3p5db))
		xxx_pcie->tx_deemph_gen2_3p5db = 0;
	if (of_property_read_u32(node, "fsl,tx-deemph-gen2-6db", &xxx_pcie->tx_deemph_gen2_6db))
		xxx_pcie->tx_deemph_gen2_6db = 20;
	if (of_property_read_u32(node, "fsl,tx-swing-full", &xxx_pcie->tx_swing_full))
		xxx_pcie->tx_swing_full = 127;
	if (of_property_read_u32(node, "fsl,tx-swing-low", &xxx_pcie->tx_swing_low))
		xxx_pcie->tx_swing_low = 127;
	
	/*2.9 获取max link speed。若获取不到,设置为Gen1*/
	ret = of_property_read_u32(node, "fsl,max-link-speed", &xxx_pcie->link_gen);
	if (ret)
		xxx_pcie->link_gen = 1;
	
	/*3、设置驱动data到平台设备*/
	platform_set_drvdata(pdev, xxx_pcie);
	
	/*4、获取power domain*/
	ret = xxx_pcie_attach_pd(dev);					
	...
	
	/*5、使能regulator输出*/
	ret = regulator_enable(xxx_pcie->epdev_on);	
	...
	
	/*6、pcie port初始化、使能msi*/
	if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS) 
			&& (xxx_pcie->hard_wired == 0)) {
				......
				......
	}else {
		ret = xxx_add_pcie_port(xxx_pcie, pdev);				//初始化pcie port
		if (ret < 0) {
			if (IS_ENABLED(CONFIG_PCI_xxx_COMPLIANCE_TEST)) {
				......
			}
		}
		pci_xxx_set_msi_en(&xxx_pcie->pci->pp);				//使能msi
		
		if (IS_ENABLED(CONFIG_RC_MODE_IN_EP_RC_SYS)
				&& (xxx_pcie->hard_wired == 0))
			......
			
		ret = xxx_pcie->drvdata->flags & xxx_PCIE_FLAG_SUPPORTS_L1SS;		//L1SS相关部分
		if (IS_ENABLED(CONFIG_PCIEASPM_POWER_SUPERSAVE) && (ret > 0)) {
			......
			......
		}
	}
	
	return 0;
}
4_2)xxx_pcie_shutdown函数;
static void xxx_pcie_shutdown(struct platform_device *pdev)
{
	struct xxx_pcie *xxx_pcie = platform_get_drvdata(pdev);
	
	xxx_pcie_assert_core_reset(xxx_pcie);
}

3)定义.driver.of_match_table

static const struct xxx_pcie_drvdata drvdata[] = {
	......
	......
	[xxx8MP] = {
		.variant = xxx8MP,
		.flags = xxx_PCIE_FLAG_SUPPORTS_SUSPEND,
	},
};
static const struct of_device_id xxx_pcie_of_match[] = {
	{ .compatible = "fsl,xxx8mq-pcie", .data = &drvdata[xxx8MQ], },
	{ .compatible = "fsl,xxx8mm-pcie", .data = &drvdata[xxx8MM], },
	{ .compatible = "fsl,xxx8qm-pcie", .data = &drvdata[xxx8QM], },
	{ .compatible = "fsl,xxx8qxp-pcie", .data = &drvdata[xxx8QXP], },
	{ .compatible = "fsl,xxx8mp-pcie", .data = &drvdata[xxx8MP], },
	{},
};
	

2)定义一个platform driver

static struct platform_driver xxx_pcie_driver = {
	.driver = {
		.name	= "xxx-pcie",
		.of_match_table = xxx_pcie_of_match,
		.suppress_bind_attrs = true,
		.pm = &xxx_pcie_pm_ops,
		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
	},
	.probe    = xxx_pcie_probe,
	.shutdown = xxx_pcie_shutdown,
};

1)入口函数

static int __init xxx_pcie_init(void)
{
	#ifdef CONFIG_ARM
		hook_fault_code(8, xxx_pcie_abort_handler, SIGBUS, 0,
				"external abort on non-linefetch");
	#endif

	return platform_driver_register(&xxx_pcie_driver);
}
device_initcall(xxx_pcie_init);							//#define device_initcall(fn) module_init(fn)

3、phy驱动框架

某平台pcie设备的(host)controller驱动框架及其phy驱动框架(二)

<think>好的,我需要帮助用户了解RK3588芯片中Rockchip DesignWare PCIe控制器的相关信息或配置方法。首先,我需要确认用户提供的引用内容中是否有相关的信息。 查看引用[1],主要涉及UART的问题汇总和开发指南,可能不直接相关。引用[2]提到了AP6275P的蓝牙功能和相关设备树文件路径,但同样没有直接提到PCIe。引用[3]提到了RK3588评估板的基本信息,包括MPIDR和内存配置,但也没有PCIe的具体内容。因此,现有的引用可能不足以直接回答用户的问题,需要结合我对RK3588芯片的般知识来补充。 接下来,我需要整理Rockchip DesignWare PCIe控制器在RK3588中的配置方法。通常,PCIe控制器的配置涉及设备树(DTS)的设置,包括时钟、电压域、PHY配置、中断等。此外,需要说明不同工作模式(RC或EP)的配置差异,并提及驱动程序的加载和调试方法,如查看系统日志和使用lspci工具。 用户可能需要了解硬件规格,比如支持的PCIe版本、通道数、接口速率等。根据公开资料,RK3588的PCIe控制器支持PCIe 3.0,可能有多个控制器实例,如PCIe2x1和PCIe3x2,每个实例的配置可能不同。 需要确保回答结构清晰,分点说明配置步骤和关键参数,并提醒用户参考官方文档进行验证。此外,生成相关问题时要围绕用户可能进步提出的疑问,比如性能优化、兼容性问题、调试技巧等。</think>### RK3588 Rockchip DesignWare PCIe控制器配置说明 #### 、硬件特性 1. **PCIe版本支持**:RK3588集成多个DesignWare PCIe控制器,支持PCIe 3.0协议,理论带宽可达8GT/s[^3] 2. **控制器实例**: - PCIE2x1:单通道模式,适用于低速外设 - PCIE3x2:双通道模式,支持更高带宽需求 3. **工作模式**:支持Root Complex(RC)和Endpoint(EP)模式,需通过寄存器配置切换 #### 二、设备树配置方法 1. **基础配置示例**(以PCIE3x2控制器为例): ```dts pcie3x2: pcie@fe190000 { compatible = "rockchip,rk3588-pcie-dw"; // 驱动匹配关键字 reg = <0x0 0xfe190000 0x0 0x10000>, // 控制器寄存器地址 <0x0 0xf4000000 0x0 0x00400000>; // 配置空间映射地址 clocks = <&cru ACLK_PCIE_3X2>, // 时钟配置 <&cru CLK_PCIE_AUX2>; power-domains = <&power RK3588_PD_PCIE>; // 电源域控制 resets = <&cru SRST_A_PCIE3X2>, // 复位信号 <&cru SRST_PCIE3X2_POWER_UP>; phys = <&pcie30phy>; // PHY物理层绑定 #address-cells = <3>; #size-cells = <2>; status = "okay"; }; ``` 2. **关键参数说明**: - **PHY配置**:需同步配置PCIe PHY节点,包括参考时钟频率(如100MHz)、阻抗校准等 - **电压域**:需确保`vcc3v3_pcie`供电稳定,典型值为3.3V - **中断配置**:建议使用MSI中断,需配置`interrupts`属性 #### 三、驱动加载验证 1. **内核配置检查**: ```bash # 确认PCIe驱动编译进内核 grep CONFIG_PCIE_ROCKCHIP_DW_HOST /boot/config-$(uname -r) ``` 2. **运行时检测**: ```bash dmesg | grep -i pcie # 查看初始化日志 lspci -vv # 枚举连接的PCIe设备 ``` #### 四、调试技巧 1. **信号质量测试**:建议使用示波器测量差分信号眼图,确保符合PCIe 3.0规范 2. **链路训练分析**:通过读取`/sys/kernel/debug/pcie/<controller>/link_status`文件获取链路状态 3. **性能测试**:使用`dd`命令或专用工具(如`iperf`)进行带宽测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值