From patchwork Wed Jan 9 20:43:01 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 1955501 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 1E3F7DF2EB for ; Wed, 9 Jan 2013 20:50:26 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Tt2Xb-0005C3-JL; Wed, 09 Jan 2013 20:46:27 +0000 Received: from moutng.kundenserver.de ([212.227.17.8]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1Tt2Ux-00045O-N4 for linux-arm-kernel@lists.infradead.org; Wed, 09 Jan 2013 20:43:53 +0000 Received: from mailbox.adnet.avionic-design.de (mailbox.avionic-design.de [109.75.18.3]) by mrelayeu.kundenserver.de (node=mreu1) with ESMTP (Nemesis) id 0Ld1dc-1TAwIZ1ZCq-00ie7l; Wed, 09 Jan 2013 21:43:20 +0100 Received: from localhost (localhost [127.0.0.1]) by mailbox.adnet.avionic-design.de (Postfix) with ESMTP id 000612A28158; Wed, 9 Jan 2013 21:43:17 +0100 (CET) X-Virus-Scanned: amavisd-new at avionic-design.de Received: from mailbox.adnet.avionic-design.de ([127.0.0.1]) by localhost (mailbox.avionic-design.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id c+JN7p5A5+jM; Wed, 9 Jan 2013 21:43:16 +0100 (CET) Received: from mailman.adnet.avionic-design.de (mailman.adnet.avionic-design.de [172.20.31.172]) by mailbox.adnet.avionic-design.de (Postfix) with ESMTP id 5ADAA2A2813C; Wed, 9 Jan 2013 21:43:15 +0100 (CET) Received: from localhost (avionic-0098.adnet.avionic-design.de [172.20.31.233]) by mailman.adnet.avionic-design.de (Postfix) with ESMTP id 964E0100512; Wed, 9 Jan 2013 21:43:11 +0100 (CET) From: Thierry Reding To: linux-tegra@vger.kernel.org Subject: [PATCH 01/14] of/pci: Provide support for parsing PCI DT ranges property Date: Wed, 9 Jan 2013 21:43:01 +0100 Message-Id: <1357764194-12677-2-git-send-email-thierry.reding@avionic-design.de> X-Mailer: git-send-email 1.8.1 In-Reply-To: <1357764194-12677-1-git-send-email-thierry.reding@avionic-design.de> References: <1357764194-12677-1-git-send-email-thierry.reding@avionic-design.de> X-Provags-ID: V02:K0:jWOjdQrL4/57JaSPKrRTwsBTFpk28bOSoQerFfatATR t4n9EtaoMDxk62dygnTpqZuJyDlxK0UiRvOe2nAOJKETB3gzY6 BOVAJg+KGeQlH1yrwDWeHsJoG41OZSOE46+G+Ypxt/l+p4ltx6 xS4/k5f41yq7HBVhozbwG3ggli5ra2wvRJQfBGmiSiGiYu5ydy lKwfUwx5jSpYFKgoDAroLSBpejG2jFGNKqo6l7nG62oaQiy/5L VMAB3b12odWkJiROsG88rqBX2dqcb3axVqnBcVgZf7CubZkJ3V k+mHkozlKRZSgsA+UBvEIiqGdEFvaDZV2EqyF4YyQ/gxXZhYg2 RP3SdlpyeievHv2pTiiZn6aMjDhluYZWgK8378wT19e1sNfJOv V4zhDWlJhk4+K44lHr6nDVbxu4zEx36gnd6kNwO8UUb7dHTH3s dMa1P X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130109_154345_145724_6A1EF0AF X-CRM114-Status: GOOD ( 15.55 ) X-Spam-Score: 1.1 (+) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (1.1 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [212.227.17.8 listed in list.dnswl.org] 3.0 KHOP_BIG_TO_CC Sent to 10+ recipients instaed of Bcc or a list -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Thomas Petazzoni , Jason Gunthorpe , Russell King , Arnd Bergmann , Stephen Warren , linux-pci@vger.kernel.org, devicetree-discuss@lists.ozlabs.org, Liviu Dudau , linux-kernel@vger.kernel.org, Rob Herring , Grant Likely , Bjorn Helgaas , Andrew Murray , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Andrew Murray DT bindings for PCI host bridges often use the ranges property to describe memory and IO ranges - this binding tends to be the same across architectures yet several parsing implementations exist, e.g. arch/mips/pci/pci.c, arch/powerpc/kernel/pci-common.c, arch/sparc/kernel/pci.c and arch/microblaze/pci/pci-common.c (clone of PPC). Some of these duplicate functionality provided by drivers/of/address.c. This patch provides a common iterator-based parser for the ranges property, it is hoped this will reduce DT representation differences between architectures and that architectures will migrate in part to this new parser. It is also hoped (and the motativation for the patch) that this patch will reduce duplication of code when writing host bridge drivers that are supported by multiple architectures. This patch provides struct resources from a device tree node, e.g.: u32 *last = NULL; struct resource res; while ((last = of_pci_process_ranges(np, res, last))) { //do something with res } Platforms with quirks can then do what they like with the resource or migrate common quirk handling to the parser. In an ideal world drivers can just request the obtained resources and pass them on (e.g. pci_add_resource_offset). Signed-off-by: Andrew Murray Signed-off-by: Liviu Dudau Signed-off-by: Thierry Reding --- drivers/of/address.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of_address.h | 9 +++++++ 2 files changed, 72 insertions(+) diff --git a/drivers/of/address.c b/drivers/of/address.c index 0125524..d659527 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -13,6 +13,7 @@ #define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0) static struct of_bus *of_match_bus(struct device_node *np); +static struct of_bus *of_find_bus(const char *name); static int __of_address_to_resource(struct device_node *dev, const __be32 *addrp, u64 size, unsigned int flags, const char *name, struct resource *r); @@ -227,6 +228,57 @@ int of_pci_address_to_resource(struct device_node *dev, int bar, return __of_address_to_resource(dev, addrp, size, flags, NULL, r); } EXPORT_SYMBOL_GPL(of_pci_address_to_resource); + +const __be32 *of_pci_process_ranges(struct device_node *node, + struct resource *res, const __be32 *from) +{ + const __be32 *start, *end; + int na, ns, np, pna; + int rlen; + struct of_bus *bus; + + WARN_ON(!res); + + bus = of_find_bus("pci"); + bus->count_cells(node, &na, &ns); + if (!OF_CHECK_COUNTS(na, ns)) { + pr_err("Bad cell count for %s\n", node->full_name); + return NULL; + } + + pna = of_n_addr_cells(node); + np = pna + na + ns; + + start = of_get_property(node, "ranges", &rlen); + if (start == NULL) + return NULL; + + end = start + rlen / sizeof(__be32); + + if (!from) + from = start; + + while (from + np <= end) { + u64 cpu_addr, size; + + cpu_addr = of_translate_address(node, from + na); + size = of_read_number(from + na + pna, ns); + res->flags = bus->get_flags(from); + from += np; + + if (cpu_addr == OF_BAD_ADDR || size == 0) + continue; + + res->name = node->full_name; + res->start = cpu_addr; + res->end = res->start + size - 1; + res->parent = res->child = res->sibling = NULL; + return from; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(of_pci_process_ranges); #endif /* CONFIG_PCI */ /* @@ -337,6 +389,17 @@ static struct of_bus *of_match_bus(struct device_node *np) return NULL; } +static struct of_bus *of_find_bus(const char *name) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(of_busses); i++) + if (strcmp(name, of_busses[i].name) == 0) + return &of_busses[i]; + + return NULL; +} + static int of_translate_one(struct device_node *parent, struct of_bus *bus, struct of_bus *pbus, __be32 *addr, int na, int ns, int pna, const char *rprop) diff --git a/include/linux/of_address.h b/include/linux/of_address.h index 0506eb5..751e889 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -27,6 +27,8 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } #define pci_address_to_pio pci_address_to_pio #endif +const __be32 *of_pci_process_ranges(struct device_node *node, + struct resource *res, const __be32 *from); #else /* CONFIG_OF_ADDRESS */ #ifndef of_address_to_resource static inline int of_address_to_resource(struct device_node *dev, int index, @@ -53,6 +55,13 @@ static inline const __be32 *of_get_address(struct device_node *dev, int index, { return NULL; } + +static inline const __be32 *of_pci_process_ranges(struct device_node *node, + struct resource *res, + const __be32 *from) +{ + return NULL; +} #endif /* CONFIG_OF_ADDRESS */