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

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驱动框架(二)

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值