From patchwork Mon Dec 2 05:55:16 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rahul Sharma X-Patchwork-Id: 3263951 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id A81CC9F377 for ; Mon, 2 Dec 2013 05:56:59 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D62E8202A1 for ; Mon, 2 Dec 2013 05:56:57 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BB3BE20295 for ; Mon, 2 Dec 2013 05:56:55 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VnMUf-0006QY-SB; Mon, 02 Dec 2013 05:56:30 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VnMUd-0004wJ-F6; Mon, 02 Dec 2013 05:56:27 +0000 Received: from mailout4.samsung.com ([203.254.224.34]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VnMUX-0004vz-SG for linux-arm-kernel@lists.infradead.org; Mon, 02 Dec 2013 05:56:25 +0000 Received: from epcpsbgr1.samsung.com (u141.gpu120.samsung.co.kr [203.254.230.141]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MX600F3C0H7Z980@mailout4.samsung.com> for linux-arm-kernel@lists.infradead.org; Mon, 02 Dec 2013 14:55:55 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [172.20.52.124]) by epcpsbgr1.samsung.com (EPCPMTA) with SMTP id 7A.EF.21927.BE02C925; Mon, 02 Dec 2013 14:55:55 +0900 (KST) X-AuditID: cbfee68d-b7f1a6d0000055a7-76-529c20eb6d19 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 61.A7.32308.AE02C925; Mon, 02 Dec 2013 14:55:55 +0900 (KST) Received: from localhost.localdomain ([107.108.83.245]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MX600I8D0GZYAA0@mmp2.samsung.com>; Mon, 02 Dec 2013 14:55:54 +0900 (KST) From: Rahul Sharma To: linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH] clk: samsung: add support for multiple clock providers Date: Mon, 02 Dec 2013 11:25:16 +0530 Message-id: <1385963716-20045-1-git-send-email-rahul.sharma@samsung.com> X-Mailer: git-send-email 1.7.9.5 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrBLMWRmVeSWpSXmKPExsWyRsSkRve1wpwgg1NzBS2+7/rCbtG74Cqb xabH11gtZpzfx2TxdMJFNouFL+Itpiw6zGpxbMYSRotVu/4wOnB67Jx1l93jzrU9bB6bl9R7 9G1ZxejxeZNcAGsUl01Kak5mWWqRvl0CV8b7r/PZCqZcYayY0vGSuYHxx2bGLkZODgkBE4m7 fxewQthiEhfurWfrYuTiEBJYyijx5OInVpiiBcsvM0EkpjNKfNz6GKqqnUli4t0HzCBVbAK6 ErMPPgMbKyLgLTH5zF92kCJmge2MEjtWHwEq4uAQBkos+KUNUsMioCrR1n6WCcTmFfCQWLJk DwtIiYSAgsScSTYgrRICk9klmpZ/Z4OoF5D4NvkQVI2sxKYDzBDHSUocXHGDZQKj4AJGhlWM oqkFyQXFSelFhnrFibnFpXnpesn5uZsYgaF8+t+z3h2Mtw9YH2JMBho3kVlKNDkfGAt5JfGG xmZGFqYmpsZG5pZmpAkrifMmPUwKEhJITyxJzU5NLUgtii8qzUktPsTIxMEp1cDYkbklprdR uita10Fxm5SFsN7/5B9O2v55ZxyNul1aevRykmtXTe962fX3r0/z24IOMU2zJ7OFn+8Q8zqx P39lUd3FxdZastO8ZhR8nxzTUKk/WTZn6UyOhF9zU+aWiPW7vlhw5fHTc+dmbzGNPnFFhmOe Ugvf/O3rfm9arni3QGG1f5iaQYkSS3FGoqEWc1FxIgBQyv09ewIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrKIsWRmVeSWpSXmKPExsVy+t9jQd3XCnOCDFqOsVh83/WF3aJ3wVU2 i02Pr7FazDi/j8ni6YSLbBYLX8RbTFl0mNXi2IwljBardv1hdOD02DnrLrvHnWt72Dw2L6n3 6NuyitHj8ya5ANaoBkabjNTElNQihdS85PyUzLx0WyXv4HjneFMzA0NdQ0sLcyWFvMTcVFsl F58AXbfMHKB7lBTKEnNKgUIBicXFSvp2mCaEhrjpWsA0Ruj6hgTB9RgZoIGENYwZ77/OZyuY coWxYkrHS+YGxh+bGbsYOTkkBEwkFiy/zARhi0lcuLeerYuRi0NIYDqjxMetj6GcdiaJiXcf MINUsQnoSsw++AysW0TAW2Lymb/sIEXMAtsZJXasPgJUxMEhDJRY8EsbpIZFQFWirf0s2AZe AQ+JJUv2sICUSAgoSMyZZDOBkXsBI8MqRtHUguSC4qT0XEO94sTc4tK8dL3k/NxNjOBIeSa1 g3Flg8UhRgEORiUe3ovCc4KEWBPLiitzDzFKcDArifCy/J0dJMSbklhZlVqUH19UmpNafIgx GWj5RGYp0eR8YBTnlcQbGpuYmxqbWppYmJhZkiasJM57oNU6UEggPbEkNTs1tSC1CGYLEwen VAOj8hTFdmeX92s++u5b6bh2++aooJ9LvWpsE57YnTP0yVkxNWLWnd9zZjiExLzb8Wu9etGX nevMlYz1mqccr9o6T2KC4e6Y6MpV+ZmOOy4e9XH3XmfnHzc3+Z/Sqm1PjQ6nK6sxPk3dXe4w jY0xIjx9ohRTj+eEoFotroeNSusW1Wv7RRgl1J9QYinOSDTUYi4qTgQA9emWsNgCAAA= DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131202_005622_366849_B451B649 X-CRM114-Status: GOOD ( 13.26 ) X-Spam-Score: -6.9 (------) Cc: kgene.kim@samsung.com, mturquette@linaro.org, tomasz.figa@gmail.com, joshi@samsung.com, thomas.abraham@linaro.org, r.sh.open@gmail.com, Rahul Sharma X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 Samsung CCF helper functions doesn't provide support to register multiple Clock Providers for a given SoC. Due to this limitation soc platforms are not able to use these helpers for registering multiple clock providers and forced to bypass this layer. This layer is modified accordingly to enable the support. Clockfile for exynos4, exynos5250, exynos5420.c and exynos5440 are also modified as per changed helper functions. Signed-off-by: Rahul Sharma --- This patch is based on the following series from Tomasz Figa : http://www.spinics.net/lists/arm-kernel/msg280223.html It is rebased on clk-for-linus-3.13 branch in mike's tree. drivers/clk/samsung/clk-exynos4.c | 42 ++++----- drivers/clk/samsung/clk-exynos5250.c | 19 ++-- drivers/clk/samsung/clk-exynos5420.c | 17 ++-- drivers/clk/samsung/clk-exynos5440.c | 12 +-- drivers/clk/samsung/clk-pll.c | 14 +-- drivers/clk/samsung/clk-s3c64xx.c | 37 ++++---- drivers/clk/samsung/clk.c | 163 ++++++++++++++++++++++++---------- drivers/clk/samsung/clk.h | 26 +++--- 8 files changed, 205 insertions(+), 125 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index ca2a940..b226544 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1093,7 +1093,7 @@ static unsigned long exynos4_get_xom(void) return xom; } -static void __init exynos4_clk_register_finpll(void) +static void __init exynos4_clk_register_finpll(struct device_node *np) { struct samsung_fixed_rate_clock fclk; struct clk *clk; @@ -1116,7 +1116,7 @@ static void __init exynos4_clk_register_finpll(void) fclk.parent_name = NULL; fclk.flags = CLK_IS_ROOT; fclk.fixed_rate = finpll_f; - samsung_clk_register_fixed_rate(&fclk, 1); + samsung_clk_register_fixed_rate(np, &fclk, 1); } @@ -1234,14 +1234,14 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_init(np, reg_base, nr_clks); - samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, + samsung_clk_of_register_fixed_ext(np, exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), ext_clk_match); - exynos4_clk_register_finpll(); + exynos4_clk_register_finpll(np); if (exynos4_soc == EXYNOS4210) { - samsung_clk_register_mux(exynos4210_mux_early, + samsung_clk_register_mux(np, exynos4210_mux_early, ARRAY_SIZE(exynos4210_mux_early)); if (_get_rate("fin_pll") == 24000000) { @@ -1255,7 +1255,7 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4210_plls[vpll].rate_table = exynos4210_vpll_rates; - samsung_clk_register_pll(exynos4210_plls, + samsung_clk_register_pll(np, exynos4210_plls, ARRAY_SIZE(exynos4210_plls), reg_base); } else { if (_get_rate("fin_pll") == 24000000) { @@ -1267,42 +1267,42 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4x12_vpll_rates; } - samsung_clk_register_pll(exynos4x12_plls, + samsung_clk_register_pll(np, exynos4x12_plls, ARRAY_SIZE(exynos4x12_plls), reg_base); } - samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks, + samsung_clk_register_fixed_rate(np, exynos4_fixed_rate_clks, ARRAY_SIZE(exynos4_fixed_rate_clks)); - samsung_clk_register_mux(exynos4_mux_clks, + samsung_clk_register_mux(np, exynos4_mux_clks, ARRAY_SIZE(exynos4_mux_clks)); - samsung_clk_register_div(exynos4_div_clks, + samsung_clk_register_div(np, exynos4_div_clks, ARRAY_SIZE(exynos4_div_clks)); - samsung_clk_register_gate(exynos4_gate_clks, + samsung_clk_register_gate(np, exynos4_gate_clks, ARRAY_SIZE(exynos4_gate_clks)); if (exynos4_soc == EXYNOS4210) { - samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks, + samsung_clk_register_fixed_rate(np, exynos4210_fixed_rate_clks, ARRAY_SIZE(exynos4210_fixed_rate_clks)); - samsung_clk_register_mux(exynos4210_mux_clks, + samsung_clk_register_mux(np, exynos4210_mux_clks, ARRAY_SIZE(exynos4210_mux_clks)); - samsung_clk_register_div(exynos4210_div_clks, + samsung_clk_register_div(np, exynos4210_div_clks, ARRAY_SIZE(exynos4210_div_clks)); - samsung_clk_register_gate(exynos4210_gate_clks, + samsung_clk_register_gate(np, exynos4210_gate_clks, ARRAY_SIZE(exynos4210_gate_clks)); - samsung_clk_register_alias(exynos4210_aliases, + samsung_clk_register_alias(np, exynos4210_aliases, ARRAY_SIZE(exynos4210_aliases)); } else { - samsung_clk_register_mux(exynos4x12_mux_clks, + samsung_clk_register_mux(np, exynos4x12_mux_clks, ARRAY_SIZE(exynos4x12_mux_clks)); - samsung_clk_register_div(exynos4x12_div_clks, + samsung_clk_register_div(np, exynos4x12_div_clks, ARRAY_SIZE(exynos4x12_div_clks)); - samsung_clk_register_gate(exynos4x12_gate_clks, + samsung_clk_register_gate(np, exynos4x12_gate_clks, ARRAY_SIZE(exynos4x12_gate_clks)); - samsung_clk_register_alias(exynos4x12_aliases, + samsung_clk_register_alias(np, exynos4x12_aliases, ARRAY_SIZE(exynos4x12_aliases)); } - samsung_clk_register_alias(exynos4_aliases, + samsung_clk_register_alias(np, exynos4_aliases, ARRAY_SIZE(exynos4_aliases)); exynos4_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 82f14e1..1785a3d 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -592,10 +592,10 @@ static void __init exynos5250_clk_init(struct device_node *np) } samsung_clk_init(np, reg_base, nr_clks); - samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, + samsung_clk_of_register_fixed_ext(np, exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); - samsung_clk_register_mux(exynos5250_pll_pmux_clks, + samsung_clk_register_mux(np, exynos5250_pll_pmux_clks, ARRAY_SIZE(exynos5250_pll_pmux_clks)); if (_get_rate("fin_pll") == 24 * MHZ) @@ -604,17 +604,18 @@ static void __init exynos5250_clk_init(struct device_node *np) if (_get_rate("mout_vpllsrc") == 24 * MHZ) exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl; - samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), - reg_base); - samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, + samsung_clk_register_pll(np, exynos5250_plls, + ARRAY_SIZE(exynos5250_plls), + reg_base); + samsung_clk_register_fixed_rate(np, exynos5250_fixed_rate_clks, ARRAY_SIZE(exynos5250_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks, + samsung_clk_register_fixed_factor(np, exynos5250_fixed_factor_clks, ARRAY_SIZE(exynos5250_fixed_factor_clks)); - samsung_clk_register_mux(exynos5250_mux_clks, + samsung_clk_register_mux(np, exynos5250_mux_clks, ARRAY_SIZE(exynos5250_mux_clks)); - samsung_clk_register_div(exynos5250_div_clks, + samsung_clk_register_div(np, exynos5250_div_clks, ARRAY_SIZE(exynos5250_div_clks)); - samsung_clk_register_gate(exynos5250_gate_clks, + samsung_clk_register_gate(np, exynos5250_gate_clks, ARRAY_SIZE(exynos5250_gate_clks)); exynos5250_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 9de5bfd..44327e3 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -817,20 +817,21 @@ static void __init exynos5420_clk_init(struct device_node *np) } samsung_clk_init(np, reg_base, nr_clks); - samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, + samsung_clk_of_register_fixed_ext(np, exynos5420_fixed_rate_ext_clks, ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), ext_clk_match); - samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls), - reg_base); - samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks, + samsung_clk_register_pll(np, exynos5420_plls, + ARRAY_SIZE(exynos5420_plls), + reg_base); + samsung_clk_register_fixed_rate(np, exynos5420_fixed_rate_clks, ARRAY_SIZE(exynos5420_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks, + samsung_clk_register_fixed_factor(np, exynos5420_fixed_factor_clks, ARRAY_SIZE(exynos5420_fixed_factor_clks)); - samsung_clk_register_mux(exynos5420_mux_clks, + samsung_clk_register_mux(np, exynos5420_mux_clks, ARRAY_SIZE(exynos5420_mux_clks)); - samsung_clk_register_div(exynos5420_div_clks, + samsung_clk_register_div(np, exynos5420_div_clks, ARRAY_SIZE(exynos5420_div_clks)); - samsung_clk_register_gate(exynos5420_gate_clks, + samsung_clk_register_gate(np, exynos5420_gate_clks, ARRAY_SIZE(exynos5420_gate_clks)); exynos5420_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index e3e460a..ef90bb7 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -115,21 +115,21 @@ static void __init exynos5440_clk_init(struct device_node *np) } samsung_clk_init(np, reg_base, nr_clks); - samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, + samsung_clk_of_register_fixed_ext(np, exynos5440_fixed_rate_ext_clks, ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10); samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10); - samsung_clk_register_fixed_rate(exynos5440_fixed_rate_clks, + samsung_clk_register_fixed_rate(np, exynos5440_fixed_rate_clks, ARRAY_SIZE(exynos5440_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks, + samsung_clk_register_fixed_factor(np, exynos5440_fixed_factor_clks, ARRAY_SIZE(exynos5440_fixed_factor_clks)); - samsung_clk_register_mux(exynos5440_mux_clks, + samsung_clk_register_mux(np, exynos5440_mux_clks, ARRAY_SIZE(exynos5440_mux_clks)); - samsung_clk_register_div(exynos5440_div_clks, + samsung_clk_register_div(np, exynos5440_div_clks, ARRAY_SIZE(exynos5440_div_clks)); - samsung_clk_register_gate(exynos5440_gate_clks, + samsung_clk_register_gate(np, exynos5440_gate_clks, ARRAY_SIZE(exynos5440_gate_clks)); pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 529e11d..5b4228e 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -710,8 +710,9 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name, return clk; } -static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, - void __iomem *base) +static void __init _samsung_clk_register_pll(struct device_node *np, + struct samsung_pll_clock *pll_clk, + void __iomem *base) { struct samsung_clk_pll *pll; struct clk *clk; @@ -804,7 +805,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, return; } - samsung_clk_add_lookup(clk, pll_clk->id); + samsung_clk_add_lookup(np, clk, pll_clk->id); if (!pll_clk->alias) return; @@ -815,11 +816,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, __func__, pll_clk->name, ret); } -void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, - unsigned int nr_pll, void __iomem *base) +void __init samsung_clk_register_pll(struct device_node *np, + struct samsung_pll_clock *pll_list, + unsigned int nr_pll, void __iomem *base) { int cnt; for (cnt = 0; cnt < nr_pll; cnt++) - _samsung_clk_register_pll(&pll_list[cnt], base); + _samsung_clk_register_pll(np, &pll_list[cnt], base); } diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index a43cbde..b12050f 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -442,12 +442,13 @@ static struct samsung_clock_alias s3c6410_clock_aliases[] = { ALIAS(MEM0_SROM, NULL, "srom"), }; -static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, - unsigned long xusbxti_f) +static void __init s3c64xx_clk_register_fixed_ext(struct device_node *np, + unsigned long fin_pll_f, + unsigned long xusbxti_f) { s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f; s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f; - samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks, + samsung_clk_register_fixed_rate(np, s3c64xx_fixed_rate_ext_clks, ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); } @@ -469,44 +470,44 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, /* Register external clocks. */ if (!np) - s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f); + s3c64xx_clk_register_fixed_ext(np, xtal_f, xusbxti_f); /* Register PLLs. */ - samsung_clk_register_pll(s3c64xx_pll_clks, + samsung_clk_register_pll(np, s3c64xx_pll_clks, ARRAY_SIZE(s3c64xx_pll_clks), reg_base); /* Register common internal clocks. */ - samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks, + samsung_clk_register_fixed_rate(np, s3c64xx_fixed_rate_clks, ARRAY_SIZE(s3c64xx_fixed_rate_clks)); - samsung_clk_register_mux(s3c64xx_mux_clks, + samsung_clk_register_mux(np, s3c64xx_mux_clks, ARRAY_SIZE(s3c64xx_mux_clks)); - samsung_clk_register_div(s3c64xx_div_clks, + samsung_clk_register_div(np, s3c64xx_div_clks, ARRAY_SIZE(s3c64xx_div_clks)); - samsung_clk_register_gate(s3c64xx_gate_clks, + samsung_clk_register_gate(np, s3c64xx_gate_clks, ARRAY_SIZE(s3c64xx_gate_clks)); /* Register SoC-specific clocks. */ if (is_s3c6400) { - samsung_clk_register_mux(s3c6400_mux_clks, + samsung_clk_register_mux(np, s3c6400_mux_clks, ARRAY_SIZE(s3c6400_mux_clks)); - samsung_clk_register_div(s3c6400_div_clks, + samsung_clk_register_div(np, s3c6400_div_clks, ARRAY_SIZE(s3c6400_div_clks)); - samsung_clk_register_gate(s3c6400_gate_clks, + samsung_clk_register_gate(np, s3c6400_gate_clks, ARRAY_SIZE(s3c6400_gate_clks)); - samsung_clk_register_alias(s3c6400_clock_aliases, + samsung_clk_register_alias(np, s3c6400_clock_aliases, ARRAY_SIZE(s3c6400_clock_aliases)); } else { - samsung_clk_register_mux(s3c6410_mux_clks, + samsung_clk_register_mux(np, s3c6410_mux_clks, ARRAY_SIZE(s3c6410_mux_clks)); - samsung_clk_register_div(s3c6410_div_clks, + samsung_clk_register_div(np, s3c6410_div_clks, ARRAY_SIZE(s3c6410_div_clks)); - samsung_clk_register_gate(s3c6410_gate_clks, + samsung_clk_register_gate(np, s3c6410_gate_clks, ARRAY_SIZE(s3c6410_gate_clks)); - samsung_clk_register_alias(s3c6410_clock_aliases, + samsung_clk_register_alias(np, s3c6410_clock_aliases, ARRAY_SIZE(s3c6410_clock_aliases)); } - samsung_clk_register_alias(s3c64xx_clock_aliases, + samsung_clk_register_alias(np, s3c64xx_clock_aliases, ARRAY_SIZE(s3c64xx_clock_aliases)); s3c64xx_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 91bec3e..a6fad4f 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -15,11 +15,15 @@ #include "clk.h" static DEFINE_SPINLOCK(lock); -static struct clk **clk_table; -static void __iomem *reg_base; -#ifdef CONFIG_OF -static struct clk_onecell_data clk_data; -#endif +static LIST_HEAD(clk_provider_list); + +/* Context node which holds information about the clock provider. */ +struct clk_provider_context { + struct list_head node; + struct device_node *of_node; + void __iomem *reg_base; + struct clk_onecell_data clk_data; +}; void samsung_clk_save(void __iomem *base, struct samsung_clk_reg_dump *rd, @@ -58,37 +62,77 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( void __init samsung_clk_init(struct device_node *np, void __iomem *base, unsigned long nr_clks) { - reg_base = base; + struct clk_provider_context *ctx; + struct clk **clk_table; + int ret; + + if (!np) + return; + + ctx = kzalloc(sizeof(struct clk_provider_context), GFP_KERNEL); + if (!ctx) + panic("could not allocate clock provider context.\n"); clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); if (!clk_table) panic("could not allocate clock lookup table\n"); - if (!np) - return; + ctx->of_node = np; + ctx->reg_base = base; + ctx->clk_data.clks = clk_table; + ctx->clk_data.clk_num = nr_clks; -#ifdef CONFIG_OF - clk_data.clks = clk_table; - clk_data.clk_num = nr_clks; - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); -#endif + ret = of_clk_add_provider(np, of_clk_src_onecell_get, + &ctx->clk_data); + if (ret) + panic("could not register clock provide\n"); + + list_add_tail(&ctx->node, &clk_provider_list); +} + +/* static helper function to extract the context from node pointer */ +static struct clk_provider_context *_get_clock_provider(struct device_node *np) +{ + struct clk_provider_context *ctx; + + list_for_each_entry(ctx, &clk_provider_list, node) + if (ctx->of_node == np) + return ctx; + return NULL; } /* add a clock instance to the clock lookup table used for dt based lookup */ -void samsung_clk_add_lookup(struct clk *clk, unsigned int id) +void samsung_clk_add_lookup(struct device_node *np, struct clk *clk, + unsigned int id) { - if (clk_table && id) - clk_table[id] = clk; + struct clk_provider_context *ctx; + + ctx = _get_clock_provider(np); + if (!ctx) { + pr_err("invalid node pointer.\n"); + return; + } + + if (ctx->clk_data.clks && id) + ctx->clk_data.clks[id] = clk; } /* register a list of aliases */ -void __init samsung_clk_register_alias(struct samsung_clock_alias *list, - unsigned int nr_clk) +void __init samsung_clk_register_alias(struct device_node *np, + struct samsung_clock_alias *list, + unsigned int nr_clk) { + struct clk_provider_context *ctx; struct clk *clk; unsigned int idx, ret; - if (!clk_table) { + ctx = _get_clock_provider(np); + if (!ctx) { + pr_err("invalid node pointer.\n"); + return; + } + + if (!ctx->clk_data.clks) { pr_err("%s: clock table missing\n", __func__); return; } @@ -100,7 +144,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list, continue; } - clk = clk_table[list->id]; + clk = ctx->clk_data.clks[list->id]; if (!clk) { pr_err("%s: failed to find clock %d\n", __func__, list->id); @@ -115,7 +159,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list, } /* register a list of fixed clocks */ -void __init samsung_clk_register_fixed_rate( +void __init samsung_clk_register_fixed_rate(struct device_node *np, struct samsung_fixed_rate_clock *list, unsigned int nr_clk) { struct clk *clk; @@ -130,7 +174,7 @@ void __init samsung_clk_register_fixed_rate( continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(np, clk, list->id); /* * Unconditionally add a clock lookup for the fixed rate clocks. @@ -144,7 +188,7 @@ void __init samsung_clk_register_fixed_rate( } /* register a list of fixed factor clocks */ -void __init samsung_clk_register_fixed_factor( +void __init samsung_clk_register_fixed_factor(struct device_node *np, struct samsung_fixed_factor_clock *list, unsigned int nr_clk) { struct clk *clk; @@ -159,20 +203,29 @@ void __init samsung_clk_register_fixed_factor( continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(np, clk, list->id); } } /* register a list of mux clocks */ -void __init samsung_clk_register_mux(struct samsung_mux_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_mux(struct device_node *np, + struct samsung_mux_clock *list, + unsigned int nr_clk) { + struct clk_provider_context *ctx; struct clk *clk; unsigned int idx, ret; + ctx = _get_clock_provider(np); + if (!ctx) { + pr_err("invalid node pointer.\n"); + return; + } + for (idx = 0; idx < nr_clk; idx++, list++) { clk = clk_register_mux(NULL, list->name, list->parent_names, - list->num_parents, list->flags, reg_base + list->offset, + list->num_parents, list->flags, + ctx->reg_base + list->offset, list->shift, list->width, list->mux_flags, &lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, @@ -180,7 +233,7 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list, continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(np, clk, list->id); /* register a clock lookup only if a clock alias is specified */ if (list->alias) { @@ -194,31 +247,39 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list, } /* register a list of div clocks */ -void __init samsung_clk_register_div(struct samsung_div_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_div(struct device_node *np, + struct samsung_div_clock *list, + unsigned int nr_clk) { + struct clk_provider_context *ctx; struct clk *clk; unsigned int idx, ret; + ctx = _get_clock_provider(np); + if (!ctx) { + pr_err("invalid node pointer.\n"); + return; + } + for (idx = 0; idx < nr_clk; idx++, list++) { if (list->table) clk = clk_register_divider_table(NULL, list->name, - list->parent_name, list->flags, - reg_base + list->offset, list->shift, - list->width, list->div_flags, - list->table, &lock); + list->parent_name, list->flags, + ctx->reg_base + list->offset, + list->shift, list->width, list->div_flags, + list->table, &lock); else clk = clk_register_divider(NULL, list->name, - list->parent_name, list->flags, - reg_base + list->offset, list->shift, - list->width, list->div_flags, &lock); + list->parent_name, list->flags, + ctx->reg_base + list->offset, list->shift, + list->width, list->div_flags, &lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(np, clk, list->id); /* register a clock lookup only if a clock alias is specified */ if (list->alias) { @@ -232,15 +293,23 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list, } /* register a list of gate clocks */ -void __init samsung_clk_register_gate(struct samsung_gate_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_gate(struct device_node *np, + struct samsung_gate_clock *list, + unsigned int nr_clk) { + struct clk_provider_context *ctx; struct clk *clk; unsigned int idx, ret; + ctx = _get_clock_provider(np); + if (!ctx) { + pr_err("invalid node pointer.\n"); + return; + } + for (idx = 0; idx < nr_clk; idx++, list++) { clk = clk_register_gate(NULL, list->name, list->parent_name, - list->flags, reg_base + list->offset, + list->flags, ctx->reg_base + list->offset, list->bit_idx, list->gate_flags, &lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, @@ -257,7 +326,7 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list, __func__, list->alias); } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(np, clk, list->id); } } @@ -266,21 +335,21 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list, * tree and register it */ #ifdef CONFIG_OF -void __init samsung_clk_of_register_fixed_ext( +void __init samsung_clk_of_register_fixed_ext(struct device_node *np, struct samsung_fixed_rate_clock *fixed_rate_clk, unsigned int nr_fixed_rate_clk, struct of_device_id *clk_matches) { const struct of_device_id *match; - struct device_node *np; + struct device_node *clk_np; u32 freq; - for_each_matching_node_and_match(np, clk_matches, &match) { - if (of_property_read_u32(np, "clock-frequency", &freq)) + for_each_matching_node_and_match(clk_np, clk_matches, &match) { + if (of_property_read_u32(clk_np, "clock-frequency", &freq)) continue; fixed_rate_clk[(u32)match->data].fixed_rate = freq; } - samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk); + samsung_clk_register_fixed_rate(np, fixed_rate_clk, nr_fixed_rate_clk); } #endif diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index c7141ba..620f7b8 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -315,26 +315,32 @@ struct samsung_pll_clock { extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, unsigned long nr_clks); extern void __init samsung_clk_of_register_fixed_ext( + struct device_node *np, struct samsung_fixed_rate_clock *fixed_rate_clk, unsigned int nr_fixed_rate_clk, struct of_device_id *clk_matches); -extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id); +extern void samsung_clk_add_lookup(struct device_node *np, + struct clk *clk, unsigned int id); -extern void samsung_clk_register_alias(struct samsung_clock_alias *list, - unsigned int nr_clk); -extern void __init samsung_clk_register_fixed_rate( +extern void samsung_clk_register_alias(struct device_node *np, + struct samsung_clock_alias *list, + unsigned int nr_clk); +extern void __init samsung_clk_register_fixed_rate(struct device_node *np, struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk); -extern void __init samsung_clk_register_fixed_factor( +extern void __init samsung_clk_register_fixed_factor(struct device_node *np, struct samsung_fixed_factor_clock *list, unsigned int nr_clk); -extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list, +extern void __init samsung_clk_register_mux(struct device_node *np, + struct samsung_mux_clock *clk_list, unsigned int nr_clk); -extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list, +extern void __init samsung_clk_register_div(struct device_node *np, + struct samsung_div_clock *clk_list, unsigned int nr_clk); -extern void __init samsung_clk_register_gate( +extern void __init samsung_clk_register_gate(struct device_node *np, struct samsung_gate_clock *clk_list, unsigned int nr_clk); -extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, - unsigned int nr_clk, void __iomem *base); +extern void __init samsung_clk_register_pll(struct device_node *np, + struct samsung_pll_clock *pll_list, + unsigned int nr_clk, void __iomem *base); extern unsigned long _get_rate(const char *clk_name);