On Tue, Oct 01, 2019 at 04:08:45PM +0530, Kishon Vijay Abraham I wrote: > Hi Andrew Murray, > > On 01/10/19 3:37 PM, Andrew Murray wrote: > > Hi Tom, > > > > Thanks for the patch. > > > > I'd suggest that you rename the subject of this series to "PCI: cadence: ..." > > to be consistent with the existing commit history, e.g. git log > > --oneline drivers/pci/controller/pcie-cadence* - you'll also see that you > > don't need a full stop at the end, and you ought to also change the tense > > of the subject, e.g. Refactor driver to ... > > > > See comments inline... > > > > On Mon, Sep 30, 2019 at 05:42:48PM +0100, Tom Joseph wrote: > >> All the platform related APIs/Structures in the driver has been extracted > >> out to a separate file (pcie-cadence-plat.c). This will enable the > >> driver to be used as a core library, which could be used by other > >> platform drivers.Testing was done using simulation environment. > > > > Also change the tense for this description. > > > > This patch appears to take the dwc approach of spliting itself into consise > > parts, such that you can have a generic Cadence driver, yet also leave room > > and share functionality with/for Cadence derivatives - this seems like a > > sensible approach. Though, as you'll see in my comments below, because there > > are no other platform drivers yet - we end up with unused code and confusing > > Kconfig options. > > > > Is there an immediate plan to add another Cadence based controller? - if so > > I'd suggest that you include this patch in that patchset for this new > > controller. Otherwise I'm happy with these changes once the Kconfig and unused > > code are fixed. > > Yes, I'll send J721E support based on this series. I've sent the RFC series > here [1]. I'll work on that while Tom could fix review comments on this series. > > [1] -> https://lkml.org/lkml/2019/6/4/619 I didn't previously see this, however I'll happily review when you repost. Thanks, Andrew Murray > > Thanks > Kishon > > > > >> > >> Signed-off-by: Tom Joseph <tjoseph@xxxxxxxxxxx> > >> --- > >> drivers/pci/controller/Kconfig | 35 +++++++ > >> drivers/pci/controller/Makefile | 1 + > >> drivers/pci/controller/pcie-cadence-ep.c | 78 ++------------- > >> drivers/pci/controller/pcie-cadence-host.c | 77 +++------------ > >> drivers/pci/controller/pcie-cadence-plat.c | 154 +++++++++++++++++++++++++++++ > >> drivers/pci/controller/pcie-cadence.h | 69 +++++++++++++ > >> 6 files changed, 278 insertions(+), 136 deletions(-) > >> create mode 100644 drivers/pci/controller/pcie-cadence-plat.c > >> > >> diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig > >> index fe9f9f1..c175b21 100644 > >> --- a/drivers/pci/controller/Kconfig > >> +++ b/drivers/pci/controller/Kconfig > >> @@ -48,6 +48,41 @@ config PCIE_CADENCE_EP > >> endpoint mode. This PCIe controller may be embedded into many > >> different vendors SoCs. > >> > >> +config PCIE_CADENCE_PLAT > >> + bool "Cadence PCIe endpoint controller" > >> + depends on OF > >> + depends on PCI_ENDPOINT > >> + select PCIE_CADENCE > >> + help > >> + Say Y here if you want to support the Cadence PCIe controller in > >> + endpoint mode. This PCIe controller may be embedded into many > >> + different vendors SoCs. > >> + > >> +config PCIE_CADENCE_PLAT_HOST > >> + bool "Cadence PCIe platform host controller" > >> + depends on OF > >> + depends on PCI > >> + select IRQ_DOMAIN > >> + select PCIE_CADENCE > >> + select PCIE_CADENCE_HOST > >> + select PCIE_CADENCE_PLAT > >> + help > >> + Say Y here if you want to support the Cadence PCIe platform controller in > >> + host mode. This PCIe controller may be embedded into many different > >> + vendors SoCs. > >> + > >> +config PCIE_CADENCE_PLAT_EP > >> + bool "Cadence PCIe platform endpoint controller" > >> + depends on OF > >> + depends on PCI_ENDPOINT > >> + select PCIE_CADENCE > >> + select PCIE_CADENCE_EP > >> + select PCIE_CADENCE_PLAT > >> + help > >> + Say Y here if you want to support the Cadence PCIe platform controller in > >> + endpoint mode. This PCIe controller may be embedded into many > >> + different vendors SoCs. > >> + > > > > I find this too confusing, if I navigate to Cadence PCIe controllers support > > in menuconfig I see these options: > > > > Cadence PCIe host controller > > Cadence PCIe endpoint controller > > Cadence PCIe endpoint controller (NEW) > > Cadence PCIe platform host controller (NEW) > > Cadence PCIe platform endpoint controller (NEW) > > > > I don't think users need to care about the platform/library support, surely > > all they care about is enabling the EP or host bridge controllers for their > > hardware (and then rely on Kconfig to select what is needed). > > > >> endmenu > >> > >> config PCIE_XILINX_NWL > >> diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile > >> index d56a507..676a41e 100644 > >> --- a/drivers/pci/controller/Makefile > >> +++ b/drivers/pci/controller/Makefile > >> @@ -2,6 +2,7 @@ > >> obj-$(CONFIG_PCIE_CADENCE) += pcie-cadence.o > >> obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o > >> obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o > >> +obj-$(CONFIG_PCIE_CADENCE_PLAT) += pcie-cadence-plat.o > >> obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o > >> obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o > >> obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o > >> diff --git a/drivers/pci/controller/pcie-cadence-ep.c b/drivers/pci/controller/pcie-cadence-ep.c > >> index def7820..617a71f 100644 > >> --- a/drivers/pci/controller/pcie-cadence-ep.c > >> +++ b/drivers/pci/controller/pcie-cadence-ep.c > >> @@ -17,35 +17,6 @@ > >> #define CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE 0x1 > >> #define CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY 0x3 > >> > >> -/** > >> - * struct cdns_pcie_ep - private data for this PCIe endpoint controller driver > >> - * @pcie: Cadence PCIe controller > >> - * @max_regions: maximum number of regions supported by hardware > >> - * @ob_region_map: bitmask of mapped outbound regions > >> - * @ob_addr: base addresses in the AXI bus where the outbound regions start > >> - * @irq_phys_addr: base address on the AXI bus where the MSI/legacy IRQ > >> - * dedicated outbound regions is mapped. > >> - * @irq_cpu_addr: base address in the CPU space where a write access triggers > >> - * the sending of a memory write (MSI) / normal message (legacy > >> - * IRQ) TLP through the PCIe bus. > >> - * @irq_pci_addr: used to save the current mapping of the MSI/legacy IRQ > >> - * dedicated outbound region. > >> - * @irq_pci_fn: the latest PCI function that has updated the mapping of > >> - * the MSI/legacy IRQ dedicated outbound region. > >> - * @irq_pending: bitmask of asserted legacy IRQs. > >> - */ > >> -struct cdns_pcie_ep { > >> - struct cdns_pcie pcie; > >> - u32 max_regions; > >> - unsigned long ob_region_map; > >> - phys_addr_t *ob_addr; > >> - phys_addr_t irq_phys_addr; > >> - void __iomem *irq_cpu_addr; > >> - u64 irq_pci_addr; > >> - u8 irq_pci_fn; > >> - u8 irq_pending; > >> -}; > >> - > >> static int cdns_pcie_ep_write_header(struct pci_epc *epc, u8 fn, > >> struct pci_epf_header *hdr) > >> { > >> @@ -396,6 +367,9 @@ static int cdns_pcie_ep_start(struct pci_epc *epc) > >> cfg |= BIT(epf->func_no); > >> cdns_pcie_writel(pcie, CDNS_PCIE_LM_EP_FUNC_CFG, cfg); > >> > >> + if (pcie->ops->cdns_start_link) > >> + return pcie->ops->cdns_start_link(pcie, true); > >> + > >> return 0; > >> } > >> > >> @@ -424,30 +398,18 @@ static const struct pci_epc_ops cdns_pcie_epc_ops = { > >> .get_features = cdns_pcie_ep_get_features, > >> }; > >> > >> -static const struct of_device_id cdns_pcie_ep_of_match[] = { > >> - { .compatible = "cdns,cdns-pcie-ep" }, > >> - > >> - { }, > >> -}; > >> > >> -static int cdns_pcie_ep_probe(struct platform_device *pdev) > >> +int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep) > >> { > >> - struct device *dev = &pdev->dev; > >> + struct device *dev = ep->dev; > >> + struct platform_device *pdev = to_platform_device(dev); > >> struct device_node *np = dev->of_node; > >> - struct cdns_pcie_ep *ep; > >> - struct cdns_pcie *pcie; > >> + struct cdns_pcie *pcie = &ep->pcie; > >> struct pci_epc *epc; > >> struct resource *res; > >> int ret; > >> int phy_count; > >> > >> - ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); > >> - if (!ep) > >> - return -ENOMEM; > >> - > >> - pcie = &ep->pcie; > >> - pcie->is_rc = false; > >> - > >> res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg"); > >> pcie->reg_base = devm_ioremap_resource(dev, res); > >> if (IS_ERR(pcie->reg_base)) { > >> @@ -537,29 +499,3 @@ static int cdns_pcie_ep_probe(struct platform_device *pdev) > >> > >> return ret; > >> } > >> - > >> -static void cdns_pcie_ep_shutdown(struct platform_device *pdev) > >> -{ > >> - struct device *dev = &pdev->dev; > >> - struct cdns_pcie *pcie = dev_get_drvdata(dev); > >> - int ret; > >> - > >> - ret = pm_runtime_put_sync(dev); > >> - if (ret < 0) > >> - dev_dbg(dev, "pm_runtime_put_sync failed\n"); > >> - > >> - pm_runtime_disable(dev); > >> - > >> - cdns_pcie_disable_phy(pcie); > >> -} > >> - > >> -static struct platform_driver cdns_pcie_ep_driver = { > >> - .driver = { > >> - .name = "cdns-pcie-ep", > >> - .of_match_table = cdns_pcie_ep_of_match, > >> - .pm = &cdns_pcie_pm_ops, > >> - }, > >> - .probe = cdns_pcie_ep_probe, > >> - .shutdown = cdns_pcie_ep_shutdown, > >> -}; > >> -builtin_platform_driver(cdns_pcie_ep_driver); > >> diff --git a/drivers/pci/controller/pcie-cadence-host.c b/drivers/pci/controller/pcie-cadence-host.c > >> index 97e2510..55c2085 100644 > >> --- a/drivers/pci/controller/pcie-cadence-host.c > >> +++ b/drivers/pci/controller/pcie-cadence-host.c > >> @@ -11,33 +11,6 @@ > >> > >> #include "pcie-cadence.h" > >> > >> -/** > >> - * struct cdns_pcie_rc - private data for this PCIe Root Complex driver > >> - * @pcie: Cadence PCIe controller > >> - * @dev: pointer to PCIe device > >> - * @cfg_res: start/end offsets in the physical system memory to map PCI > >> - * configuration space accesses > >> - * @bus_range: first/last buses behind the PCIe host controller > >> - * @cfg_base: IO mapped window to access the PCI configuration space of a > >> - * single function at a time > >> - * @max_regions: maximum number of regions supported by the hardware > >> - * @no_bar_nbits: Number of bits to keep for inbound (PCIe -> CPU) address > >> - * translation (nbits sets into the "no BAR match" register) > >> - * @vendor_id: PCI vendor ID > >> - * @device_id: PCI device ID > >> - */ > >> -struct cdns_pcie_rc { > >> - struct cdns_pcie pcie; > >> - struct device *dev; > >> - struct resource *cfg_res; > >> - struct resource *bus_range; > >> - void __iomem *cfg_base; > >> - u32 max_regions; > >> - u32 no_bar_nbits; > >> - u16 vendor_id; > >> - u16 device_id; > >> -}; > >> - > >> static void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, > >> int where) > >> { > >> @@ -92,11 +65,6 @@ static struct pci_ops cdns_pcie_host_ops = { > >> .write = pci_generic_config_write, > >> }; > >> > >> -static const struct of_device_id cdns_pcie_host_of_match[] = { > >> - { .compatible = "cdns,cdns-pcie-host" }, > >> - > >> - { }, > >> -}; > >> > >> static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc) > >> { > >> @@ -233,27 +201,23 @@ static int cdns_pcie_host_init(struct device *dev, > >> return err; > >> } > >> > >> -static int cdns_pcie_host_probe(struct platform_device *pdev) > >> +int cdns_pcie_host_setup(struct cdns_pcie_rc *rc) > >> { > >> - struct device *dev = &pdev->dev; > >> + struct device *dev = rc->dev; > >> + struct platform_device *pdev = to_platform_device(dev); > >> struct device_node *np = dev->of_node; > >> struct pci_host_bridge *bridge; > >> struct list_head resources; > >> - struct cdns_pcie_rc *rc; > >> struct cdns_pcie *pcie; > >> struct resource *res; > >> int ret; > >> int phy_count; > >> > >> - bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc)); > >> + bridge = pci_host_bridge_from_priv(rc); > >> if (!bridge) > >> return -ENOMEM; > >> > >> - rc = pci_host_bridge_priv(bridge); > >> - rc->dev = dev; > >> - > >> pcie = &rc->pcie; > >> - pcie->is_rc = true; > >> > >> rc->max_regions = 32; > >> of_property_read_u32(np, "cdns,max-outbound-regions", &rc->max_regions); > >> @@ -303,6 +267,14 @@ static int cdns_pcie_host_probe(struct platform_device *pdev) > >> goto err_get_sync; > >> } > >> > >> + if (pcie->ops->cdns_start_link) { > >> + ret = pcie->ops->cdns_start_link(pcie, true); > >> + if (ret) { > >> + dev_err(dev, "Failed to start link\n"); > >> + return ret; > >> + } > >> + } > >> + > >> ret = cdns_pcie_host_init(dev, &resources, rc); > >> if (ret) > >> goto err_init; > >> @@ -335,28 +307,3 @@ static int cdns_pcie_host_probe(struct platform_device *pdev) > >> > >> return ret; > >> } > >> - > >> -static void cdns_pcie_shutdown(struct platform_device *pdev) > >> -{ > >> - struct device *dev = &pdev->dev; > >> - struct cdns_pcie *pcie = dev_get_drvdata(dev); > >> - int ret; > >> - > >> - ret = pm_runtime_put_sync(dev); > >> - if (ret < 0) > >> - dev_dbg(dev, "pm_runtime_put_sync failed\n"); > >> - > >> - pm_runtime_disable(dev); > >> - cdns_pcie_disable_phy(pcie); > >> -} > >> - > >> -static struct platform_driver cdns_pcie_host_driver = { > >> - .driver = { > >> - .name = "cdns-pcie-host", > >> - .of_match_table = cdns_pcie_host_of_match, > >> - .pm = &cdns_pcie_pm_ops, > >> - }, > >> - .probe = cdns_pcie_host_probe, > >> - .shutdown = cdns_pcie_shutdown, > >> -}; > >> -builtin_platform_driver(cdns_pcie_host_driver); > >> diff --git a/drivers/pci/controller/pcie-cadence-plat.c b/drivers/pci/controller/pcie-cadence-plat.c > >> new file mode 100644 > >> index 0000000..274615d > >> --- /dev/null > >> +++ b/drivers/pci/controller/pcie-cadence-plat.c > >> @@ -0,0 +1,154 @@ > >> +// SPDX-License-Identifier: GPL-2.0 > >> +// Copyright (c) 2019 Cadence > >> +// Cadence PCIe platform driver. > >> +// Author: Tom Joseph <tjoseph@xxxxxxxxxxx> > >> + > > > > The style of this comment block is consistent with the other cadence files in > > the tree, however the cadence files aren't consistent with the other PCI > > controller drivers (or probably much of the kernel). I don't have any objections > > with this, but ideally we'd eventually move to this: > > > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Cadence PCIe platform driver. > > + * > > + * Copyright (c) 2019 Cadence > > + * > > + * Author: Tom Joseph <tjoseph@xxxxxxxxxxx> > > + */ > > > >> +#include <linux/kernel.h> > >> +#include <linux/of_address.h> > >> +#include <linux/of_pci.h> > >> +#include <linux/platform_device.h> > >> +#include <linux/pm_runtime.h> > >> +#include <linux/of_device.h> > >> +#include "pcie-cadence.h" > >> + > >> +/** > >> + * struct cdns_plat_pcie - private data for this PCIe platform driver > >> + * @pcie: Cadence PCIe controller > >> + * @regmap: pointer to PCIe device > > > > regmap? A leftover from pcie-designware-plat.c? > > > >> + * @is_rc: Set to 1 indicates the PCIe controller mode is Root Complex, > >> + * if 0 it is in Endpoint mode. > >> + */ > >> +struct cdns_plat_pcie { > >> + struct cdns_pcie *pcie; > >> + bool is_rc; > >> +}; > >> + > >> +struct cdns_plat_pcie_of_data { > >> + bool is_rc; > >> +}; > >> + > >> +static const struct of_device_id cdns_plat_pcie_of_match[]; > >> + > >> +int cdns_plat_pcie_link_control(struct cdns_pcie *pcie, bool start) > >> +{ > >> + pr_debug(" %s called\n", __func__); > >> + return 0; > >> +} > >> + > >> +bool cdns_plat_pcie_link_status(struct cdns_pcie *pcie) > >> +{ > >> + pr_debug(" %s called\n", __func__); > >> + return 0; > >> +} > > > > Given that these above two functions are only called through the > > cdns_pcie_common_ops abstraction, they should be declared static. > > > > I also don't understand why they are here in *this* patch - > > cdns_plat_pcie_link_status isn't called anywhere, and even though > > cdns_plat_pcie_link_control is called it doesn't do anything (start > > is always true which makes me wonder if you'll ever get a caller > > that sets it to false). > > > > I'd suggest removing these two functions (and related logic) until > > there is a user. This also makes reviewing the patch easier. > > > >> + > >> +static const struct cdns_pcie_common_ops cdns_pcie_common_ops = { > >> + .cdns_start_link = cdns_plat_pcie_link_control, > >> + .cdns_is_link_up = cdns_plat_pcie_link_status, > >> +}; > >> + > >> +static int cdns_plat_pcie_probe(struct platform_device *pdev) > >> +{ > >> + struct device *dev = &pdev->dev; > >> + struct cdns_plat_pcie *cdns_plat_pcie; > >> + const struct of_device_id *match; > >> + const struct cdns_plat_pcie_of_data *data; > >> + struct pci_host_bridge *bridge; > >> + struct cdns_pcie_rc *rc; > >> + struct cdns_pcie_ep *ep; > >> + int ret; > >> + bool is_rc; > >> + > >> + match = of_match_device(cdns_plat_pcie_of_match, dev); > >> + if (!match) > >> + return -EINVAL; > > > > Add a new line here. > > > >> + data = (struct cdns_plat_pcie_of_data *)match->data; > >> + is_rc = data->is_rc; > >> + > >> + pr_debug(" Started %s with is_rc: %d\n", __func__, is_rc); > >> + cdns_plat_pcie = devm_kzalloc(dev, sizeof(*cdns_plat_pcie), GFP_KERNEL); > >> + if (!cdns_plat_pcie) > >> + return -ENOMEM; > >> + > >> + platform_set_drvdata(pdev, cdns_plat_pcie); > >> + if (is_rc) { > >> + if (!IS_ENABLED(CONFIG_PCIE_CADENCE_PLAT_HOST)) > >> + return -ENODEV; > >> + > >> + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc)); > >> + if (!bridge) > >> + return -ENOMEM; > >> + > >> + rc = pci_host_bridge_priv(bridge); > >> + rc->dev = dev; > >> + rc->pcie.ops = &cdns_pcie_common_ops; > >> + cdns_plat_pcie->pcie = &rc->pcie; > >> + cdns_plat_pcie->is_rc = is_rc; > >> + > >> + ret = cdns_pcie_host_setup(rc); > >> + if (ret < 0) > >> + return ret; > >> + } else { > >> + if (!IS_ENABLED(CONFIG_PCIE_CADENCE_PLAT_EP)) > >> + return -ENODEV; > >> + > >> + ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); > >> + if (!ep) > >> + return -ENOMEM; > >> + ep->dev = dev; > >> + ep->pcie.ops = &cdns_pcie_common_ops; > >> + cdns_plat_pcie->pcie = &ep->pcie; > >> + cdns_plat_pcie->is_rc = is_rc; > >> + > >> + ret = cdns_pcie_ep_setup(ep); > >> + if (ret < 0) > >> + return ret; > >> + } > >> + return 0; > >> +} > >> + > >> + > >> +static void cdns_plat_pcie_shutdown(struct platform_device *pdev) > >> +{ > >> + struct device *dev = &pdev->dev; > >> + struct cdns_pcie *pcie = dev_get_drvdata(dev); > >> + int ret; > >> + > >> + ret = pm_runtime_put_sync(dev); > >> + if (ret < 0) > >> + dev_dbg(dev, "pm_runtime_put_sync failed\n"); > >> + > >> + pm_runtime_disable(dev); > >> + > >> + cdns_pcie_disable_phy(pcie); > >> +} > >> + > >> +static const struct cdns_plat_pcie_of_data cdns_plat_pcie_host_of_data = { > >> + .is_rc = true, > >> +}; > >> + > >> +static const struct cdns_plat_pcie_of_data cdns_plat_pcie_ep_of_data = { > >> + .is_rc = false, > >> +}; > >> + > >> +static const struct of_device_id cdns_plat_pcie_of_match[] = { > >> + { > >> + .compatible = "cdns,cdns-pcie-host", > >> + .data = &cdns_plat_pcie_host_of_data, > >> + }, > >> + { > >> + .compatible = "cdns,cdns-pcie-ep", > >> + .data = &cdns_plat_pcie_ep_of_data, > >> + }, > >> + {}, > >> +}; > >> + > >> +static struct platform_driver cdns_plat_pcie_driver = { > >> + .driver = { > >> + .name = "cdns-pcie", > >> + .of_match_table = cdns_plat_pcie_of_match, > >> + .pm = &cdns_pcie_pm_ops, > >> + }, > >> + .probe = cdns_plat_pcie_probe, > >> + .shutdown = cdns_plat_pcie_shutdown, > >> +}; > >> +builtin_platform_driver(cdns_plat_pcie_driver); > >> diff --git a/drivers/pci/controller/pcie-cadence.h b/drivers/pci/controller/pcie-cadence.h > >> index ae6bf2a..3df902a 100644 > >> --- a/drivers/pci/controller/pcie-cadence.h > >> +++ b/drivers/pci/controller/pcie-cadence.h > >> @@ -190,6 +190,8 @@ enum cdns_pcie_rp_bar { > >> (((code) << 8) & CDNS_PCIE_NORMAL_MSG_CODE_MASK) > >> #define CDNS_PCIE_MSG_NO_DATA BIT(16) > >> > >> +struct cdns_pcie; > >> + > >> enum cdns_pcie_msg_code { > >> MSG_CODE_ASSERT_INTA = 0x20, > >> MSG_CODE_ASSERT_INTB = 0x21, > >> @@ -221,6 +223,11 @@ enum cdns_pcie_msg_routing { > >> MSG_ROUTING_GATHER, > >> }; > >> > >> + > >> +struct cdns_pcie_common_ops { > >> + int (*cdns_start_link)(struct cdns_pcie *pcie, bool start); > >> + bool (*cdns_is_link_up)(struct cdns_pcie *pcie); > >> +}; > >> /** > >> * struct cdns_pcie - private data for Cadence PCIe controller drivers > >> * @reg_base: IO mapped register base > >> @@ -236,8 +243,67 @@ struct cdns_pcie { > >> int phy_count; > >> struct phy **phy; > >> struct device_link **link; > >> + const struct cdns_pcie_common_ops *ops; > >> +}; > >> + > >> +/** > >> + * struct cdns_pcie_rc - private data for this PCIe Root Complex driver > >> + * @pcie: Cadence PCIe controller > >> + * @dev: pointer to PCIe device > >> + * @cfg_res: start/end offsets in the physical system memory to map PCI > >> + * configuration space accesses > >> + * @bus_range: first/last buses behind the PCIe host controller > >> + * @cfg_base: IO mapped window to access the PCI configuration space of a > >> + * single function at a time > >> + * @max_regions: maximum number of regions supported by the hardware > >> + * @no_bar_nbits: Number of bits to keep for inbound (PCIe -> CPU) address > >> + * translation (nbits sets into the "no BAR match" register) > >> + * @vendor_id: PCI vendor ID > >> + * @device_id: PCI device ID > >> + */ > >> +struct cdns_pcie_rc { > >> + struct cdns_pcie pcie; > >> + struct device *dev; > >> + struct resource *cfg_res; > >> + struct resource *bus_range; > >> + void __iomem *cfg_base; > >> + u32 max_regions; > >> + u32 no_bar_nbits; > >> + u16 vendor_id; > >> + u16 device_id; > >> }; > >> > >> +/** > >> + * struct cdns_pcie_ep - private data for this PCIe endpoint controller driver > >> + * @pcie: Cadence PCIe controller > >> + * @max_regions: maximum number of regions supported by hardware > >> + * @ob_region_map: bitmask of mapped outbound regions > >> + * @ob_addr: base addresses in the AXI bus where the outbound regions start > >> + * @irq_phys_addr: base address on the AXI bus where the MSI/legacy IRQ > >> + * dedicated outbound regions is mapped. > >> + * @irq_cpu_addr: base address in the CPU space where a write access triggers > >> + * the sending of a memory write (MSI) / normal message (legacy > >> + * IRQ) TLP through the PCIe bus. > >> + * @irq_pci_addr: used to save the current mapping of the MSI/legacy IRQ > >> + * dedicated outbound region. > >> + * @irq_pci_fn: the latest PCI function that has updated the mapping of > >> + * the MSI/legacy IRQ dedicated outbound region. > >> + * @irq_pending: bitmask of asserted legacy IRQs. > >> + */ > >> +struct cdns_pcie_ep { > >> + struct cdns_pcie pcie; > >> + struct device *dev; > >> + u32 max_regions; > >> + unsigned long ob_region_map; > >> + phys_addr_t *ob_addr; > >> + phys_addr_t irq_phys_addr; > >> + void __iomem *irq_cpu_addr; > >> + u64 irq_pci_addr; > >> + u8 irq_pci_fn; > >> + u8 irq_pending; > >> +}; > >> + > >> + > >> /* Register access */ > >> static inline void cdns_pcie_writeb(struct cdns_pcie *pcie, u32 reg, u8 value) > >> { > >> @@ -306,6 +372,9 @@ static inline u32 cdns_pcie_ep_fn_readl(struct cdns_pcie *pcie, u8 fn, u32 reg) > >> return readl(pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg); > >> } > >> > >> +int cdns_pcie_host_setup(struct cdns_pcie_rc *rc); > >> +int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep); > >> + > > > > What happens if a user only selects the host bridge, will you get a build > > error relating to cdns_plat_pcie_probe not being able to find an > > implementation of cdns_pcie_ep_setup? > > > > Thanks, > > > > Andrew Murray > > > >> void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 fn, > >> u32 r, bool is_io, > >> u64 cpu_addr, u64 pci_addr, size_t size); > >> -- > >> 2.2.2 > >>