18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * PCI <-> OF mapping helpers
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2011 IBM Corp.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#define pr_fmt(fmt)	"PCI: OF: " fmt
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/irqdomain.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/pci.h>
128c2ecf20Sopenharmony_ci#include <linux/of.h>
138c2ecf20Sopenharmony_ci#include <linux/of_irq.h>
148c2ecf20Sopenharmony_ci#include <linux/of_address.h>
158c2ecf20Sopenharmony_ci#include <linux/of_pci.h>
168c2ecf20Sopenharmony_ci#include "pci.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI
198c2ecf20Sopenharmony_civoid pci_set_of_node(struct pci_dev *dev)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	if (!dev->bus->dev.of_node)
228c2ecf20Sopenharmony_ci		return;
238c2ecf20Sopenharmony_ci	dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
248c2ecf20Sopenharmony_ci						    dev->devfn);
258c2ecf20Sopenharmony_ci	if (dev->dev.of_node)
268c2ecf20Sopenharmony_ci		dev->dev.fwnode = &dev->dev.of_node->fwnode;
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_civoid pci_release_of_node(struct pci_dev *dev)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	of_node_put(dev->dev.of_node);
328c2ecf20Sopenharmony_ci	dev->dev.of_node = NULL;
338c2ecf20Sopenharmony_ci	dev->dev.fwnode = NULL;
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_civoid pci_set_bus_of_node(struct pci_bus *bus)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	struct device_node *node;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (bus->self == NULL) {
418c2ecf20Sopenharmony_ci		node = pcibios_get_phb_of_node(bus);
428c2ecf20Sopenharmony_ci	} else {
438c2ecf20Sopenharmony_ci		node = of_node_get(bus->self->dev.of_node);
448c2ecf20Sopenharmony_ci		if (node && of_property_read_bool(node, "external-facing"))
458c2ecf20Sopenharmony_ci			bus->self->external_facing = true;
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	bus->dev.of_node = node;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (bus->dev.of_node)
518c2ecf20Sopenharmony_ci		bus->dev.fwnode = &bus->dev.of_node->fwnode;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_civoid pci_release_bus_of_node(struct pci_bus *bus)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	of_node_put(bus->dev.of_node);
578c2ecf20Sopenharmony_ci	bus->dev.of_node = NULL;
588c2ecf20Sopenharmony_ci	bus->dev.fwnode = NULL;
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistruct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	/* This should only be called for PHBs */
648c2ecf20Sopenharmony_ci	if (WARN_ON(bus->self || bus->parent))
658c2ecf20Sopenharmony_ci		return NULL;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	/*
688c2ecf20Sopenharmony_ci	 * Look for a node pointer in either the intermediary device we
698c2ecf20Sopenharmony_ci	 * create above the root bus or its own parent. Normally only
708c2ecf20Sopenharmony_ci	 * the later is populated.
718c2ecf20Sopenharmony_ci	 */
728c2ecf20Sopenharmony_ci	if (bus->bridge->of_node)
738c2ecf20Sopenharmony_ci		return of_node_get(bus->bridge->of_node);
748c2ecf20Sopenharmony_ci	if (bus->bridge->parent && bus->bridge->parent->of_node)
758c2ecf20Sopenharmony_ci		return of_node_get(bus->bridge->parent->of_node);
768c2ecf20Sopenharmony_ci	return NULL;
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistruct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci#ifdef CONFIG_IRQ_DOMAIN
828c2ecf20Sopenharmony_ci	struct irq_domain *d;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	if (!bus->dev.of_node)
858c2ecf20Sopenharmony_ci		return NULL;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* Start looking for a phandle to an MSI controller. */
888c2ecf20Sopenharmony_ci	d = of_msi_get_domain(&bus->dev, bus->dev.of_node, DOMAIN_BUS_PCI_MSI);
898c2ecf20Sopenharmony_ci	if (d)
908c2ecf20Sopenharmony_ci		return d;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	/*
938c2ecf20Sopenharmony_ci	 * If we don't have an msi-parent property, look for a domain
948c2ecf20Sopenharmony_ci	 * directly attached to the host bridge.
958c2ecf20Sopenharmony_ci	 */
968c2ecf20Sopenharmony_ci	d = irq_find_matching_host(bus->dev.of_node, DOMAIN_BUS_PCI_MSI);
978c2ecf20Sopenharmony_ci	if (d)
988c2ecf20Sopenharmony_ci		return d;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	return irq_find_host(bus->dev.of_node);
1018c2ecf20Sopenharmony_ci#else
1028c2ecf20Sopenharmony_ci	return NULL;
1038c2ecf20Sopenharmony_ci#endif
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistatic inline int __of_pci_pci_compare(struct device_node *node,
1078c2ecf20Sopenharmony_ci				       unsigned int data)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	int devfn;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	devfn = of_pci_get_devfn(node);
1128c2ecf20Sopenharmony_ci	if (devfn < 0)
1138c2ecf20Sopenharmony_ci		return 0;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	return devfn == data;
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistruct device_node *of_pci_find_child_device(struct device_node *parent,
1198c2ecf20Sopenharmony_ci					     unsigned int devfn)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	struct device_node *node, *node2;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	for_each_child_of_node(parent, node) {
1248c2ecf20Sopenharmony_ci		if (__of_pci_pci_compare(node, devfn))
1258c2ecf20Sopenharmony_ci			return node;
1268c2ecf20Sopenharmony_ci		/*
1278c2ecf20Sopenharmony_ci		 * Some OFs create a parent node "multifunc-device" as
1288c2ecf20Sopenharmony_ci		 * a fake root for all functions of a multi-function
1298c2ecf20Sopenharmony_ci		 * device we go down them as well.
1308c2ecf20Sopenharmony_ci		 */
1318c2ecf20Sopenharmony_ci		if (of_node_name_eq(node, "multifunc-device")) {
1328c2ecf20Sopenharmony_ci			for_each_child_of_node(node, node2) {
1338c2ecf20Sopenharmony_ci				if (__of_pci_pci_compare(node2, devfn)) {
1348c2ecf20Sopenharmony_ci					of_node_put(node);
1358c2ecf20Sopenharmony_ci					return node2;
1368c2ecf20Sopenharmony_ci				}
1378c2ecf20Sopenharmony_ci			}
1388c2ecf20Sopenharmony_ci		}
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci	return NULL;
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_pci_find_child_device);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/**
1458c2ecf20Sopenharmony_ci * of_pci_get_devfn() - Get device and function numbers for a device node
1468c2ecf20Sopenharmony_ci * @np: device node
1478c2ecf20Sopenharmony_ci *
1488c2ecf20Sopenharmony_ci * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
1498c2ecf20Sopenharmony_ci * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
1508c2ecf20Sopenharmony_ci * and function numbers respectively. On error a negative error code is
1518c2ecf20Sopenharmony_ci * returned.
1528c2ecf20Sopenharmony_ci */
1538c2ecf20Sopenharmony_ciint of_pci_get_devfn(struct device_node *np)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	u32 reg[5];
1568c2ecf20Sopenharmony_ci	int error;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	error = of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg));
1598c2ecf20Sopenharmony_ci	if (error)
1608c2ecf20Sopenharmony_ci		return error;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	return (reg[0] >> 8) & 0xff;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_pci_get_devfn);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci/**
1678c2ecf20Sopenharmony_ci * of_pci_parse_bus_range() - parse the bus-range property of a PCI device
1688c2ecf20Sopenharmony_ci * @node: device node
1698c2ecf20Sopenharmony_ci * @res: address to a struct resource to return the bus-range
1708c2ecf20Sopenharmony_ci *
1718c2ecf20Sopenharmony_ci * Returns 0 on success or a negative error-code on failure.
1728c2ecf20Sopenharmony_ci */
1738c2ecf20Sopenharmony_ciint of_pci_parse_bus_range(struct device_node *node, struct resource *res)
1748c2ecf20Sopenharmony_ci{
1758c2ecf20Sopenharmony_ci	u32 bus_range[2];
1768c2ecf20Sopenharmony_ci	int error;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	error = of_property_read_u32_array(node, "bus-range", bus_range,
1798c2ecf20Sopenharmony_ci					   ARRAY_SIZE(bus_range));
1808c2ecf20Sopenharmony_ci	if (error)
1818c2ecf20Sopenharmony_ci		return error;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	res->name = node->name;
1848c2ecf20Sopenharmony_ci	res->start = bus_range[0];
1858c2ecf20Sopenharmony_ci	res->end = bus_range[1];
1868c2ecf20Sopenharmony_ci	res->flags = IORESOURCE_BUS;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	return 0;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci/**
1938c2ecf20Sopenharmony_ci * This function will try to obtain the host bridge domain number by
1948c2ecf20Sopenharmony_ci * finding a property called "linux,pci-domain" of the given device node.
1958c2ecf20Sopenharmony_ci *
1968c2ecf20Sopenharmony_ci * @node: device tree node with the domain information
1978c2ecf20Sopenharmony_ci *
1988c2ecf20Sopenharmony_ci * Returns the associated domain number from DT in the range [0-0xffff], or
1998c2ecf20Sopenharmony_ci * a negative value if the required property is not found.
2008c2ecf20Sopenharmony_ci */
2018c2ecf20Sopenharmony_ciint of_get_pci_domain_nr(struct device_node *node)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	u32 domain;
2048c2ecf20Sopenharmony_ci	int error;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	error = of_property_read_u32(node, "linux,pci-domain", &domain);
2078c2ecf20Sopenharmony_ci	if (error)
2088c2ecf20Sopenharmony_ci		return error;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	return (u16)domain;
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci/**
2158c2ecf20Sopenharmony_ci * of_pci_check_probe_only - Setup probe only mode if linux,pci-probe-only
2168c2ecf20Sopenharmony_ci *                           is present and valid
2178c2ecf20Sopenharmony_ci */
2188c2ecf20Sopenharmony_civoid of_pci_check_probe_only(void)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	u32 val;
2218c2ecf20Sopenharmony_ci	int ret;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	ret = of_property_read_u32(of_chosen, "linux,pci-probe-only", &val);
2248c2ecf20Sopenharmony_ci	if (ret) {
2258c2ecf20Sopenharmony_ci		if (ret == -ENODATA || ret == -EOVERFLOW)
2268c2ecf20Sopenharmony_ci			pr_warn("linux,pci-probe-only without valid value, ignoring\n");
2278c2ecf20Sopenharmony_ci		return;
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	if (val)
2318c2ecf20Sopenharmony_ci		pci_add_flags(PCI_PROBE_ONLY);
2328c2ecf20Sopenharmony_ci	else
2338c2ecf20Sopenharmony_ci		pci_clear_flags(PCI_PROBE_ONLY);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	pr_info("PROBE_ONLY %sabled\n", val ? "en" : "dis");
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_pci_check_probe_only);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci/**
2408c2ecf20Sopenharmony_ci * devm_of_pci_get_host_bridge_resources() - Resource-managed parsing of PCI
2418c2ecf20Sopenharmony_ci *                                           host bridge resources from DT
2428c2ecf20Sopenharmony_ci * @dev: host bridge device
2438c2ecf20Sopenharmony_ci * @busno: bus number associated with the bridge root bus
2448c2ecf20Sopenharmony_ci * @bus_max: maximum number of buses for this bridge
2458c2ecf20Sopenharmony_ci * @resources: list where the range of resources will be added after DT parsing
2468c2ecf20Sopenharmony_ci * @ib_resources: list where the range of inbound resources (with addresses
2478c2ecf20Sopenharmony_ci *                from 'dma-ranges') will be added after DT parsing
2488c2ecf20Sopenharmony_ci * @io_base: pointer to a variable that will contain on return the physical
2498c2ecf20Sopenharmony_ci * address for the start of the I/O range. Can be NULL if the caller doesn't
2508c2ecf20Sopenharmony_ci * expect I/O ranges to be present in the device tree.
2518c2ecf20Sopenharmony_ci *
2528c2ecf20Sopenharmony_ci * This function will parse the "ranges" property of a PCI host bridge device
2538c2ecf20Sopenharmony_ci * node and setup the resource mapping based on its content. It is expected
2548c2ecf20Sopenharmony_ci * that the property conforms with the Power ePAPR document.
2558c2ecf20Sopenharmony_ci *
2568c2ecf20Sopenharmony_ci * It returns zero if the range parsing has been successful or a standard error
2578c2ecf20Sopenharmony_ci * value if it failed.
2588c2ecf20Sopenharmony_ci */
2598c2ecf20Sopenharmony_cistatic int devm_of_pci_get_host_bridge_resources(struct device *dev,
2608c2ecf20Sopenharmony_ci			unsigned char busno, unsigned char bus_max,
2618c2ecf20Sopenharmony_ci			struct list_head *resources,
2628c2ecf20Sopenharmony_ci			struct list_head *ib_resources,
2638c2ecf20Sopenharmony_ci			resource_size_t *io_base)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	struct device_node *dev_node = dev->of_node;
2668c2ecf20Sopenharmony_ci	struct resource *res, tmp_res;
2678c2ecf20Sopenharmony_ci	struct resource *bus_range;
2688c2ecf20Sopenharmony_ci	struct of_pci_range range;
2698c2ecf20Sopenharmony_ci	struct of_pci_range_parser parser;
2708c2ecf20Sopenharmony_ci	const char *range_type;
2718c2ecf20Sopenharmony_ci	int err;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	if (io_base)
2748c2ecf20Sopenharmony_ci		*io_base = (resource_size_t)OF_BAD_ADDR;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	bus_range = devm_kzalloc(dev, sizeof(*bus_range), GFP_KERNEL);
2778c2ecf20Sopenharmony_ci	if (!bus_range)
2788c2ecf20Sopenharmony_ci		return -ENOMEM;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	dev_info(dev, "host bridge %pOF ranges:\n", dev_node);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	err = of_pci_parse_bus_range(dev_node, bus_range);
2838c2ecf20Sopenharmony_ci	if (err) {
2848c2ecf20Sopenharmony_ci		bus_range->start = busno;
2858c2ecf20Sopenharmony_ci		bus_range->end = bus_max;
2868c2ecf20Sopenharmony_ci		bus_range->flags = IORESOURCE_BUS;
2878c2ecf20Sopenharmony_ci		dev_info(dev, "  No bus range found for %pOF, using %pR\n",
2888c2ecf20Sopenharmony_ci			 dev_node, bus_range);
2898c2ecf20Sopenharmony_ci	} else {
2908c2ecf20Sopenharmony_ci		if (bus_range->end > bus_range->start + bus_max)
2918c2ecf20Sopenharmony_ci			bus_range->end = bus_range->start + bus_max;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci	pci_add_resource(resources, bus_range);
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	/* Check for ranges property */
2968c2ecf20Sopenharmony_ci	err = of_pci_range_parser_init(&parser, dev_node);
2978c2ecf20Sopenharmony_ci	if (err)
2988c2ecf20Sopenharmony_ci		return 0;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	dev_dbg(dev, "Parsing ranges property...\n");
3018c2ecf20Sopenharmony_ci	for_each_of_pci_range(&parser, &range) {
3028c2ecf20Sopenharmony_ci		/* Read next ranges element */
3038c2ecf20Sopenharmony_ci		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
3048c2ecf20Sopenharmony_ci			range_type = "IO";
3058c2ecf20Sopenharmony_ci		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
3068c2ecf20Sopenharmony_ci			range_type = "MEM";
3078c2ecf20Sopenharmony_ci		else
3088c2ecf20Sopenharmony_ci			range_type = "err";
3098c2ecf20Sopenharmony_ci		dev_info(dev, "  %6s %#012llx..%#012llx -> %#012llx\n",
3108c2ecf20Sopenharmony_ci			 range_type, range.cpu_addr,
3118c2ecf20Sopenharmony_ci			 range.cpu_addr + range.size - 1, range.pci_addr);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci		/*
3148c2ecf20Sopenharmony_ci		 * If we failed translation or got a zero-sized region
3158c2ecf20Sopenharmony_ci		 * then skip this range
3168c2ecf20Sopenharmony_ci		 */
3178c2ecf20Sopenharmony_ci		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
3188c2ecf20Sopenharmony_ci			continue;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci		err = of_pci_range_to_resource(&range, dev_node, &tmp_res);
3218c2ecf20Sopenharmony_ci		if (err)
3228c2ecf20Sopenharmony_ci			continue;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci		res = devm_kmemdup(dev, &tmp_res, sizeof(tmp_res), GFP_KERNEL);
3258c2ecf20Sopenharmony_ci		if (!res) {
3268c2ecf20Sopenharmony_ci			err = -ENOMEM;
3278c2ecf20Sopenharmony_ci			goto failed;
3288c2ecf20Sopenharmony_ci		}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci		if (resource_type(res) == IORESOURCE_IO) {
3318c2ecf20Sopenharmony_ci			if (!io_base) {
3328c2ecf20Sopenharmony_ci				dev_err(dev, "I/O range found for %pOF. Please provide an io_base pointer to save CPU base address\n",
3338c2ecf20Sopenharmony_ci					dev_node);
3348c2ecf20Sopenharmony_ci				err = -EINVAL;
3358c2ecf20Sopenharmony_ci				goto failed;
3368c2ecf20Sopenharmony_ci			}
3378c2ecf20Sopenharmony_ci			if (*io_base != (resource_size_t)OF_BAD_ADDR)
3388c2ecf20Sopenharmony_ci				dev_warn(dev, "More than one I/O resource converted for %pOF. CPU base address for old range lost!\n",
3398c2ecf20Sopenharmony_ci					 dev_node);
3408c2ecf20Sopenharmony_ci			*io_base = range.cpu_addr;
3418c2ecf20Sopenharmony_ci		}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	/* Check for dma-ranges property */
3478c2ecf20Sopenharmony_ci	if (!ib_resources)
3488c2ecf20Sopenharmony_ci		return 0;
3498c2ecf20Sopenharmony_ci	err = of_pci_dma_range_parser_init(&parser, dev_node);
3508c2ecf20Sopenharmony_ci	if (err)
3518c2ecf20Sopenharmony_ci		return 0;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	dev_dbg(dev, "Parsing dma-ranges property...\n");
3548c2ecf20Sopenharmony_ci	for_each_of_pci_range(&parser, &range) {
3558c2ecf20Sopenharmony_ci		struct resource_entry *entry;
3568c2ecf20Sopenharmony_ci		/*
3578c2ecf20Sopenharmony_ci		 * If we failed translation or got a zero-sized region
3588c2ecf20Sopenharmony_ci		 * then skip this range
3598c2ecf20Sopenharmony_ci		 */
3608c2ecf20Sopenharmony_ci		if (((range.flags & IORESOURCE_TYPE_BITS) != IORESOURCE_MEM) ||
3618c2ecf20Sopenharmony_ci		    range.cpu_addr == OF_BAD_ADDR || range.size == 0)
3628c2ecf20Sopenharmony_ci			continue;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci		dev_info(dev, "  %6s %#012llx..%#012llx -> %#012llx\n",
3658c2ecf20Sopenharmony_ci			 "IB MEM", range.cpu_addr,
3668c2ecf20Sopenharmony_ci			 range.cpu_addr + range.size - 1, range.pci_addr);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci		err = of_pci_range_to_resource(&range, dev_node, &tmp_res);
3708c2ecf20Sopenharmony_ci		if (err)
3718c2ecf20Sopenharmony_ci			continue;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci		res = devm_kmemdup(dev, &tmp_res, sizeof(tmp_res), GFP_KERNEL);
3748c2ecf20Sopenharmony_ci		if (!res) {
3758c2ecf20Sopenharmony_ci			err = -ENOMEM;
3768c2ecf20Sopenharmony_ci			goto failed;
3778c2ecf20Sopenharmony_ci		}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci		/* Keep the resource list sorted */
3808c2ecf20Sopenharmony_ci		resource_list_for_each_entry(entry, ib_resources)
3818c2ecf20Sopenharmony_ci			if (entry->res->start > res->start)
3828c2ecf20Sopenharmony_ci				break;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci		pci_add_resource_offset(&entry->node, res,
3858c2ecf20Sopenharmony_ci					res->start - range.pci_addr);
3868c2ecf20Sopenharmony_ci	}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	return 0;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cifailed:
3918c2ecf20Sopenharmony_ci	pci_free_resource_list(resources);
3928c2ecf20Sopenharmony_ci	return err;
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_OF_IRQ)
3968c2ecf20Sopenharmony_ci/**
3978c2ecf20Sopenharmony_ci * of_irq_parse_pci - Resolve the interrupt for a PCI device
3988c2ecf20Sopenharmony_ci * @pdev:       the device whose interrupt is to be resolved
3998c2ecf20Sopenharmony_ci * @out_irq:    structure of_phandle_args filled by this function
4008c2ecf20Sopenharmony_ci *
4018c2ecf20Sopenharmony_ci * This function resolves the PCI interrupt for a given PCI device. If a
4028c2ecf20Sopenharmony_ci * device-node exists for a given pci_dev, it will use normal OF tree
4038c2ecf20Sopenharmony_ci * walking. If not, it will implement standard swizzling and walk up the
4048c2ecf20Sopenharmony_ci * PCI tree until an device-node is found, at which point it will finish
4058c2ecf20Sopenharmony_ci * resolving using the OF tree walking.
4068c2ecf20Sopenharmony_ci */
4078c2ecf20Sopenharmony_cistatic int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	struct device_node *dn, *ppnode;
4108c2ecf20Sopenharmony_ci	struct pci_dev *ppdev;
4118c2ecf20Sopenharmony_ci	__be32 laddr[3];
4128c2ecf20Sopenharmony_ci	u8 pin;
4138c2ecf20Sopenharmony_ci	int rc;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	/*
4168c2ecf20Sopenharmony_ci	 * Check if we have a device node, if yes, fallback to standard
4178c2ecf20Sopenharmony_ci	 * device tree parsing
4188c2ecf20Sopenharmony_ci	 */
4198c2ecf20Sopenharmony_ci	dn = pci_device_to_OF_node(pdev);
4208c2ecf20Sopenharmony_ci	if (dn) {
4218c2ecf20Sopenharmony_ci		rc = of_irq_parse_one(dn, 0, out_irq);
4228c2ecf20Sopenharmony_ci		if (!rc)
4238c2ecf20Sopenharmony_ci			return rc;
4248c2ecf20Sopenharmony_ci	}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	/*
4278c2ecf20Sopenharmony_ci	 * Ok, we don't, time to have fun. Let's start by building up an
4288c2ecf20Sopenharmony_ci	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
4298c2ecf20Sopenharmony_ci	 * for PCI. If you do different, then don't use that routine.
4308c2ecf20Sopenharmony_ci	 */
4318c2ecf20Sopenharmony_ci	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
4328c2ecf20Sopenharmony_ci	if (rc != 0)
4338c2ecf20Sopenharmony_ci		goto err;
4348c2ecf20Sopenharmony_ci	/* No pin, exit with no error message. */
4358c2ecf20Sopenharmony_ci	if (pin == 0)
4368c2ecf20Sopenharmony_ci		return -ENODEV;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	/* Now we walk up the PCI tree */
4398c2ecf20Sopenharmony_ci	for (;;) {
4408c2ecf20Sopenharmony_ci		/* Get the pci_dev of our parent */
4418c2ecf20Sopenharmony_ci		ppdev = pdev->bus->self;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci		/* Ouch, it's a host bridge... */
4448c2ecf20Sopenharmony_ci		if (ppdev == NULL) {
4458c2ecf20Sopenharmony_ci			ppnode = pci_bus_to_OF_node(pdev->bus);
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci			/* No node for host bridge ? give up */
4488c2ecf20Sopenharmony_ci			if (ppnode == NULL) {
4498c2ecf20Sopenharmony_ci				rc = -EINVAL;
4508c2ecf20Sopenharmony_ci				goto err;
4518c2ecf20Sopenharmony_ci			}
4528c2ecf20Sopenharmony_ci		} else {
4538c2ecf20Sopenharmony_ci			/* We found a P2P bridge, check if it has a node */
4548c2ecf20Sopenharmony_ci			ppnode = pci_device_to_OF_node(ppdev);
4558c2ecf20Sopenharmony_ci		}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		/*
4588c2ecf20Sopenharmony_ci		 * Ok, we have found a parent with a device-node, hand over to
4598c2ecf20Sopenharmony_ci		 * the OF parsing code.
4608c2ecf20Sopenharmony_ci		 * We build a unit address from the linux device to be used for
4618c2ecf20Sopenharmony_ci		 * resolution. Note that we use the linux bus number which may
4628c2ecf20Sopenharmony_ci		 * not match your firmware bus numbering.
4638c2ecf20Sopenharmony_ci		 * Fortunately, in most cases, interrupt-map-mask doesn't
4648c2ecf20Sopenharmony_ci		 * include the bus number as part of the matching.
4658c2ecf20Sopenharmony_ci		 * You should still be careful about that though if you intend
4668c2ecf20Sopenharmony_ci		 * to rely on this function (you ship a firmware that doesn't
4678c2ecf20Sopenharmony_ci		 * create device nodes for all PCI devices).
4688c2ecf20Sopenharmony_ci		 */
4698c2ecf20Sopenharmony_ci		if (ppnode)
4708c2ecf20Sopenharmony_ci			break;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		/*
4738c2ecf20Sopenharmony_ci		 * We can only get here if we hit a P2P bridge with no node;
4748c2ecf20Sopenharmony_ci		 * let's do standard swizzling and try again
4758c2ecf20Sopenharmony_ci		 */
4768c2ecf20Sopenharmony_ci		pin = pci_swizzle_interrupt_pin(pdev, pin);
4778c2ecf20Sopenharmony_ci		pdev = ppdev;
4788c2ecf20Sopenharmony_ci	}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	out_irq->np = ppnode;
4818c2ecf20Sopenharmony_ci	out_irq->args_count = 1;
4828c2ecf20Sopenharmony_ci	out_irq->args[0] = pin;
4838c2ecf20Sopenharmony_ci	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
4848c2ecf20Sopenharmony_ci	laddr[1] = laddr[2] = cpu_to_be32(0);
4858c2ecf20Sopenharmony_ci	rc = of_irq_parse_raw(laddr, out_irq);
4868c2ecf20Sopenharmony_ci	if (rc)
4878c2ecf20Sopenharmony_ci		goto err;
4888c2ecf20Sopenharmony_ci	return 0;
4898c2ecf20Sopenharmony_cierr:
4908c2ecf20Sopenharmony_ci	if (rc == -ENOENT) {
4918c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev,
4928c2ecf20Sopenharmony_ci			"%s: no interrupt-map found, INTx interrupts not available\n",
4938c2ecf20Sopenharmony_ci			__func__);
4948c2ecf20Sopenharmony_ci		pr_warn_once("%s: possibly some PCI slots don't have level triggered interrupts capability\n",
4958c2ecf20Sopenharmony_ci			__func__);
4968c2ecf20Sopenharmony_ci	} else {
4978c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "%s: failed with rc=%d\n", __func__, rc);
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ci	return rc;
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci/**
5038c2ecf20Sopenharmony_ci * of_irq_parse_and_map_pci() - Decode a PCI IRQ from the device tree and map to a VIRQ
5048c2ecf20Sopenharmony_ci * @dev: The PCI device needing an IRQ
5058c2ecf20Sopenharmony_ci * @slot: PCI slot number; passed when used as map_irq callback. Unused
5068c2ecf20Sopenharmony_ci * @pin: PCI IRQ pin number; passed when used as map_irq callback. Unused
5078c2ecf20Sopenharmony_ci *
5088c2ecf20Sopenharmony_ci * @slot and @pin are unused, but included in the function so that this
5098c2ecf20Sopenharmony_ci * function can be used directly as the map_irq callback to
5108c2ecf20Sopenharmony_ci * pci_assign_irq() and struct pci_host_bridge.map_irq pointer
5118c2ecf20Sopenharmony_ci */
5128c2ecf20Sopenharmony_ciint of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	struct of_phandle_args oirq;
5158c2ecf20Sopenharmony_ci	int ret;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	ret = of_irq_parse_pci(dev, &oirq);
5188c2ecf20Sopenharmony_ci	if (ret)
5198c2ecf20Sopenharmony_ci		return 0; /* Proper return code 0 == NO_IRQ */
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	return irq_create_of_mapping(&oirq);
5228c2ecf20Sopenharmony_ci}
5238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
5248c2ecf20Sopenharmony_ci#endif	/* CONFIG_OF_IRQ */
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_cistatic int pci_parse_request_of_pci_ranges(struct device *dev,
5278c2ecf20Sopenharmony_ci					   struct pci_host_bridge *bridge)
5288c2ecf20Sopenharmony_ci{
5298c2ecf20Sopenharmony_ci	int err, res_valid = 0;
5308c2ecf20Sopenharmony_ci	resource_size_t iobase;
5318c2ecf20Sopenharmony_ci	struct resource_entry *win, *tmp;
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&bridge->windows);
5348c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&bridge->dma_ranges);
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &bridge->windows,
5378c2ecf20Sopenharmony_ci						    &bridge->dma_ranges, &iobase);
5388c2ecf20Sopenharmony_ci	if (err)
5398c2ecf20Sopenharmony_ci		return err;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	err = devm_request_pci_bus_resources(dev, &bridge->windows);
5428c2ecf20Sopenharmony_ci	if (err)
5438c2ecf20Sopenharmony_ci		return err;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	resource_list_for_each_entry_safe(win, tmp, &bridge->windows) {
5468c2ecf20Sopenharmony_ci		struct resource *res = win->res;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci		switch (resource_type(res)) {
5498c2ecf20Sopenharmony_ci		case IORESOURCE_IO:
5508c2ecf20Sopenharmony_ci			err = devm_pci_remap_iospace(dev, res, iobase);
5518c2ecf20Sopenharmony_ci			if (err) {
5528c2ecf20Sopenharmony_ci				dev_warn(dev, "error %d: failed to map resource %pR\n",
5538c2ecf20Sopenharmony_ci					 err, res);
5548c2ecf20Sopenharmony_ci				resource_list_destroy_entry(win);
5558c2ecf20Sopenharmony_ci			}
5568c2ecf20Sopenharmony_ci			break;
5578c2ecf20Sopenharmony_ci		case IORESOURCE_MEM:
5588c2ecf20Sopenharmony_ci			res_valid |= !(res->flags & IORESOURCE_PREFETCH);
5598c2ecf20Sopenharmony_ci			break;
5608c2ecf20Sopenharmony_ci		}
5618c2ecf20Sopenharmony_ci	}
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	if (!res_valid)
5648c2ecf20Sopenharmony_ci		dev_warn(dev, "non-prefetchable memory resource required\n");
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	return 0;
5678c2ecf20Sopenharmony_ci}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ciint devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge)
5708c2ecf20Sopenharmony_ci{
5718c2ecf20Sopenharmony_ci	if (!dev->of_node)
5728c2ecf20Sopenharmony_ci		return 0;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	bridge->swizzle_irq = pci_common_swizzle;
5758c2ecf20Sopenharmony_ci	bridge->map_irq = of_irq_parse_and_map_pci;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	return pci_parse_request_of_pci_ranges(dev, bridge);
5788c2ecf20Sopenharmony_ci}
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI */
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci/**
5838c2ecf20Sopenharmony_ci * This function will try to find the limitation of link speed by finding
5848c2ecf20Sopenharmony_ci * a property called "max-link-speed" of the given device node.
5858c2ecf20Sopenharmony_ci *
5868c2ecf20Sopenharmony_ci * @node: device tree node with the max link speed information
5878c2ecf20Sopenharmony_ci *
5888c2ecf20Sopenharmony_ci * Returns the associated max link speed from DT, or a negative value if the
5898c2ecf20Sopenharmony_ci * required property is not found or is invalid.
5908c2ecf20Sopenharmony_ci */
5918c2ecf20Sopenharmony_ciint of_pci_get_max_link_speed(struct device_node *node)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	u32 max_link_speed;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (of_property_read_u32(node, "max-link-speed", &max_link_speed) ||
5968c2ecf20Sopenharmony_ci	    max_link_speed == 0 || max_link_speed > 4)
5978c2ecf20Sopenharmony_ci		return -EINVAL;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	return max_link_speed;
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_pci_get_max_link_speed);
602