RE: [PATCH v3 2/2] dwc: PCI: intel: Intel PCIe RC controller driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Sep 12, 2019 at 10:23:31, Dilip Kota 
<eswara.kota@xxxxxxxxxxxxxxx> wrote:

> Quoting Andrew Murray:
> Quoting Gustavo Pimentel:
> 
> On 9/12/2019 4:25 PM, Andrew Murray wrote:
> > [...]
> >>>>>>>>>> +static void intel_pcie_max_link_width_setup(struct intel_pcie_port *lpp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	u32 mask, val;
> >>>>>>>>>> +
> >>>>>>>>>> +	/* HW auto bandwidth negotiation must be enabled */
> >>>>>>>>>> +	pcie_rc_cfg_wr_mask(lpp, PCIE_LCTLSTS_HW_AW_DIS, 0, PCIE_LCTLSTS);
> >>>>>>>>>> +
> >>>>>>>>>> +	mask = PCIE_DIRECT_LINK_WIDTH_CHANGE | PCIE_TARGET_LINK_WIDTH;
> >>>>>>>>>> +	val = PCIE_DIRECT_LINK_WIDTH_CHANGE | lpp->lanes;
> >>>>>>>>>> +	pcie_rc_cfg_wr_mask(lpp, mask, val, PCIE_MULTI_LANE_CTRL);
> >>>>>>>>> Is this identical functionality to the writing of PCIE_PORT_LINK_CONTROL
> >>>>>>>>> in dw_pcie_setup?
> >>>>>>>>>
> >>>>>>>>> I ask because if the user sets num-lanes in the DT, will it have the
> >>>>>>>>> desired effect?
> >>>>>>>> intel_pcie_max_link_width_setup() function will be called by sysfs attribute pcie_width_store() to change on the fly.
> >>>>>>> Indeed, but a user may also set num-lanes in the device tree. I'm wondering
> >>>>>>> if, when set in device-tree, it will have the desired effect. Because I don't
> >>>>>>> see anything similar to PCIE_LCTLSTS_HW_AW_DIS in dw_pcie_setup which is what
> >>>>>>> your function does here.
> >>>>>>>
> >>>>>>> I guess I'm trying to avoid the suitation where num-lanes doesn't have the
> >>>>>>> desired effect and the only way to set the num-lanes is throught the sysfs
> >>>>>>> control.
> >>>>>> I will check this and get back to you.
> >>>> intel_pcie_max_link_width_setup() is doing the lane resizing which is
> >>>> different from the link up/establishment happening during probe. Also
> >>>> PCIE_LCTLSTS_HW_AW_DIS default value is 0 so not setting during the probe or
> >>>> dw_pcie_setup.
> >>>>
> >>>> intel_pcie_max_link_width_setup() is programming as per the designware PCIe
> >>>> controller databook instructions for lane resizing.
> >>>>
> >>>> Below lines are from Designware PCIe databook for lane resizing.
> >>>>
> >>>>    Program the TARGET_LINK_WIDTH[5:0] field of the MULTI_LANE_CONTROL_OFF
> >>>> register.
> >>>>    Program the DIRECT_LINK_WIDTH_CHANGE2 field of the MULTI_LANE_CONTROL_OFF
> >>>> register.
> >>>> It is assumed that the PCIE_CAP_HW_AUTO_WIDTH_DISABLE field in the
> >>>> LINK_CONTROL_LINK_STATUS_REG register is 0.
> >>> OK, so there is a difference between initial training and then resizing
> >>> of the link. Given that this is not Intel specific, should this function
> >>> exist within the designware driver for the benefit of others?
> >> I am ok to add if maintainer agrees with it.
> 
> Gustavo Pimentel,
> 
> Could you please let us know your opinion on this.

Hi, I just return from parental leave, therefore I still trying to get 
the pace in mailing list discussion.

However your suggestion looks good, I agree that can go into DesignWare 
driver to be available to all.

Just a small request, please do in general:
s/designware/DesignWare

Regards,
Gustavo

> 
> [...]
> 
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static void intel_pcie_port_logic_setup(struct intel_pcie_port *lpp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	u32 val, mask, fts;
> >>>>>>>>>> +
> >>>>>>>>>> +	switch (lpp->max_speed) {
> >>>>>>>>>> +	case PCIE_LINK_SPEED_GEN1:
> >>>>>>>>>> +	case PCIE_LINK_SPEED_GEN2:
> >>>>>>>>>> +		fts = PCIE_AFR_GEN12_FTS_NUM_DFT;
> >>>>>>>>>> +		break;
> [...]
> >>>>>>>>>> +
> >>>>>>>>>> +	if (device_property_read_u32(dev, "max-link-speed", &lpp->link_gen))
> >>>>>>>>>> +		lpp->link_gen = 0; /* Fallback to auto */
> >>>>>>>>> Is it possible to use of_pci_get_max_link_speed here instead?
> >>>>>>>> Thanks for pointing it. of_pci_get_max_link_speed() can be used here. I will
> >>>>>>>> update it in the next patch revision.
> >>>> I just remember, earlier we were using  of_pci_get_max_link_speed() itself.
> >>>> As per reviewer comments changed to device_property_read_u32() to maintain
> >>>> symmetry in parsing device tree properties from device node.
> >>>> Let me know your view.
> >>> I couldn't find an earlier version of this series that used of_pci_get_max_link_speed,
> >>> have I missed it somewhere?
> >> It happened in our internal review.
> >> What's your suggestion please, either to go with symmetry in parsing
> >> "device_property_read_u32()" or with pci helper function
> >> "of_pci_get_max_link_speed"?
> > I'd prefer the helper, the added benefit of this is additional error checking.
> > It also means users can be confident that max-link-speed will behave in the
> > same way as other host controllers that use this field.
> Ok, i will update it in the next patch version.
> 
> 
> Regards,
> 
> Dilip
> 
> >
> > Thanks,
> >
> > Andrew Murray
> >
> >>>>>>>>>> +
> >>>>>>>>>> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app");
> >>>>>>>>>> +	if (!res)
> >>>>>>>>>> +		return -ENXIO;
> >>>>>>>>>> +
> >>>>>>>>>> +	lpp->app_base = devm_ioremap_resource(dev, res);
> >>>>>>>>>> +	if (IS_ERR(lpp->app_base))
> >>>>>>>>>> +		return PTR_ERR(lpp->app_base);
> >>>>>>>>>> +
> >>>>>>>>>> +	ret = intel_pcie_ep_rst_init(lpp);
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		return ret;
> >>>>>>>>> Given that this is called from a function '..._get_resources' I don't think
> >>>>>>>>> we should be resetting anything here.
> >>>>>>>> Agree. I will move it out of get_resources().
> >>>>>>>>>> +
> >>>>>>>>>> +	lpp->phy = devm_phy_get(dev, "pciephy");
> >>>>>>>>>> +	if (IS_ERR(lpp->phy)) {
> >>>>>>>>>> +		ret = PTR_ERR(lpp->phy);
> >>>>>>>>>> +		if (ret != -EPROBE_DEFER)
> >>>>>>>>>> +			dev_err(dev, "couldn't get pcie-phy: %d\n", ret);
> >>>>>>>>>> +		return ret;
> >>>>>>>>>> +	}
> >>>>>>>>>> +	return 0;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static void intel_pcie_deinit_phy(struct intel_pcie_port *lpp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	phy_exit(lpp->phy);
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static int intel_pcie_wait_l2(struct intel_pcie_port *lpp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	u32 value;
> >>>>>>>>>> +	int ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	if (lpp->max_speed < PCIE_LINK_SPEED_GEN3)
> >>>>>>>>>> +		return 0;
> >>>>>>>>>> +
> >>>>>>>>>> +	/* Send PME_TURN_OFF message */
> >>>>>>>>>> +	pcie_app_wr_mask(lpp, PCIE_APP_MSG_XMT_PM_TURNOFF,
> >>>>>>>>>> +			 PCIE_APP_MSG_XMT_PM_TURNOFF, PCIE_APP_MSG_CR);
> >>>>>>>>>> +
> >>>>>>>>>> +	/* Read PMC status and wait for falling into L2 link state */
> >>>>>>>>>> +	ret = readl_poll_timeout(lpp->app_base + PCIE_APP_PMC, value,
> >>>>>>>>>> +				 (value & PCIE_APP_PMC_IN_L2), 20,
> >>>>>>>>>> +				 jiffies_to_usecs(5 * HZ));
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		dev_err(lpp->pci.dev, "PCIe link enter L2 timeout!\n");
> >>>>>>>>>> +
> >>>>>>>>>> +	return ret;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static void intel_pcie_turn_off(struct intel_pcie_port *lpp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	if (dw_pcie_link_up(&lpp->pci))
> >>>>>>>>>> +		intel_pcie_wait_l2(lpp);
> >>>>>>>>>> +
> >>>>>>>>>> +	/* Put EP in reset state */
> >>>>>>>>> EP?
> >>>>>>>> End point device. I will update it.
> >>>>>>> Is this not a host bridge controller?
> >>>>>> It is PERST#, signals hardware reset to the End point .
> >>>>>>            /* Put EP in reset state */
> >>>>>>            intel_pcie_device_rst_assert(lpp);
> >>>>> OK.
> >>>>>
> >>>>>>>>>> +	intel_pcie_device_rst_assert(lpp);
> >>>>>>>>>> +	pcie_rc_cfg_wr_mask(lpp, PCI_COMMAND_MEMORY, 0, PCI_COMMAND);
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static int intel_pcie_host_setup(struct intel_pcie_port *lpp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	int ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	intel_pcie_core_rst_assert(lpp);
> >>>>>>>>>> +	intel_pcie_device_rst_assert(lpp);
> >>>>>>>>>> +
> >>>>>>>>>> +	ret = phy_init(lpp->phy);
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		return ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	intel_pcie_core_rst_deassert(lpp);
> >>>>>>>>>> +
> >>>>>>>>>> +	ret = clk_prepare_enable(lpp->core_clk);
> >>>>>>>>>> +	if (ret) {
> >>>>>>>>>> +		dev_err(lpp->pci.dev, "Core clock enable failed: %d\n", ret);
> >>>>>>>>>> +		goto clk_err;
> >>>>>>>>>> +	}
> >>>>>>>>>> +
> >>>>>>>>>> +	intel_pcie_rc_setup(lpp);
> >>>>>>>>>> +	ret = intel_pcie_app_logic_setup(lpp);
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		goto app_init_err;
> >>>>>>>>>> +
> >>>>>>>>>> +	ret = intel_pcie_setup_irq(lpp);
> >>>>>>>>>> +	if (!ret)
> >>>>>>>>>> +		return ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	intel_pcie_turn_off(lpp);
> >>>>>>>>>> +app_init_err:
> >>>>>>>>>> +	clk_disable_unprepare(lpp->core_clk);
> >>>>>>>>>> +clk_err:
> >>>>>>>>>> +	intel_pcie_core_rst_assert(lpp);
> >>>>>>>>>> +	intel_pcie_deinit_phy(lpp);
> >>>>>>>>>> +	return ret;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static ssize_t
> >>>>>>>>>> +pcie_link_status_show(struct device *dev, struct device_attribute *attr,
> >>>>>>>>>> +		      char *buf)
> >>>>>>>>>> +{
> >>>>>>>>>> +	u32 reg, width, gen;
> >>>>>>>>>> +	struct intel_pcie_port *lpp;
> >>>>>>>>>> +
> >>>>>>>>>> +	lpp = dev_get_drvdata(dev);
> >>>>>>>>>> +
> >>>>>>>>>> +	reg = pcie_rc_cfg_rd(lpp, PCIE_LCTLSTS);
> >>>>>>>>>> +	width = FIELD_GET(PCIE_LCTLSTS_NEGOTIATED_LINK_WIDTH, reg);
> >>>>>>>>>> +	gen = FIELD_GET(PCIE_LCTLSTS_LINK_SPEED, reg);
> >>>>>>>>>> +	if (gen > lpp->max_speed)
> >>>>>>>>>> +		return -EINVAL;
> >>>>>>>>>> +
> >>>>>>>>>> +	return sprintf(buf, "Port %2u Width x%u Speed %s GT/s\n", lpp->id,
> >>>>>>>>>> +		       width, pcie_link_gen_to_str(gen));
> >>>>>>>>>> +}
> >>>>>>>>>> +static DEVICE_ATTR_RO(pcie_link_status);
> >>>>>>>>>> +
> >>>>>>>>>> +static ssize_t pcie_speed_store(struct device *dev,
> >>>>>>>>>> +				struct device_attribute *attr,
> >>>>>>>>>> +				const char *buf, size_t len)
> >>>>>>>>>> +{
> >>>>>>>>>> +	struct intel_pcie_port *lpp;
> >>>>>>>>>> +	unsigned long val;
> >>>>>>>>>> +	int ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	lpp = dev_get_drvdata(dev);
> >>>>>>>>>> +
> >>>>>>>>>> +	ret = kstrtoul(buf, 10, &val);
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		return ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	if (val > lpp->max_speed)
> >>>>>>>>>> +		return -EINVAL;
> >>>>>>>>>> +
> >>>>>>>>>> +	lpp->link_gen = val;
> >>>>>>>>>> +	intel_pcie_max_speed_setup(lpp);
> >>>>>>>>>> +	intel_pcie_speed_change_disable(lpp);
> >>>>>>>>>> +	intel_pcie_speed_change_enable(lpp);
> >>>>>>>>>> +
> >>>>>>>>>> +	return len;
> >>>>>>>>>> +}
> >>>>>>>>>> +static DEVICE_ATTR_WO(pcie_speed);
> >>>>>>>>>> +
> >>>>>>>>>> +/*
> >>>>>>>>>> + * Link width change on the fly is not always successful.
> >>>>>>>>>> + * It also depends on the partner.
> >>>>>>>>>> + */
> >>>>>>>>>> +static ssize_t pcie_width_store(struct device *dev,
> >>>>>>>>>> +				struct device_attribute *attr,
> >>>>>>>>>> +				const char *buf, size_t len)
> >>>>>>>>>> +{
> >>>>>>>>>> +	struct intel_pcie_port *lpp;
> >>>>>>>>>> +	unsigned long val;
> >>>>>>>>>> +
> >>>>>>>>>> +	lpp = dev_get_drvdata(dev);
> >>>>>>>>>> +
> >>>>>>>>>> +	if (kstrtoul(buf, 10, &val))
> >>>>>>>>>> +		return -EINVAL;
> >>>>>>>>>> +
> >>>>>>>>>> +	if (val > lpp->max_width)
> >>>>>>>>>> +		return -EINVAL;
> >>>>>>>>>> +
> >>>>>>>>>> +	lpp->lanes = val;
> >>>>>>>>>> +	intel_pcie_max_link_width_setup(lpp);
> >>>>>>>>>> +
> >>>>>>>>>> +	return len;
> >>>>>>>>>> +}
> >>>>>>>>>> +static DEVICE_ATTR_WO(pcie_width);
> >>>>>>>>> You mentioned that a use-case for changing width/speed on the fly was to
> >>>>>>>>> control power consumption (and this also helps debugging issues). As I
> >>>>>>>>> understand there is no current support for this in the kernel - yet it is
> >>>>>>>>> something that would provide value.
> >>>>>>>>>
> >>>>>>>>> I haven't looked in much detail, however as I understand the PCI spec
> >>>>>>>>> allows an upstream partner to change the link speed and retrain. (I'm not
> >>>>>>>>> sure about link width). Given that we already have
> >>>>>>>>> [current,max]_link_[speed,width] is sysfs for each PCI device, it would
> >>>>>>>>> seem natural to extend this to allow for writing a max width or speed.
> >>>>>>>>>
> >>>>>>>>> So ideally this type of thing would be moved to the core or at least in
> >>>>>>>>> the dwc driver. This way the benefits can be applied to more devices on
> >>>>>>>>> larger PCI fabrics - Though perhaps others here will have a different view
> >>>>>>>>> and I'm keen to hear them.
> >>>>>>>>>
> >>>>>>>>> I'm keen to limit the differences between the DWC controller drivers and
> >>>>>>>>> unify common code - thus it would be helpful to have a justification as to
> >>>>>>>>> why this is only relevant for this controller.
> >>>>>>>>>
> >>>>>>>>> For user-space only control, it is possible to achieve what you have here
> >>>>>>>>> with userspace utilities (something like setpci) (assuming the standard
> >>>>>>>>> looking registers you currently access are exposed in the normal config
> >>>>>>>>> space way - though PCIe capabilities).
> >>>>>>>>>
> >>>>>>>>> My suggestion would be to drop these changes and later add something that
> >>>>>>>>> can benefit more devices. In any case if these changes stay within this
> >>>>>>>>> driver then it would be helpful to move them to a separate patch.
> >>>>>>>> Sure, i will submit these entity in separate patch.
> >>>>>>> Please ensure that all supporting macros, functions and defines go with that
> >>>>>>> other patch as well please.
> >>>>>> Sure.
> >>>>>>>>>> +
> >>>>>>>>>> +static struct attribute *pcie_cfg_attrs[] = {
> >>>>>>>>>> +	&dev_attr_pcie_link_status.attr,
> >>>>>>>>>> +	&dev_attr_pcie_speed.attr,
> >>>>>>>>>> +	&dev_attr_pcie_width.attr,
> >>>>>>>>>> +	NULL,
> >>>>>>>>>> +};
> >>>>>>>>>> +ATTRIBUTE_GROUPS(pcie_cfg);
> >>>>>>>>>> +
> >>>>>>>>>> +static int intel_pcie_sysfs_init(struct intel_pcie_port *lpp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	return devm_device_add_groups(lpp->pci.dev, pcie_cfg_groups);
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static void __intel_pcie_remove(struct intel_pcie_port *lpp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	pcie_rc_cfg_wr_mask(lpp, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
> >>>>>>>>>> +			    0, PCI_COMMAND);
> >>>>>>>>>> +	intel_pcie_core_irq_disable(lpp);
> >>>>>>>>>> +	intel_pcie_turn_off(lpp);
> >>>>>>>>>> +	clk_disable_unprepare(lpp->core_clk);
> >>>>>>>>>> +	intel_pcie_core_rst_assert(lpp);
> >>>>>>>>>> +	intel_pcie_deinit_phy(lpp);
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static int intel_pcie_remove(struct platform_device *pdev)
> >>>>>>>>>> +{
> >>>>>>>>>> +	struct intel_pcie_port *lpp = platform_get_drvdata(pdev);
> >>>>>>>>>> +	struct pcie_port *pp = &lpp->pci.pp;
> >>>>>>>>>> +
> >>>>>>>>>> +	dw_pcie_host_deinit(pp);
> >>>>>>>>>> +	__intel_pcie_remove(lpp);
> >>>>>>>>>> +
> >>>>>>>>>> +	return 0;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static int __maybe_unused intel_pcie_suspend_noirq(struct device *dev)
> >>>>>>>>>> +{
> >>>>>>>>>> +	struct intel_pcie_port *lpp = dev_get_drvdata(dev);
> >>>>>>>>>> +	int ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	intel_pcie_core_irq_disable(lpp);
> >>>>>>>>>> +	ret = intel_pcie_wait_l2(lpp);
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		return ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	intel_pcie_deinit_phy(lpp);
> >>>>>>>>>> +	clk_disable_unprepare(lpp->core_clk);
> >>>>>>>>>> +	return ret;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static int __maybe_unused intel_pcie_resume_noirq(struct device *dev)
> >>>>>>>>>> +{
> >>>>>>>>>> +	struct intel_pcie_port *lpp = dev_get_drvdata(dev);
> >>>>>>>>>> +
> >>>>>>>>>> +	return intel_pcie_host_setup(lpp);
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static int intel_pcie_rc_init(struct pcie_port *pp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> >>>>>>>>>> +	struct intel_pcie_port *lpp = dev_get_drvdata(pci->dev);
> >>>>>>>>>> +	int ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	/* RC/host initialization */
> >>>>>>>>>> +	ret = intel_pcie_host_setup(lpp);
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		return ret;
> >>>>>>>>> Insert new line here.
> >>>>>>>> Ok.
> >>>>>>>>>> +	ret = intel_pcie_sysfs_init(lpp);
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		__intel_pcie_remove(lpp);
> >>>>>>>>>> +	return ret;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +int intel_pcie_msi_init(struct pcie_port *pp)
> >>>>>>>>>> +{
> >>>>>>>>>> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> >>>>>>>>>> +
> >>>>>>>>>> +	dev_dbg(pci->dev, "PCIe MSI/MSIx is handled by MSI in x86 processor\n");
> >>>>>>>>> What about other processors? (Noting that this driver doesn't depend on
> >>>>>>>>> any specific ARCH in the KConfig).
> >>>>>>>> Agree. i will mark the dependency in Kconfig.
> >>>>>>> OK, please also see how other drivers use the COMPILE_TEST Kconfig option.
> >>>>>> Ok sure.
> >>>>>>> I'd suggest that the dev_dbg just becomes a code comment.
> >>>> Ok
> >>>>>>>>>> +	return 0;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr)
> >>>>>>>>>> +{
> >>>>>>>>>> +	return cpu_addr + BUS_IATU_OFFS;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static const struct dw_pcie_ops intel_pcie_ops = {
> >>>>>>>>>> +	.cpu_addr_fixup = intel_pcie_cpu_addr,
> >>>>>>>>>> +};
> >>>>>>>>>> +
> >>>>>>>>>> +static const struct dw_pcie_host_ops intel_pcie_dw_ops = {
> >>>>>>>>>> +	.host_init =		intel_pcie_rc_init,
> >>>>>>>>>> +	.msi_host_init =	intel_pcie_msi_init,
> >>>>>>>>>> +};
> >>>>>>>>>> +
> >>>>>>>>>> +static const struct intel_pcie_soc pcie_data = {
> >>>>>>>>>> +	.pcie_ver =		0x520A,
> >>>>>>>>>> +	.pcie_atu_offset =	0xC0000,
> >>>>>>>>>> +	.num_viewport =		3,
> >>>>>>>>>> +};
> >>>>>>>>>> +
> >>>>>>>>>> +static int intel_pcie_probe(struct platform_device *pdev)
> >>>>>>>>>> +{
> >>>>>>>>>> +	const struct intel_pcie_soc *data;
> >>>>>>>>>> +	struct device *dev = &pdev->dev;
> >>>>>>>>>> +	struct intel_pcie_port *lpp;
> >>>>>>>>>> +	struct pcie_port *pp;
> >>>>>>>>>> +	struct dw_pcie *pci;
> >>>>>>>>>> +	int ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	lpp = devm_kzalloc(dev, sizeof(*lpp), GFP_KERNEL);
> >>>>>>>>>> +	if (!lpp)
> >>>>>>>>>> +		return -ENOMEM;
> >>>>>>>>>> +
> >>>>>>>>>> +	platform_set_drvdata(pdev, lpp);
> >>>>>>>>>> +	pci = &lpp->pci;
> >>>>>>>>>> +	pci->dev = dev;
> >>>>>>>>>> +	pp = &pci->pp;
> >>>>>>>>>> +
> >>>>>>>>>> +	ret = intel_pcie_get_resources(pdev);
> >>>>>>>>>> +	if (ret)
> >>>>>>>>>> +		return ret;
> >>>>>>>>>> +
> >>>>>>>>>> +	data = device_get_match_data(dev);
> >>>>>>>>>> +	pci->ops = &intel_pcie_ops;
> >>>>>>>>>> +	pci->version = data->pcie_ver;
> >>>>>>>>>> +	pci->atu_base = pci->dbi_base + data->pcie_atu_offset;
> >>>>>>>>>> +	pp->ops = &intel_pcie_dw_ops;
> >>>>>>>>>> +
> >>>>>>>>>> +	ret = dw_pcie_host_init(pp);
> >>>>>>>>>> +	if (ret) {
> >>>>>>>>>> +		dev_err(dev, "cannot initialize host\n");
> >>>>>>>>>> +		return ret;
> >>>>>>>>>> +	}
> >>>>>>>>> Add a new line after the closing brace.
> >>>>>>>> Ok
> >>>>>>>>>> +	/* Intel PCIe doesn't configure IO region, so configure
> >>>>>>>>>> +	 * viewport to not to access IO region during register
> >>>>>>>>>> +	 * read write operations.
> >>>>>>>>>> +	 */
> >>>>>>>>>> +	pci->num_viewport = data->num_viewport;
> >>>>>>>>>> +	dev_info(dev,
> >>>>>>>>>> +		 "Intel AXI PCIe Root Complex Port %d Init Done\n", lpp->id);
> >>>>>>>>>> +	return ret;
> >>>>>>>>>> +}
> >>>>>>>>>> +
> >>>>>>>>>> +static const struct dev_pm_ops intel_pcie_pm_ops = {
> >>>>>>>>>> +	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(intel_pcie_suspend_noirq,
> >>>>>>>>>> +				      intel_pcie_resume_noirq)
> >>>>>>>>>> +};
> >>>>>>>>>> +
> >>>>>>>>>> +static const struct of_device_id of_intel_pcie_match[] = {
> >>>>>>>>>> +	{ .compatible = "intel,lgm-pcie", .data = &pcie_data },
> >>>>>>>>>> +	{}
> >>>>>>>>>> +};
> >>>>>>>>>> +
> >>>>>>>>>> +static struct platform_driver intel_pcie_driver = {
> >>>>>>>>>> +	.probe = intel_pcie_probe,
> >>>>>>>>>> +	.remove = intel_pcie_remove,
> >>>>>>>>>> +	.driver = {
> >>>>>>>>>> +		.name = "intel-lgm-pcie",
> >>>>>>>>> Is there a reason why the we use intel-lgm-pcie here and pcie-intel-axi
> >>>>>>>>> elsewhere? What does lgm mean?
> >>>>>>>> lgm is the name of intel SoC.  I will name it to pcie-intel-axi to be
> >>>>>>>> generic.
> >>>>>>> I'm keen to ensure that it is consistently named. I've seen other comments
> >>>>>>> regarding what the name should be - I don't have a strong opinion though
> >>>>>>> I do think that *-axi may be too generic.
> >>>> This PCIe driver is for the Intel Gateway SoCs. So how about naming it is as
> >>>> "pcie-intel-gw"; pcie-intel-gw.c and Kconfig as PCIE_INTEL_GW.
> >>> I don't have a problem with this, though others may have differing views.
> >> Sure. thank you.
> >>> Thanks,
> >>>
> >>> Andrew Murray
> >>>
> >>>> Regards,
> >>>> Dilip
> >>>>
> >>>>>> Ok, i will check and get back to you on this.
> >>>>>> Regards,
> >>>>> Thanks,
> >>>>>
> >>>>> Andrew Murray
> >>>>>
> >>>>>> Dilip
> >>>>>>
> >>>>>>> Thanks,
> >>>>>>>
> >>>>>>> Andrew Murray
> >>>>>>>
> >>>>>>>>> Thanks,
> >>>>>>>>>
> >>>>>>>>> Andrew Murray
> >>>>>>>>>
> >>>>>>>>>> +		.of_match_table = of_intel_pcie_match,
> >>>>>>>>>> +		.pm = &intel_pcie_pm_ops,
> >>>>>>>>>> +	},
> >>>>>>>>>> +};
> >>>>>>>>>> +builtin_platform_driver(intel_pcie_driver);
> >>>>>>>>>> -- 
> >>>>>>>>>> 2.11.0
> >>>>>>>>>>






[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux