diff options
| -rw-r--r-- | drivers/pci/pcie_mediatek.c | 127 | 
1 files changed, 100 insertions, 27 deletions
| 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; | 
