From patchwork Mon Sep 22 04:47:02 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abhilash Kesavan X-Patchwork-Id: 4945501 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 9EA95BEEA5 for ; Mon, 22 Sep 2014 04:47:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0F3AD20219 for ; Mon, 22 Sep 2014 04:47:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3EBB82024C for ; Mon, 22 Sep 2014 04:47:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752632AbaIVEre (ORCPT ); Mon, 22 Sep 2014 00:47:34 -0400 Received: from mailout4.samsung.com ([203.254.224.34]:47837 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751498AbaIVErd (ORCPT ); Mon, 22 Sep 2014 00:47:33 -0400 Received: from epcpsbgr2.samsung.com (u142.gpu120.samsung.co.kr [203.254.230.142]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0NCA00MZLDB73G40@mailout4.samsung.com>; Mon, 22 Sep 2014 13:47:31 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.126]) by epcpsbgr2.samsung.com (EPCPMTA) with SMTP id 90.6B.11124.3E9AF145; Mon, 22 Sep 2014 13:47:31 +0900 (KST) X-AuditID: cbfee68e-f79b46d000002b74-f6-541fa9e3fd57 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 89.ED.09430.2E9AF145; Mon, 22 Sep 2014 13:47:31 +0900 (KST) Received: from abhilash-ubuntu.sisodomain.com ([107.108.73.92]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0NCA00BJEDAQ2W10@mmp2.samsung.com>; Mon, 22 Sep 2014 13:47:30 +0900 (KST) From: Abhilash Kesavan To: linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, catalin.marinas@arm.com Cc: tomasz.figa@gmail.com, naveenkrishna.ch@gmail.com, kesavan.abhilash@gmail.com Subject: [PATCH v5 2/8] clk: samsung: Factor out the common code to clk.c Date: Mon, 22 Sep 2014 10:17:02 +0530 Message-id: <1411361228-18279-3-git-send-email-a.kesavan@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1411361228-18279-1-git-send-email-a.kesavan@samsung.com> References: <1411361228-18279-1-git-send-email-a.kesavan@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrCLMWRmVeSWpSXmKPExsWyRsSkTvfxSvkQg7aJ/Bbvl/UwWsw/co7V Ys1fJYtNj6+xWsw4v4/JYtG2/8wWq3b9YXRg91gzbw2jx85Zd9k9Ni+p9/i8SS6AJYrLJiU1 J7MstUjfLoErY8PCv4wFe6YyVvxe/4a1gfFnbRcjJ4eEgInEqXeNrBC2mMSFe+vZuhi5OIQE ljJKzNv1igWmaP6CW4wQiemMErOfHWeGcPqYJPbfXAbWziagJ7Hg31ewhIhAE6PExROrmUES zALBEss//GADsYUFPCVetV8AGsXBwSKgKrF6sSRImFfAVWLWhQUsIGEJAQWJOZNsQMKcAm4S r+Z8YQIJCwGVzLidBjJdQmAyu8SfuxMZQWpYBAQkvk0+BNUqK7HpADPEzZISB1fcYJnAKLyA kWEVo2hqQXJBcVJ6kZFecWJucWleul5yfu4mRmBgn/73rG8H480D1ocYBTgYlXh4f7TIhwix JpYVV+YeYjQF2jCRWUo0OR8YP3kl8YbGZkYWpiamxkbmlmZK4rwJUj+DhQTSE0tSs1NTC1KL 4otKc1KLDzEycXBKNTBaO+7Yc4Y35P6qXYvEzPx4NYNkrCLmp6wV4Of7uuT7rsDQd/524u7J 5fwbzLimT2zbyJj791VSTs15w/y5bBs/S/avDVs8/cZvwc07LafsiZHWP/I6PlpK7yl7otb3 2G/Zez0rGUUUeq34S7OXNp8P8LHK9uvSNz7b7qceOD+C375e6O7DcCWW4oxEQy3mouJEANhk 9xRnAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprLIsWRmVeSWpSXmKPExsVy+t9jQd3HK+VDDCaFWbxf1sNoMf/IOVaL NX+VLDY9vsZqMeP8PiaLRdv+M1us2vWH0YHdY828NYweO2fdZffYvKTe4/MmuQCWqAZGm4zU xJTUIoXUvOT8lMy8dFsl7+B453hTMwNDXUNLC3MlhbzE3FRbJRefAF23zByg/UoKZYk5pUCh gMTiYiV9O0wTQkPcdC1gGiN0fUOC4HqMDNBAwhrGjA0L/zIW7JnKWPF7/RvWBsaftV2MnBwS AiYS8xfcYoSwxSQu3FvP1sXIxSEkMJ1RYvaz48wQTh+TxP6by1hBqtgE9CQW/PsKlhARaGKU uHhiNTNIglkgWGL5hx9sILawgKfEq/YLQGM5OFgEVCVWL5YECfMKuErMurCABSQsIaAgMWeS DUiYU8BN4tWcL0wgYSGgkhm30yYw8i5gZFjFKJpakFxQnJSea6RXnJhbXJqXrpecn7uJERw1 z6R3MK5qsDjEKMDBqMTD+6NFPkSINbGsuDL3EKMEB7OSCO/RHKAQb0piZVVqUX58UWlOavEh RlOgkyYyS4km5wMjOq8k3tDYxNzU2NTSxMLEzFJJnPdgq3WgkEB6YklqdmpqQWoRTB8TB6dU AyOzzsQHhzrqJp6IuvyIeRaPwplpwrcKt3qYn5IWeKYms4eLm/dYe1nzSaOf8toM3fvFMlN+ lFroTkiKCBI7X3Vk8dFPS32rW7iKHi6a3/P1kqT555iFL6+JGbRu0pO6EZ+4xaypW9S597/O h0eaLhZrq76tlbnt37ig/PqVmUEuOpOL+UTy/iqxFGckGmoxFxUnAgCkGzE2sAIAAA== DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Naveen Krishna Ch While adding clock support for Exynos5260, the infrastructure to register multiple clock controllers was introduced. Factor out the support for registering multiple clock controller from Exynos5260 clock code to common samsung clock code so that it can be used by other Exynos SoC which have multiple clock controllers. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Reviewed-by: Thomas Abraham Tested-by: Thomas Abraham Cc: Tomasz Figa Cc: Mike Turquette --- drivers/clk/samsung/clk-exynos5260.c | 185 +++++------------------------------ drivers/clk/samsung/clk.c | 95 ++++++++++++++++++ drivers/clk/samsung/clk.h | 34 +++++++ 3 files changed, 155 insertions(+), 159 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c index ce3de97..64aeadf 100644 --- a/drivers/clk/samsung/clk-exynos5260.c +++ b/drivers/clk/samsung/clk-exynos5260.c @@ -11,10 +11,8 @@ #include #include -#include #include #include -#include #include "clk-exynos5260.h" #include "clk.h" @@ -22,39 +20,6 @@ #include -static LIST_HEAD(clock_reg_cache_list); - -struct exynos5260_clock_reg_cache { - struct list_head node; - void __iomem *reg_base; - struct samsung_clk_reg_dump *rdump; - unsigned int rd_num; -}; - -struct exynos5260_cmu_info { - /* list of pll clocks and respective count */ - struct samsung_pll_clock *pll_clks; - unsigned int nr_pll_clks; - /* list of mux clocks and respective count */ - struct samsung_mux_clock *mux_clks; - unsigned int nr_mux_clks; - /* list of div clocks and respective count */ - struct samsung_div_clock *div_clks; - unsigned int nr_div_clks; - /* list of gate clocks and respective count */ - struct samsung_gate_clock *gate_clks; - unsigned int nr_gate_clks; - /* list of fixed clocks and respective count */ - struct samsung_fixed_rate_clock *fixed_clks; - unsigned int nr_fixed_clks; - /* total number of clocks with IDs assigned*/ - unsigned int nr_clk_ids; - - /* list and number of clocks registers */ - unsigned long *clk_regs; - unsigned int nr_clk_regs; -}; - /* * Applicable for all 2550 Type PLLS for Exynos5260, listed below * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. @@ -113,104 +78,6 @@ static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = { PLL_36XX_RATE(66000000, 176, 2, 5, 0), }; -#ifdef CONFIG_PM_SLEEP - -static int exynos5260_clk_suspend(void) -{ - struct exynos5260_clock_reg_cache *cache; - - list_for_each_entry(cache, &clock_reg_cache_list, node) - samsung_clk_save(cache->reg_base, cache->rdump, - cache->rd_num); - - return 0; -} - -static void exynos5260_clk_resume(void) -{ - struct exynos5260_clock_reg_cache *cache; - - list_for_each_entry(cache, &clock_reg_cache_list, node) - samsung_clk_restore(cache->reg_base, cache->rdump, - cache->rd_num); -} - -static struct syscore_ops exynos5260_clk_syscore_ops = { - .suspend = exynos5260_clk_suspend, - .resume = exynos5260_clk_resume, -}; - -static void exynos5260_clk_sleep_init(void __iomem *reg_base, - unsigned long *rdump, - unsigned long nr_rdump) -{ - struct exynos5260_clock_reg_cache *reg_cache; - - reg_cache = kzalloc(sizeof(struct exynos5260_clock_reg_cache), - GFP_KERNEL); - if (!reg_cache) - panic("could not allocate register cache.\n"); - - reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); - - if (!reg_cache->rdump) - panic("could not allocate register dump storage.\n"); - - if (list_empty(&clock_reg_cache_list)) - register_syscore_ops(&exynos5260_clk_syscore_ops); - - reg_cache->rd_num = nr_rdump; - reg_cache->reg_base = reg_base; - list_add_tail(®_cache->node, &clock_reg_cache_list); -} - -#else -static void exynos5260_clk_sleep_init(void __iomem *reg_base, - unsigned long *rdump, - unsigned long nr_rdump){} -#endif - -/* - * Common function which registers plls, muxes, dividers and gates - * for each CMU. It also add CMU register list to register cache. - */ - -void __init exynos5260_cmu_register_one(struct device_node *np, - struct exynos5260_cmu_info *cmu) -{ - void __iomem *reg_base; - struct samsung_clk_provider *ctx; - - reg_base = of_iomap(np, 0); - if (!reg_base) - panic("%s: failed to map registers\n", __func__); - - ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); - if (!ctx) - panic("%s: unable to alllocate ctx\n", __func__); - - if (cmu->pll_clks) - samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, - reg_base); - if (cmu->mux_clks) - samsung_clk_register_mux(ctx, cmu->mux_clks, - cmu->nr_mux_clks); - if (cmu->div_clks) - samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); - if (cmu->gate_clks) - samsung_clk_register_gate(ctx, cmu->gate_clks, - cmu->nr_gate_clks); - if (cmu->fixed_clks) - samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, - cmu->nr_fixed_clks); - if (cmu->clk_regs) - exynos5260_clk_sleep_init(reg_base, cmu->clk_regs, - cmu->nr_clk_regs); - - samsung_clk_of_add_provider(np, ctx); -} - - /* CMU_AUD */ static unsigned long aud_clk_regs[] __initdata = { @@ -268,7 +135,7 @@ struct samsung_gate_clock aud_gate_clks[] __initdata = { static void __init exynos5260_clk_aud_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.mux_clks = aud_mux_clks; cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks); @@ -280,7 +147,7 @@ static void __init exynos5260_clk_aud_init(struct device_node *np) cmu.clk_regs = aud_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", @@ -458,7 +325,7 @@ struct samsung_gate_clock disp_gate_clks[] __initdata = { static void __init exynos5260_clk_disp_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.mux_clks = disp_mux_clks; cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks); @@ -470,7 +337,7 @@ static void __init exynos5260_clk_disp_init(struct device_node *np) cmu.clk_regs = disp_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", @@ -522,7 +389,7 @@ static struct samsung_pll_clock egl_pll_clks[] __initdata = { static void __init exynos5260_clk_egl_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.pll_clks = egl_pll_clks; cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks); @@ -534,7 +401,7 @@ static void __init exynos5260_clk_egl_init(struct device_node *np) cmu.clk_regs = egl_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", @@ -624,7 +491,7 @@ struct samsung_gate_clock fsys_gate_clks[] __initdata = { static void __init exynos5260_clk_fsys_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.mux_clks = fsys_mux_clks; cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks); @@ -634,7 +501,7 @@ static void __init exynos5260_clk_fsys_init(struct device_node *np) cmu.clk_regs = fsys_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", @@ -713,7 +580,7 @@ struct samsung_gate_clock g2d_gate_clks[] __initdata = { static void __init exynos5260_clk_g2d_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.mux_clks = g2d_mux_clks; cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks); @@ -725,7 +592,7 @@ static void __init exynos5260_clk_g2d_init(struct device_node *np) cmu.clk_regs = g2d_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", @@ -774,7 +641,7 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = { static void __init exynos5260_clk_g3d_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.pll_clks = g3d_pll_clks; cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks); @@ -788,7 +655,7 @@ static void __init exynos5260_clk_g3d_init(struct device_node *np) cmu.clk_regs = g3d_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", @@ -909,7 +776,7 @@ struct samsung_gate_clock gscl_gate_clks[] __initdata = { static void __init exynos5260_clk_gscl_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.mux_clks = gscl_mux_clks; cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks); @@ -921,7 +788,7 @@ static void __init exynos5260_clk_gscl_init(struct device_node *np) cmu.clk_regs = gscl_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", @@ -1028,7 +895,7 @@ struct samsung_gate_clock isp_gate_clks[] __initdata = { static void __init exynos5260_clk_isp_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.mux_clks = isp_mux_clks; cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks); @@ -1040,7 +907,7 @@ static void __init exynos5260_clk_isp_init(struct device_node *np) cmu.clk_regs = isp_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", @@ -1092,7 +959,7 @@ static struct samsung_pll_clock kfc_pll_clks[] __initdata = { static void __init exynos5260_clk_kfc_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.pll_clks = kfc_pll_clks; cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks); @@ -1104,7 +971,7 @@ static void __init exynos5260_clk_kfc_init(struct device_node *np) cmu.clk_regs = kfc_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", @@ -1148,7 +1015,7 @@ struct samsung_gate_clock mfc_gate_clks[] __initdata = { static void __init exynos5260_clk_mfc_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.mux_clks = mfc_mux_clks; cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks); @@ -1160,7 +1027,7 @@ static void __init exynos5260_clk_mfc_init(struct device_node *np) cmu.clk_regs = mfc_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", @@ -1295,7 +1162,7 @@ static struct samsung_pll_clock mif_pll_clks[] __initdata = { static void __init exynos5260_clk_mif_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.pll_clks = mif_pll_clks; cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks); @@ -1309,7 +1176,7 @@ static void __init exynos5260_clk_mif_init(struct device_node *np) cmu.clk_regs = mif_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", @@ -1503,7 +1370,7 @@ struct samsung_gate_clock peri_gate_clks[] __initdata = { static void __init exynos5260_clk_peri_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.mux_clks = peri_mux_clks; cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks); @@ -1515,7 +1382,7 @@ static void __init exynos5260_clk_peri_init(struct device_node *np) cmu.clk_regs = peri_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", @@ -1959,7 +1826,7 @@ static struct samsung_pll_clock top_pll_clks[] __initdata = { static void __init exynos5260_clk_top_init(struct device_node *np) { - struct exynos5260_cmu_info cmu = {0}; + struct samsung_cmu_info cmu = {0}; cmu.pll_clks = top_pll_clks; cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks); @@ -1975,7 +1842,7 @@ static void __init exynos5260_clk_top_init(struct device_node *np) cmu.clk_regs = top_clk_regs; cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs); - exynos5260_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &cmu); } CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top", diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index deab84d..a648236 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -14,6 +14,8 @@ #include #include "clk.h" +static LIST_HEAD(clock_reg_cache_list); + void samsung_clk_save(void __iomem *base, struct samsung_clk_reg_dump *rd, unsigned int num_regs) @@ -313,3 +315,96 @@ unsigned long _get_rate(const char *clk_name) return clk_get_rate(clk); } + +#ifdef CONFIG_PM_SLEEP +static int samsung_clk_suspend(void) +{ + struct samsung_clock_reg_cache *reg_cache; + + list_for_each_entry(reg_cache, &clock_reg_cache_list, node) + samsung_clk_save(reg_cache->reg_base, reg_cache->rdump, + reg_cache->rd_num); + return 0; +} + +static void samsung_clk_resume(void) +{ + struct samsung_clock_reg_cache *reg_cache; + + list_for_each_entry(reg_cache, &clock_reg_cache_list, node) + samsung_clk_restore(reg_cache->reg_base, reg_cache->rdump, + reg_cache->rd_num); +} + +static struct syscore_ops samsung_clk_syscore_ops = { + .suspend = samsung_clk_suspend, + .resume = samsung_clk_resume, +}; + +static void samsung_clk_sleep_init(void __iomem *reg_base, + const unsigned long *rdump, + unsigned long nr_rdump) +{ + struct samsung_clock_reg_cache *reg_cache; + + reg_cache = kzalloc(sizeof(struct samsung_clock_reg_cache), + GFP_KERNEL); + if (!reg_cache) + panic("could not allocate register reg_cache.\n"); + reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); + + if (!reg_cache->rdump) + panic("could not allocate register dump storage.\n"); + + if (list_empty(&clock_reg_cache_list)) + register_syscore_ops(&samsung_clk_syscore_ops); + + reg_cache->reg_base = reg_base; + reg_cache->rd_num = nr_rdump; + list_add_tail(®_cache->node, &clock_reg_cache_list); +} + +#else +static void samsung_clk_sleep_init(void __iomem *reg_base, + const unsigned long *rdump, + unsigned long nr_rdump) {} +#endif + +/* + * Common function which registers plls, muxes, dividers and gates + * for each CMU. It also add CMU register list to register cache. + */ +void __init samsung_cmu_register_one(struct device_node *np, + struct samsung_cmu_info *cmu) +{ + void __iomem *reg_base; + struct samsung_clk_provider *ctx; + + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + + ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); + if (!ctx) + panic("%s: unable to alllocate ctx\n", __func__); + + if (cmu->pll_clks) + samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, + reg_base); + if (cmu->mux_clks) + samsung_clk_register_mux(ctx, cmu->mux_clks, + cmu->nr_mux_clks); + if (cmu->div_clks) + samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); + if (cmu->gate_clks) + samsung_clk_register_gate(ctx, cmu->gate_clks, + cmu->nr_gate_clks); + if (cmu->fixed_clks) + samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, + cmu->nr_fixed_clks); + if (cmu->clk_regs) + samsung_clk_sleep_init(reg_base, cmu->clk_regs, + cmu->nr_clk_regs); + + samsung_clk_of_add_provider(np, ctx); +} diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 66ab36b..b3d0f4d 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -324,6 +324,37 @@ struct samsung_pll_clock { __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ _lock, _con, _rtable, _alias) +struct samsung_clock_reg_cache { + struct list_head node; + void __iomem *reg_base; + struct samsung_clk_reg_dump *rdump; + unsigned int rd_num; +}; + +struct samsung_cmu_info { + /* list of pll clocks and respective count */ + struct samsung_pll_clock *pll_clks; + unsigned int nr_pll_clks; + /* list of mux clocks and respective count */ + struct samsung_mux_clock *mux_clks; + unsigned int nr_mux_clks; + /* list of div clocks and respective count */ + struct samsung_div_clock *div_clks; + unsigned int nr_div_clks; + /* list of gate clocks and respective count */ + struct samsung_gate_clock *gate_clks; + unsigned int nr_gate_clks; + /* list of fixed clocks and respective count */ + struct samsung_fixed_rate_clock *fixed_clks; + unsigned int nr_fixed_clks; + /* total number of clocks with IDs assigned*/ + unsigned int nr_clk_ids; + + /* list and number of clocks registers */ + unsigned long *clk_regs; + unsigned int nr_clk_regs; +}; + extern struct samsung_clk_provider *__init samsung_clk_init( struct device_node *np, void __iomem *base, unsigned long nr_clks); @@ -362,6 +393,9 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, struct samsung_pll_clock *pll_list, unsigned int nr_clk, void __iomem *base); +extern void __init samsung_cmu_register_one(struct device_node *, + struct samsung_cmu_info *); + extern unsigned long _get_rate(const char *clk_name); extern void samsung_clk_save(void __iomem *base,