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

Commit 4abbb75b authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'of_pci-3.11' of git://git.infradead.org/users/jcooper/linux into next/cleanup



From Jason Cooper, of/pci changes for v3.11.

The patches had Reviewed-by: from Rob Herring on the lists, but seems to
have been missed from the commit messages. These will be required as a base
for some of the other functionality in this merge window, so taking it through
arm-soc.

Signed-off-by: default avatarOlof Johansson <olof@lixom.net>

* tag 'of_pci-3.11' of git://git.infradead.org/users/jcooper/linux:
  of/pci: Add of_pci_parse_bus_range() function
  of/pci: Add of_pci_get_devfn() function
  of/pci: Provide support for parsing PCI DT ranges property
parents b54338b3 4e23d3f5
Loading
Loading
Loading
Loading
+67 −0
Original line number Original line Diff line number Diff line
@@ -227,6 +227,73 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
	return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
	return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
}
}
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);

int of_pci_range_parser_init(struct of_pci_range_parser *parser,
				struct device_node *node)
{
	const int na = 3, ns = 2;
	int rlen;

	parser->node = node;
	parser->pna = of_n_addr_cells(node);
	parser->np = parser->pna + na + ns;

	parser->range = of_get_property(node, "ranges", &rlen);
	if (parser->range == NULL)
		return -ENOENT;

	parser->end = parser->range + rlen / sizeof(__be32);

	return 0;
}
EXPORT_SYMBOL_GPL(of_pci_range_parser_init);

struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
						struct of_pci_range *range)
{
	const int na = 3, ns = 2;

	if (!range)
		return NULL;

	if (!parser->range || parser->range + parser->np > parser->end)
		return NULL;

	range->pci_space = parser->range[0];
	range->flags = of_bus_pci_get_flags(parser->range);
	range->pci_addr = of_read_number(parser->range + 1, ns);
	range->cpu_addr = of_translate_address(parser->node,
				parser->range + na);
	range->size = of_read_number(parser->range + parser->pna + na, ns);

	parser->range += parser->np;

	/* Now consume following elements while they are contiguous */
	while (parser->range + parser->np <= parser->end) {
		u32 flags, pci_space;
		u64 pci_addr, cpu_addr, size;

		pci_space = be32_to_cpup(parser->range);
		flags = of_bus_pci_get_flags(parser->range);
		pci_addr = of_read_number(parser->range + 1, ns);
		cpu_addr = of_translate_address(parser->node,
				parser->range + na);
		size = of_read_number(parser->range + parser->pna + na, ns);

		if (flags != range->flags)
			break;
		if (pci_addr != range->pci_addr + range->size ||
		    cpu_addr != range->cpu_addr + range->size)
			break;

		range->size += size;
		parser->range += parser->np;
	}

	return range;
}
EXPORT_SYMBOL_GPL(of_pci_range_parser_one);

#endif /* CONFIG_PCI */
#endif /* CONFIG_PCI */


/*
/*
+54 −5
Original line number Original line Diff line number Diff line
@@ -5,14 +5,15 @@
#include <asm/prom.h>
#include <asm/prom.h>


static inline int __of_pci_pci_compare(struct device_node *node,
static inline int __of_pci_pci_compare(struct device_node *node,
				       unsigned int devfn)
				       unsigned int data)
{
{
	unsigned int size;
	int devfn;
	const __be32 *reg = of_get_property(node, "reg", &size);


	if (!reg || size < 5 * sizeof(__be32))
	devfn = of_pci_get_devfn(node);
	if (devfn < 0)
		return 0;
		return 0;
	return ((be32_to_cpup(&reg[0]) >> 8) & 0xff) == devfn;

	return devfn == data;
}
}


struct device_node *of_pci_find_child_device(struct device_node *parent,
struct device_node *of_pci_find_child_device(struct device_node *parent,
@@ -40,3 +41,51 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
	return NULL;
	return NULL;
}
}
EXPORT_SYMBOL_GPL(of_pci_find_child_device);
EXPORT_SYMBOL_GPL(of_pci_find_child_device);

/**
 * of_pci_get_devfn() - Get device and function numbers for a device node
 * @np: device node
 *
 * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
 * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
 * and function numbers respectively. On error a negative error code is
 * returned.
 */
