diff --git a/drivers/pci/pcie_mediatek.c b/drivers/pci/pcie_mediatek.c index 04d8cc29afd..d88d850924c 100644 --- a/drivers/pci/pcie_mediatek.c +++ b/drivers/pci/pcie_mediatek.c @@ -524,7 +524,7 @@ exit: mtk_pcie_port_free(port); } -static int mtk_pcie_parse_port(struct udevice *dev, u32 slot) +static int mtk_pcie_parse_port(struct udevice *dev, u32 slot, int index) { struct mtk_pcie *pcie = dev_get_priv(dev); struct mtk_pcie_port *port; @@ -545,11 +545,11 @@ static int mtk_pcie_parse_port(struct udevice *dev, u32 slot) if (err) return err; - err = reset_get_by_index(dev, slot, &port->reset); + err = reset_get_by_index(dev, index, &port->reset); if (err) return err; - err = generic_phy_get_by_index(dev, slot, &port->phy); + err = generic_phy_get_by_index(dev, index, &port->phy); if (err) return err; @@ -631,18 +631,58 @@ static int mtk_pcie_parse_port_v2(struct udevice *dev, u32 slot) return 0; } +static int mtk_pcie_subsys_get(struct udevice *dev) +{ + struct mtk_pcie *pcie = dev_get_priv(dev); + ofnode cfg_node; + fdt_addr_t addr; + + cfg_node = ofnode_by_compatible(ofnode_null(), + "mediatek,generic-pciecfg"); + if (!ofnode_valid(cfg_node)) + return -ENOENT; + + addr = ofnode_get_addr(cfg_node); + if (addr == FDT_ADDR_T_NONE) + return -ENODEV; + + pcie->base = map_physmem(addr, 0, MAP_NOCACHE); + if (!pcie->base) + return -ENOENT; + + return 0; +} + static int mtk_pcie_probe(struct udevice *dev) { struct mtk_pcie *pcie = dev_get_priv(dev); struct mtk_pcie_port *port, *tmp; + bool split_pcie_node = false; ofnode subnode; + unsigned int slot; int err; INIT_LIST_HEAD(&pcie->ports); - pcie->base = dev_remap_addr_name(dev, "subsys"); - if (!pcie->base) - return -ENOENT; + /* Check if upstream implementation is used */ + err = mtk_pcie_subsys_get(dev); + if (!err) { + /* + * Assume split port node implementation with "mediatek,generic-pciecfg" + * found. We check reg-names and check if the node is for port0 or port1. + */ + split_pcie_node = true; + if (!strcmp(dev_read_string(dev, "reg-names"), "port0")) + slot = 0; + else if (!strcmp(dev_read_string(dev, "reg-names"), "port1")) + slot = 1; + else + return -EINVAL; + } else { + pcie->base = dev_remap_addr_name(dev, "subsys"); + if (!pcie->base) + return -ENOENT; + } err = clk_get_by_name(dev, "free_ck", &pcie->free_ck); if (err) @@ -653,20 +693,27 @@ static int mtk_pcie_probe(struct udevice *dev) if (err) return err; - dev_for_each_subnode(subnode, dev) { - struct fdt_pci_addr addr; - u32 slot = 0; + if (!split_pcie_node) { + dev_for_each_subnode(subnode, dev) { + struct fdt_pci_addr addr; - if (!ofnode_is_enabled(subnode)) - continue; + slot = 0; - err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); - if (err) - return err; + if (!ofnode_is_enabled(subnode)) + continue; - slot = PCI_DEV(addr.phys_hi); + err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); + if (err) + return err; - err = mtk_pcie_parse_port(dev, slot); + slot = PCI_DEV(addr.phys_hi); + + err = mtk_pcie_parse_port(dev, slot, slot); + if (err) + return err; + } + } else { + err = mtk_pcie_parse_port(dev, slot, 0); if (err) return err; } @@ -682,28 +729,54 @@ static int mtk_pcie_probe_v2(struct udevice *dev) { struct mtk_pcie *pcie = dev_get_priv(dev); struct mtk_pcie_port *port, *tmp; - struct fdt_pci_addr addr; + bool split_pcie_node = false; ofnode subnode; unsigned int slot; int err; INIT_LIST_HEAD(&pcie->ports); - pcie->base = dev_remap_addr_name(dev, "subsys"); - if (!pcie->base) - return -ENOENT; + /* Check if upstream implementation is used */ + err = mtk_pcie_subsys_get(dev); + if (!err) { + /* + * Assume split port node implementation with "mediatek,generic-pciecfg" + * found. We check reg-names and check if the node is for port0 or port1. + */ + split_pcie_node = true; + if (!strcmp(dev_read_string(dev, "reg-names"), "port0")) + slot = 0; + else if (!strcmp(dev_read_string(dev, "reg-names"), "port1")) + slot = 1; + else + return -EINVAL; + } else { + pcie->base = dev_remap_addr_name(dev, "subsys"); + if (!pcie->base) + return -ENOENT; + } pcie->priv = dev; - dev_for_each_subnode(subnode, dev) { - if (!ofnode_is_enabled(subnode)) - continue; + if (!split_pcie_node) { + dev_for_each_subnode(subnode, dev) { + struct fdt_pci_addr addr; - err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); - if (err) - return err; + slot = 0; - slot = PCI_DEV(addr.phys_hi); + if (!ofnode_is_enabled(subnode)) + continue; + + err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); + if (err) + return err; + + slot = PCI_DEV(addr.phys_hi); + err = mtk_pcie_parse_port_v2(dev, slot); + if (err) + return err; + } + } else { err = mtk_pcie_parse_port_v2(dev, slot); if (err) return err;