From patchwork Mon May 23 09:30:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 9131385 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 68CD360459 for ; Mon, 23 May 2016 09:30:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 56B182822F for ; Mon, 23 May 2016 09:30:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4B61A28230; Mon, 23 May 2016 09:30:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D9EDF28220 for ; Mon, 23 May 2016 09:30:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753617AbcEWJaX (ORCPT ); Mon, 23 May 2016 05:30:23 -0400 Received: from mailout3.w1.samsung.com ([210.118.77.13]:39252 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753435AbcEWJaV (ORCPT ); Mon, 23 May 2016 05:30:21 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0O7M00898IEH1U40@mailout3.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Mon, 23 May 2016 10:30:17 +0100 (BST) X-AuditID: cbfec7f4-f796c6d000001486-b6-5742cda98901 Received: from eusync4.samsung.com ( [203.254.199.214]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 58.73.05254.9ADC2475; Mon, 23 May 2016 10:30:17 +0100 (BST) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0O7M00M2SIECIH30@eusync4.samsung.com>; Mon, 23 May 2016 10:30:17 +0100 (BST) From: Marek Szyprowski To: iommu@lists.linux-foundation.org, linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Marek Szyprowski , Joerg Roedel , Inki Dae , Kukjin Kim , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Subject: [PATCH 3/3] iommu/exynos: Prepare clocks when needed, not in driver probe Date: Mon, 23 May 2016 11:30:09 +0200 Message-id: <1463995809-26862-4-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com> References: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprHLMWRmVeSWpSXmKPExsVy+t/xa7orzzqFG7yawW2xccZ6VotJ9yew WCzYb23ROXsDu8XrF4YW/Y9fM1tsenyN1WLG+X1MFmuP3GV34PR4cnAek8emVZ1sHpuX1HtM vrGc0aNvyypGj8+b5ALYorhsUlJzMstSi/TtErgyvl/PL1isVDHjQF4D41eZLkZODgkBE4lX 176zQ9hiEhfurWcDsYUEljJKHFlb3sXIBWQ3MUns3rqZCSTBJmAo0fW2C6xIRCBf4sXevywg RcwCvxglznW2gxUJC4RILFzYzwxiswioSiw43sUKYvMKeEisvfeUEWKbnMT/lyvA6jkFPCUe LrsLtdlDYv6FKUwTGHkXMDKsYhRNLU0uKE5KzzXUK07MLS7NS9dLzs/dxAgJtS87GBcfszrE KMDBqMTDu4HRKVyINbGsuDL3EKMEB7OSCG/maaAQb0piZVVqUX58UWlOavEhRmkOFiVx3rm7 3ocICaQnlqRmp6YWpBbBZJk4OKUaGBl37Dt78tAZvR+Fe4xe7pVuW8awLXCjUuGUPNbHEhtT 3Kws7EUe3Fdfrua07PIzeb883gYvDyVbUc8K4Z9ak2sfdO8vC9Z+LLgzdMF5DtMd7MzvN+xb +v8mu26mesfpBKdFlvwWCXsO/L3sE+UiL23A6JJy2mSJgAV78S2OT+cPz5/9LDrHSYmlOCPR UIu5qDgRAM9IHaExAgAA Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Make clock preparation together with clk_enable(). This way inactive SYSMMU controllers will not keep clocks prepared all the time. This change allows more fine graded power management in the future. All the code assumes that clock management doesn't fail, so guard clock_prepare_enable() it with BUG_ON(). Signed-off-by: Marek Szyprowski --- drivers/iommu/exynos-iommu.c | 54 +++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 018bcd5d5edc..e0b834375f17 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -322,14 +322,27 @@ static void __sysmmu_set_ptbase(struct sysmmu_drvdata *data, phys_addr_t pgd) __sysmmu_tlb_invalidate(data); } +static void __sysmmu_enable_clocks(struct sysmmu_drvdata *data) +{ + BUG_ON(clk_prepare_enable(data->clk_master)); + BUG_ON(clk_prepare_enable(data->clk)); + BUG_ON(clk_prepare_enable(data->pclk)); + BUG_ON(clk_prepare_enable(data->aclk)); +} + +static void __sysmmu_disable_clocks(struct sysmmu_drvdata *data) +{ + clk_disable_unprepare(data->aclk); + clk_disable_unprepare(data->pclk); + clk_disable_unprepare(data->clk); + clk_disable_unprepare(data->clk_master); +} + static void __sysmmu_get_version(struct sysmmu_drvdata *data) { u32 ver; - clk_enable(data->clk_master); - clk_enable(data->clk); - clk_enable(data->pclk); - clk_enable(data->aclk); + __sysmmu_enable_clocks(data); ver = readl(data->sfrbase + REG_MMU_VERSION); @@ -342,10 +355,7 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data) dev_dbg(data->sysmmu, "hardware version: %d.%d\n", MMU_MAJ_VER(data->version), MMU_MIN_VER(data->version)); - clk_disable(data->aclk); - clk_disable(data->pclk); - clk_disable(data->clk); - clk_disable(data->clk_master); + __sysmmu_disable_clocks(data); } static void show_fault_information(struct sysmmu_drvdata *data, @@ -427,10 +437,7 @@ static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data) writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL); writel(0, data->sfrbase + REG_MMU_CFG); - clk_disable(data->aclk); - clk_disable(data->pclk); - clk_disable(data->clk); - clk_disable(data->clk_master); + __sysmmu_disable_clocks(data); } static bool __sysmmu_disable(struct sysmmu_drvdata *data) @@ -475,10 +482,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data) static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data) { - clk_enable(data->clk_master); - clk_enable(data->clk); - clk_enable(data->pclk); - clk_enable(data->aclk); + __sysmmu_enable_clocks(data); writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL); @@ -488,6 +492,12 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data) writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL); + /* + * SYSMMU driver keeps master's clock enabled only for the short + * time, while accessing the registers. For performing address + * translation during DMA transaction it relies on the client + * driver to enable it. + */ clk_disable(data->clk_master); } @@ -605,27 +615,18 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) data->clk = NULL; else if (IS_ERR(data->clk)) return PTR_ERR(data->clk); - ret = clk_prepare(data->clk); - if (ret) - return ret; data->aclk = devm_clk_get(dev, "aclk"); if (PTR_ERR(data->aclk) == -ENOENT) data->aclk = NULL; else if (IS_ERR(data->aclk)) return PTR_ERR(data->aclk); - ret = clk_prepare(data->aclk); - if (ret) - return ret; data->pclk = devm_clk_get(dev, "pclk"); if (PTR_ERR(data->pclk) == -ENOENT) data->pclk = NULL; else if (IS_ERR(data->pclk)) return PTR_ERR(data->pclk); - ret = clk_prepare(data->pclk); - if (ret) - return ret; if (!data->clk && (!data->aclk || !data->pclk)) { dev_err(dev, "Failed to get device clock(s)!\n"); @@ -637,9 +638,6 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) data->clk_master = NULL; else if (IS_ERR(data->clk_master)) return PTR_ERR(data->clk_master); - ret = clk_prepare(data->clk_master); - if (ret) - return ret; data->sysmmu = dev; spin_lock_init(&data->lock);