int of_pci_get_devfn(struct device_node *np)
{
	unsigned int size;
	const __be32 *reg;

	reg = of_get_property(np, "reg", &size);

	if (!reg || size < 5 * sizeof(__be32))
		return -EINVAL;

	return (be32_to_cpup(reg) >> 8) & 0xff;
}
EXPORT_SYMBOL_GPL(of_pci_get_devfn);

/**
 * of_pci_parse_bus_range() - parse the bus-range property of a PCI device
 * @node: device node
 * @res: address to a struct resource to return the bus-range
 *
 * Returns 0 on success or a negative error-code on failure.
 */
int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
{
	const __be32 *values;
	int len;

	values = of_get_property(node, "bus-range", &len);
	if (!values || len < sizeof(*values) * 2)
		return -EINVAL;

	res->name = node->name;
	res->start = be32_to_cpup(values++);
	res->end = be32_to_cpup(values);
	res->flags = IORESOURCE_BUS;

	return 0;
}
EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+48 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,36 @@
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/of.h>
#include <linux/of.h>


struct of_pci_range_parser {
	struct device_node *node;
	const __be32 *range;
	const __be32 *end;
	int np;
	int pna;
};

struct of_pci_range {
	u32 pci_space;
	u64 pci_addr;
	u64 cpu_addr;
	u64 size;
	u32 flags;
};

#define for_each_of_pci_range(parser, range) \
	for (; of_pci_range_parser_one(parser, range);)

static inline void of_pci_range_to_resource(struct of_pci_range *range,
					    struct device_node *np,
					    struct resource *res)
{
	res->flags = range->flags;
	res->start = range->cpu_addr;
	res->end = range->cpu_addr + range->size - 1;
	res->parent = res->child = res->sibling = NULL;
	res->name = np->full_name;
}

#ifdef CONFIG_OF_ADDRESS
#ifdef CONFIG_OF_ADDRESS
extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
extern bool of_can_translate_address(struct device_node *dev);
extern bool of_can_translate_address(struct device_node *dev);
@@ -27,6 +57,11 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
#define pci_address_to_pio pci_address_to_pio
#define pci_address_to_pio pci_address_to_pio
#endif
#endif


extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
			struct device_node *node);
extern struct of_pci_range *of_pci_range_parser_one(
					struct of_pci_range_parser *parser,
					struct of_pci_range *range);
#else /* CONFIG_OF_ADDRESS */
#else /* CONFIG_OF_ADDRESS */
#ifndef of_address_to_resource
#ifndef of_address_to_resource
static inline int of_address_to_resource(struct device_node *dev, int index,
static inline int of_address_to_resource(struct device_node *dev, int index,
@@ -53,6 +88,19 @@ static inline const __be32 *of_get_address(struct device_node *dev, int index,
{
{
	return NULL;
	return NULL;
}
}

static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,
			struct device_node *node)
{
	return -1;
}

static inline struct of_pci_range *of_pci_range_parser_one(
					struct of_pci_range_parser *parser,
					struct of_pci_range *range)
{
	return NULL;
}
#endif /* CONFIG_OF_ADDRESS */
#endif /* CONFIG_OF_ADDRESS */




+2 −0
Original line number Original line Diff line number Diff line
@@ -10,5 +10,7 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq);
struct device_node;
struct device_node;
struct device_node *of_pci_find_child_device(struct device_node *parent,
struct device_node *of_pci_find_child_device(struct device_node *parent,
					     unsigned int devfn);
					     unsigned int devfn);
int of_pci_get_devfn(struct device_node *np);
int of_pci_parse_bus_range(struct device_node *node, struct resource *res);


#endif
#endif