Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea0b4d40 authored by Hemant Kumar's avatar Hemant Kumar
Browse files

pci/of: expand match PCI devices to OF nodes



Expand match criteria so that multiple OF nodes with
the same BDF will match with the correct PCI device.
OF node will have an optional compatible entry with
device and vendor ID, which will be matched to a PCI
device and vendor ID.

Change-Id: I6e654d5dbf55a05b4e1b6a60d5d87addc2cb14b9
Signed-off-by: default avatarTony Truong <truong@codeaurora.org>
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
parent 1a6f8ce5
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -20,8 +20,12 @@ void pci_set_of_node(struct pci_dev *dev)
{
	if (!dev->bus->dev.of_node)
		return;
#ifdef CONFIG_PCI_QTI
	dev->dev.of_node = of_pci_find_child_device(dev);
#else
	dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
						    dev->devfn);
#endif
	if (dev->dev.of_node)
		dev->dev.fwnode = &dev->dev.of_node->fwnode;
}
@@ -115,6 +119,50 @@ static inline int __of_pci_pci_compare(struct device_node *node,
	return devfn == data;
}

#ifdef CONFIG_PCI_QTI
static inline bool __of_pci_pci_compare_id(struct device_node *node,
					   struct pci_dev *dev)
{
	char dev_id_str[10];
	int index;

	scnprintf(dev_id_str, sizeof(dev_id_str), "%04x:%04x", dev->vendor,
			dev->device);

	index = of_property_match_string(node, "pci-ids", dev_id_str);
	if (index < 0 && index != -EINVAL)
		return false;

	return true;
}

struct device_node *of_pci_find_child_device(struct pci_dev *dev)
{
	struct device_node *node, *node2;
	struct device_node *parent = dev->bus->dev.of_node;
	unsigned int devfn = dev->devfn;

	for_each_child_of_node(parent, node) {
		if (__of_pci_pci_compare(node, devfn))
			if (__of_pci_pci_compare_id(node, dev))
				return node;
		/*
		 * Some OFs create a parent node "multifunc-device" as
		 * a fake root for all functions of a multi-function
		 * device we go down them as well.
		 */
		if (of_node_name_eq(node, "multifunc-device")) {
			for_each_child_of_node(node, node2) {
				if (__of_pci_pci_compare(node2, devfn)) {
					of_node_put(node);
					return node2;
				}
			}
		}
	}
	return NULL;
}
#else
struct device_node *of_pci_find_child_device(struct device_node *parent,
					     unsigned int devfn)
{
@@ -139,6 +187,7 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
	}
	return NULL;
}
#endif
EXPORT_SYMBOL_GPL(of_pci_find_child_device);

/**
+11 −0
Original line number Diff line number Diff line
@@ -10,16 +10,27 @@ struct of_phandle_args;
struct device_node;

#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_PCI)
#ifdef CONFIG_PCI_QTI
struct device_node *of_pci_find_child_device(struct pci_dev *dev);
#else
struct device_node *of_pci_find_child_device(struct device_node *parent,
					     unsigned int devfn);
#endif
int of_pci_get_devfn(struct device_node *np);
void of_pci_check_probe_only(void);
#else
#ifdef CONFIG_PCI_QTI
static inline struct device_node *of_pci_find_child_device(struct pci_dev *dev)
{
	return NULL;
}
#else
static inline struct device_node *of_pci_find_child_device(struct device_node *parent,
					     unsigned int devfn)
{
	return NULL;
}
#endif

static inline int of_pci_get_devfn(struct device_node *np)
{