From patchwork Tue Feb 12 16:28:53 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Petazzoni X-Patchwork-Id: 2129951 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 16666DF23E for ; Tue, 12 Feb 2013 16:39:58 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1U5IrA-0000sU-MD; Tue, 12 Feb 2013 16:37:20 +0000 Received: from mail.free-electrons.com ([94.23.35.102]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1U5Ijk-00030g-9Y for linux-arm-kernel@lists.infradead.org; Tue, 12 Feb 2013 16:29:49 +0000 Received: by mail.free-electrons.com (Postfix, from userid 106) id 42D2EB98; Tue, 12 Feb 2013 17:29:40 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT shortcircuit=ham autolearn=disabled version=3.3.2 Received: from localhost (col31-4-88-188-83-94.fbx.proxad.net [88.188.83.94]) by mail.free-electrons.com (Postfix) with ESMTPSA id 78B35825; Tue, 12 Feb 2013 17:29:39 +0100 (CET) From: Thomas Petazzoni To: Bjorn Helgaas , linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 19/32] arm: plat-orion: introduce orion_{alloc, free}_cpu_win() functions Date: Tue, 12 Feb 2013 17:28:53 +0100 Message-Id: <1360686546-24277-20-git-send-email-thomas.petazzoni@free-electrons.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1360686546-24277-1-git-send-email-thomas.petazzoni@free-electrons.com> References: <1360686546-24277-1-git-send-email-thomas.petazzoni@free-electrons.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130212_112940_561484_24641D79 X-CRM114-Status: GOOD ( 18.50 ) X-Spam-Score: 0.4 (/) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- 3.0 KHOP_BIG_TO_CC Sent to 10+ recipients instaed of Bcc or a list -0.0 SPF_PASS SPF: sender matches SPF record -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Lior Amsalem , Andrew Lunn , Russell King - ARM Linux , Jason Cooper , Arnd Bergmann , Stephen Warren , Thierry Reding , Eran Ben-Avi , Nadav Haklai , Maen Suleiman , Shadi Ammouri , Gregory Clement , Tawfik Bayouk , Jason Gunthorpe 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 In the address decoding code, we implement two new functions: orion_alloc_cpu_win() and orion_free_cpu_win(). The first function finds an unused address decoding window, and configures it according to the given arguments (in terms of base address, size, target, attributes). The second function frees an address decoding window, given a physical base address. Those two new functions will be used by the PCIe code, which needs to dynamically register address decoding windows depending on the PCIe devices that are detected. The orion_free_cpu_win() function is only here to handle error cases in the PCIe devices initialization, in the normal case, address decoding windows are never freed. Signed-off-by: Thomas Petazzoni --- arch/arm/plat-orion/addr-map.c | 75 +++++++++++++++++++++++++++ arch/arm/plat-orion/include/plat/addr-map.h | 7 +++ 2 files changed, 82 insertions(+) diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c index a187524..a7bdc21 100644 --- a/arch/arm/plat-orion/addr-map.c +++ b/arch/arm/plat-orion/addr-map.c @@ -108,6 +108,81 @@ static void orion_disable_cpu_win(const struct orion_addr_map_cfg *cfg, } } +static int orion_window_is_free(const struct orion_addr_map_cfg *cfg, + const int win) +{ + void __iomem *addr = cfg->win_cfg_base(cfg, win); + u32 ctrl = readl(addr + WIN_CTRL_OFF); + return !(ctrl & WIN_CTRL_ENABLE); +} + +/* + * Find an unused address decoding window, and enable it according to + * the arguments passed (base, size, target, attributes, remap). + */ +int orion_alloc_cpu_win(const struct orion_addr_map_cfg *cfg, + const u32 base, const u32 size, + const u8 target, const u8 attr, const u32 remap) +{ + int win; + + /* + * If we don't need to remap, try to first allocate a window + * that doesn't have remapping capabilities, since those are + * pretty limited in number. + */ + if (remap == ORION_ADDR_MAP_NO_REMAP) { + for (win = cfg->remappable_wins; win < cfg->num_wins; win++) + if (orion_window_is_free(cfg, win)) + break; + + if (win < cfg->num_wins) { + orion_setup_cpu_win(cfg, win, base, size, target, attr, remap); + return 0; + } + } + + /* + * We need a remap window, or we haven't found a non-remap + * capable window. + */ + for (win = 0; win < cfg->num_wins; win++) + if (orion_window_is_free(cfg, win)) + break; + + if (win < cfg->num_wins) { + orion_setup_cpu_win(cfg, win, base, size, target, attr, remap); + return 0; + } + + /* No window found */ + return -ENOMEM; +} + +/* + * Free an address decoding window, given its base address. + */ +int orion_free_cpu_win(const struct orion_addr_map_cfg *cfg, + const u32 base) +{ + int win; + + for (win = 0; win < cfg->num_wins; win++) { + void __iomem *addr = cfg->win_cfg_base(cfg, win); + u32 winbase = readl(addr + WIN_BASE_OFF); + + if (orion_window_is_free(cfg, win)) + continue; + + if (winbase == (base & 0xffff0000)) { + orion_disable_cpu_win(cfg, win); + return 0; + } + } + + return -EINVAL; +} + /* * Configure a number of windows. */ diff --git a/arch/arm/plat-orion/include/plat/addr-map.h b/arch/arm/plat-orion/include/plat/addr-map.h index a5b21a9..fc46878 100644 --- a/arch/arm/plat-orion/include/plat/addr-map.h +++ b/arch/arm/plat-orion/include/plat/addr-map.h @@ -51,6 +51,13 @@ void orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg, const u32 size, const u8 target, const u8 attr, const u32 remap); +int orion_alloc_cpu_win(const struct orion_addr_map_cfg *cfg, + const u32 base, const u32 size, + const u8 target, const u8 attr, const u32 remap); + +int orion_free_cpu_win(const struct orion_addr_map_cfg *cfg, + const u32 base); + void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg, const void __iomem *ddr_window_cpu_base); #endif