of: import pci range parser from linux
Signed-off-by: Lucas Stach <dev@lynxeye.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
7a2255b43e
commit
2840294a51
|
@ -30,6 +30,7 @@ config OF_GPIO
|
||||||
config OF_PCI
|
config OF_PCI
|
||||||
bool
|
bool
|
||||||
depends on PCI
|
depends on PCI
|
||||||
|
select OF_ADDRESS_PCI
|
||||||
help
|
help
|
||||||
OpenFirmware PCI bus accessors
|
OpenFirmware PCI bus accessors
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,74 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_OF_ADDRESS_PCI */
|
#endif /* CONFIG_OF_ADDRESS_PCI */
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF_PCI
|
||||||
|
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_OF_PCI */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Array of bus specific translators
|
* Array of bus specific translators
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,6 +4,38 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <of.h>
|
#include <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 = NULL;
|
||||||
|
INIT_LIST_HEAD(&res->children);
|
||||||
|
INIT_LIST_HEAD(&res->sibling);
|
||||||
|
res->name = np->full_name;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef pci_address_to_pio
|
#ifndef pci_address_to_pio
|
||||||
static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
|
static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,4 +101,29 @@ static inline void __iomem *of_iomap(struct device_node *np, int index)
|
||||||
|
|
||||||
#endif /* CONFIG_OFTREE */
|
#endif /* CONFIG_OFTREE */
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF_PCI
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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_PCI */
|
||||||
|
|
||||||
#endif /* __OF_ADDRESS_H */
|
#endif /* __OF_ADDRESS_H */
|
||||||
|
|
Loading…
Reference in New Issue