From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from ns.lynxeye.de ([87.118.118.114] helo=lynxeye.de) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XXCPD-00031p-PS for barebox@lists.infradead.org; Thu, 25 Sep 2014 17:00:38 +0000 Received: from tellur.intern.lynxeye.de (p57B5E0B8.dip0.t-ipconnect.de [87.181.224.184]) by lynxeye.de (Postfix) with ESMTPA id F009626C2004 for ; Thu, 25 Sep 2014 18:58:57 +0200 (CEST) From: Lucas Stach Date: Thu, 25 Sep 2014 19:05:07 +0200 Message-Id: <1411664709-13699-14-git-send-email-dev@lynxeye.de> In-Reply-To: <1411664709-13699-1-git-send-email-dev@lynxeye.de> References: <1411664709-13699-1-git-send-email-dev@lynxeye.de> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "barebox" Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: [PATCH 13/15] of: import pci range parser from linux To: barebox@lists.infradead.org Signed-off-by: Lucas Stach --- drivers/of/address.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/of_address.h | 51 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/drivers/of/address.c b/drivers/of/address.c index b3cbb15..15f3ade 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -179,6 +179,74 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) } #endif /* CONFIG_OF_ADDRESS_PCI */ +#ifdef CONFIG_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_PCI */ + /* * Array of bus specific translators */ diff --git a/include/of_address.h b/include/of_address.h index 9022ab7..f9c3c0f 100644 --- a/include/of_address.h +++ b/include/of_address.h @@ -4,6 +4,38 @@ #include #include +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 static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } #endif @@ -23,7 +55,11 @@ extern struct device_node *of_find_matching_node_by_address( struct device_node *from, const struct of_device_id *matches, u64 base_address); extern void __iomem *of_iomap(struct device_node *np, int index); - +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_OFTREE */ static inline u64 of_translate_address(struct device_node *dev, @@ -67,6 +103,19 @@ static inline void __iomem *of_iomap(struct device_node *np, int index) 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_OFTREE */ #endif /* __OF_ADDRESS_H */ -- 1.9.3 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox