@@ -415,19 +415,24 @@ static const struct irq_domain_ops msi_domain_ops = {
.map = dw_pcie_msi_map,
};
-int __init dw_pcie_host_init(struct pcie_port *pp)
+static int __init dw_pcie_common_host_init(struct pcie_port *pp,
+ struct hw_pci *hw)
{
struct device_node *np = pp->dev->of_node;
struct of_pci_range range;
struct of_pci_range_parser parser;
+ struct hw_pci *pci_hw = hw;
u32 val;
- int i;
if (of_pci_range_parser_init(&parser, np)) {
dev_err(pp->dev, "missing ranges property\n");
return -EINVAL;
}
+ /* Default to dw_pci if no hw ops provided */
+ if (!pci_hw)
+ pci_hw = &dw_pci;
+
/* Get the I/O and memory ranges from DT */
for_each_of_pci_range(&parser, &range) {
unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
@@ -467,21 +472,24 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
}
}
- pp->cfg0_base = pp->cfg.start;
- pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
pp->mem_base = pp->mem.start;
-
- pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
- pp->config.cfg0_size);
- if (!pp->va_cfg0_base) {
- dev_err(pp->dev, "error with ioremap in function\n");
- return -ENOMEM;
- }
- pp->va_cfg1_base = devm_ioremap(pp->dev, pp->cfg1_base,
- pp->config.cfg1_size);
- if (!pp->va_cfg1_base) {
- dev_err(pp->dev, "error with ioremap\n");
- return -ENOMEM;
+ if (!pp->version & DW_HW_V3_65) {
+ /* Default is with ATU port. */
+ pp->cfg0_base = pp->cfg.start;
+ pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size;
+
+ pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
+ pp->config.cfg0_size);
+ if (!pp->va_cfg0_base) {
+ dev_err(pp->dev, "error with ioremap in function\n");
+ return -ENOMEM;
+ }
+ pp->va_cfg1_base = devm_ioremap(pp->dev, pp->cfg1_base,
+ pp->config.cfg1_size);
+ if (!pp->va_cfg1_base) {
+ dev_err(pp->dev, "error with ioremap\n");
+ return -ENOMEM;
+ }
}
if (of_property_read_u32(np, "num-lanes", &pp->lanes)) {
@@ -489,19 +497,6 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
return -EINVAL;
}
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- pp->irq_domain = irq_domain_add_linear(pp->dev->of_node,
- MAX_MSI_IRQS, &msi_domain_ops,
- &dw_pcie_msi_chip);
- if (!pp->irq_domain) {
- dev_err(pp->dev, "irq domain init failed\n");
- return -ENXIO;
- }
-
- for (i = 0; i < MAX_MSI_IRQS; i++)
- irq_create_mapping(pp->irq_domain, i);
- }
-
if (pp->ops->host_init)
pp->ops->host_init(pp);
@@ -514,10 +509,10 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
val |= PORT_LOGIC_SPEED_CHANGE;
dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
- dw_pci.nr_controllers = 1;
- dw_pci.private_data = (void **)&pp;
+ pci_hw->nr_controllers = 1;
+ pci_hw->private_data = (void **)&pp;
- pci_common_init_dev(pp->dev, &dw_pci);
+ pci_common_init_dev(pp->dev, pci_hw);
pci_assign_unassigned_resources();
#ifdef CONFIG_PCI_DOMAINS
dw_pci.domain++;
@@ -526,6 +521,52 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
return 0;
}
+/*
+ * dw_pcie_msi_host_init() - Function to initialize msi host controller
+ * @pp: ptr to pcie port
+ * @msi_irqc_np: device node ptr to msi irq controller
+ * @irq_msi_ops: ptr to MSI irq_domain_ops struct
+ *
+ * Function register irq domain for msi irq controller and create mappings
+ * for MSI irqs.
+ */
+static int dw_pcie_msi_host_init(struct pcie_port *pp,
+ struct device_node *msi_irqc_np,
+ const struct irq_domain_ops *msi_irq_ops)
+{
+ const struct irq_domain_ops *msi_irq_domain_ops = msi_irq_ops;
+ int i;
+
+ /* Default to msi_domain_ops if no msi irq domain ops provided */
+ if (!msi_irq_domain_ops)
+ msi_irq_domain_ops = &msi_domain_ops;
+
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
+ pp->irq_domain = irq_domain_add_linear(msi_irqc_np,
+ MAX_MSI_IRQS, msi_irq_domain_ops,
+ &dw_pcie_msi_chip);
+ if (!pp->irq_domain) {
+ dev_err(pp->dev, "irq domain init failed\n");
+ return -ENXIO;
+ }
+
+ for (i = 0; i < MAX_MSI_IRQS; i++)
+ irq_create_mapping(pp->irq_domain, i);
+ }
+ return 0;
+}
+
+int __init dw_pcie_host_init(struct pcie_port *pp)
+{
+ int ret;
+
+ ret = dw_pcie_msi_host_init(pp, pp->dev->of_node, NULL);
+ if (ret)
+ return ret;
+
+ return dw_pcie_common_host_init(pp, NULL);
+}
+
static void dw_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev)
{
/* Program viewport 0 : OUTBOUND : CFG0 */
@@ -51,6 +51,8 @@ struct pcie_port {
int msi_irq;
struct irq_domain *irq_domain;
unsigned long msi_data;
+#define DW_HW_V3_65 BIT(0)
+ u32 version;
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
};
@@ -79,5 +81,4 @@ void dw_pcie_msi_init(struct pcie_port *pp);
int dw_pcie_link_up(struct pcie_port *pp);
void dw_pcie_setup_rc(struct pcie_port *pp);
int dw_pcie_host_init(struct pcie_port *pp);
-
#endif /* _PCIE_DESIGNWARE_H */