From patchwork Tue Mar 6 14:33:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 10261809 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 B6BA4602C8 for ; Tue, 6 Mar 2018 14:33:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A65A928EF6 for ; Tue, 6 Mar 2018 14:33:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9AD8128EFA; Tue, 6 Mar 2018 14:33:33 +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.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable 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 0E18628EF6 for ; Tue, 6 Mar 2018 14:33:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753799AbeCFOdc (ORCPT ); Tue, 6 Mar 2018 09:33:32 -0500 Received: from mailout1.w1.samsung.com ([210.118.77.11]:46323 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753715AbeCFOd1 (ORCPT ); Tue, 6 Mar 2018 09:33:27 -0500 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20180306143325euoutp0114f2de2d3d21854c46193db96771ff2e~ZW11EHU9u0513005130euoutp01m; Tue, 6 Mar 2018 14:33:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20180306143325euoutp0114f2de2d3d21854c46193db96771ff2e~ZW11EHU9u0513005130euoutp01m DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1520346805; bh=Z88dYuDha2anhj7Ft3g18Mk+7ZL0LlycrcTx6wTx/H8=; h=From:To:Cc:Subject:Date:In-reply-to:References:From; b=mBJLeSg9NhRJCXA/OEoKfu5ROOUnB0Rxr8pR4i6F8RHH8FR3+kner9HUwoGl6zx40 n6Og9PPL6l8qAf+oHy2quhHnqYgMuP53LLoPjiYt7NYqjhvgo6oDqu+Fv18Q6dcg5Q 0sacd99FiErNeGcbdrJLcGnVjI32P9COkdQv/icA= Received: from eusmges3new.samsung.com (unknown [203.254.199.245]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20180306143324eucas1p1eedf5436d332a0457a7c65068ba3eb98~ZW10WZGg_3060730607eucas1p1B; Tue, 6 Mar 2018 14:33:24 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges3new.samsung.com (EUCPMTA) with SMTP id F7.0E.10409.4B6AE9A5; Tue, 6 Mar 2018 14:33:24 +0000 (GMT) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20180306143323eucas1p1398ec0ae5a45235ddadb9398437c5250~ZW1zgaMom3061130611eucas1p12; Tue, 6 Mar 2018 14:33:23 +0000 (GMT) X-AuditID: cbfec7f5-b45ff700000028a9-b5-5a9ea6b44e93 Received: from eusync1.samsung.com ( [203.254.199.211]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id 22.0F.04178.3B6AE9A5; Tue, 6 Mar 2018 14:33:23 +0000 (GMT) Received: from AMDC2765.digital.local ([106.116.147.25]) by eusync1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0P5600MGHB3ETD00@eusync1.samsung.com>; Tue, 06 Mar 2018 14:33:23 +0000 (GMT) From: Marek Szyprowski To: linux-clk@vger.kernel.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Sylwester Nawrocki , Chanwoo Choi , Inki Dae , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Subject: [PATCH v3 2/6] clk: samsung: Add Exynos5 sub-CMU clock driver Date: Tue, 06 Mar 2018 15:33:08 +0100 Message-id: <20180306143312.21035-3-m.szyprowski@samsung.com> X-Mailer: git-send-email 2.15.0 In-reply-to: <20180306143312.21035-1-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrAIsWRmVeSWpSXmKPExsWy7djP87pbls2LMlgyR8hi44z1rBbXvzxn tZh0fwKLxfnzG9gtPvbcY7WYcX4fk8XaI3fZLQ6/aWd14PDYtKqTzaNvyypGj8+b5AKYo7hs UlJzMstSi/TtErgyPl/Zwliwwrri8N6KBsaDhl2MnBwSAiYSW/6/Yeli5OIQEljBKNF8dj8b hPOZUeLXzOmsMFVP581mhEgsY5R433CfGSQhJNDAJDHjaTyIzSZgKNH1tosNxBYRcJD4/Ok1 WAOzQBuTxNkD+5lAEsICbhIrzl0DK2IRUJU4tLEbbBCvgK3EzaNtLBDb5CUWf98JVsMpYCdx 59JMsPskBH6ySix88JAdoshFYtHshVC2sMSr41ugbBmJzo6DTBB2vUTf9yNMEM09jBJ7W6ZC JawlDh+/CPYbswCfxKRt04Gu4ACK80p0tAlBlHhIPFt9AarcUeLRhY3sEO9PZJSY0nuRbQKj 1AJGhlWM4qmlxbnpqcXGeanlesWJucWleel6yfm5mxiB8Xj63/GvOxj3/Uk6xCjAwajEw7vB Y26UEGtiWXFl7iFGCQ5mJRHeCP15UUK8KYmVValF+fFFpTmpxYcYpTlYlMR54zTqooQE0hNL UrNTUwtSi2CyTBycUg2MEb90hKez3nl/ZdWcI6uyND6ZW8zb5n928d4lAoLfKySln1quPvub x3mf0DWHFwqyUwTDJPUbo7++YFKUkG1MXvfuQdtqw/cPOZ6n7RFt5X2u+4Lln1mBiJlYwunu lZ8nRrtcrnHdl+7S+ODa77kP+3fMmJq2dmHS26MKe1fpvp6oUhw1KZOvR4mlOCPRUIu5qDgR AMyU7VTDAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpiluLIzCtJLcpLzFFi42I5/e/4Zd3Ny+ZFGbRuU7PYOGM9q8X1L89Z LSbdn8Bicf78BnaLjz33WC1mnN/HZLH2yF12i8Nv2lkdODw2repk8+jbsorR4/MmuQDmKC6b lNSczLLUIn27BK6Mz1e2MBassK44vLeigfGgYRcjJ4eEgInE03mzGbsYuTiEBJYwSmy/epQN wmlikpjUcYsRpIpNwFCi620XG4gtIuAg8fnTa7AOZoEOJok9ex+CJYQF3CRWnLsGZrMIqEoc 2tjNDGLzCthK3DzaxgKxTl5i8fedYDWcAnYSdy7NBIsLAdVcnvCdcQIjzwJGhlWMIqmlxbnp ucWGesWJucWleel6yfm5mxiBIbPt2M/NOxgvbQw+xCjAwajEw7vBY26UEGtiWXFl7iFGCQ5m JRHeCP15UUK8KYmVValF+fFFpTmpxYcYpTlYlMR5zxtURgkJpCeWpGanphakFsFkmTg4pRoY yznE1LduMtdc1rOmm/mKzcWSCrngW2xzqk8/N1xrlHfI61d3RvaGCQd93FPPnPjyM0+n+k3g hjiVyVGxf2WK18roxxotnPLvtbk8o/33wn27P6eK67WWf/yQqbto2tNXPjxxZiIiNznOttnJ L7vHZ7taOaJhM6N59NWdJs5PPcX2uex6ovtBiaU4I9FQi7moOBEAAGGV6xUCAAA= X-CMS-MailID: 20180306143323eucas1p1398ec0ae5a45235ddadb9398437c5250 X-Msg-Generator: CA CMS-TYPE: 201P X-CMS-RootMailID: 20180306143323eucas1p1398ec0ae5a45235ddadb9398437c5250 X-RootMTR: 20180306143323eucas1p1398ec0ae5a45235ddadb9398437c5250 References: <20180306143312.21035-1-m.szyprowski@samsung.com> 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 Exynos5250/5420/5800 have only one clock constroller, but some of their clock depends on respective power domains. Handling integration of clock controller and power domain can be done using runtime PM feature of CCF framework. This however needs a separate struct device for each power domain. This patch adds such separate driver for a group of such clocks, which can be instantiated more than once, each time for a different power domain. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-exynos5-subcmu.c | 186 +++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-exynos5-subcmu.h | 26 +++++ 2 files changed, 212 insertions(+) create mode 100644 drivers/clk/samsung/clk-exynos5-subcmu.c create mode 100644 drivers/clk/samsung/clk-exynos5-subcmu.h diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c new file mode 100644 index 000000000000..ac3983c8adf2 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5-subcmu.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 Samsung Electronics Co., Ltd. +// Author: Marek Szyprowski +// Common Clock Framework support for Exynos5 power-domain dependent clocks + +#include +#include +#include +#include + +#include "clk.h" +#include "clk-exynos5-subcmu.h" + +static struct samsung_clk_provider *ctx; +static const struct exynos5_subcmu_info *cmu; +static int nr_cmus; + +static void exynos5_subcmu_clk_save(void __iomem *base, + struct exynos5_subcmu_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) { + rd->save = readl(base + rd->offset); + writel((rd->save & ~rd->mask) | rd->value, base + rd->offset); + rd->save &= rd->mask; + } +}; + +static void exynos5_subcmu_clk_restore(void __iomem *base, + struct exynos5_subcmu_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) + writel((readl(base + rd->offset) & ~rd->mask) | rd->save, + base + rd->offset); +} + +static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx, + const struct samsung_gate_clock *list, int nr_clk) +{ + while (nr_clk--) + samsung_clk_add_lookup(ctx, ERR_PTR(-EPROBE_DEFER), list++->id); +} + +/* + * Pass the needed clock provider context and register sub-CMU clocks + * + * NOTE: This function has to be called from the main, OF_CLK_DECLARE- + * initialized clock provider driver. This happens very early during boot + * process. Then this driver, during core_initcall registers two platform + * drivers: one which binds to the same device-tree node as OF_CLK_DECLARE + * driver and second, for handling its per-domain child-devices. Those + * platform drivers are bound to their devices a bit later in arch_initcall, + * when OF-core populates all device-tree nodes. + */ +void exynos5_subcmus_init(struct samsung_clk_provider *_ctx, int _nr_cmus, + const struct exynos5_subcmu_info *_cmu) +{ + ctx = _ctx; + cmu = _cmu; + nr_cmus = _nr_cmus; + + for (; _nr_cmus--; _cmu++) { + exynos5_subcmu_defer_gate(ctx, _cmu->gate_clks, + _cmu->nr_gate_clks); + exynos5_subcmu_clk_save(ctx->reg_base, _cmu->suspend_regs, + _cmu->nr_suspend_regs); + } +} + +static int __maybe_unused exynos5_subcmu_suspend(struct device *dev) +{ + struct exynos5_subcmu_info *info = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&ctx->lock, flags); + exynos5_subcmu_clk_save(ctx->reg_base, info->suspend_regs, + info->nr_suspend_regs); + spin_unlock_irqrestore(&ctx->lock, flags); + + return 0; +} + +static int __maybe_unused exynos5_subcmu_resume(struct device *dev) +{ + struct exynos5_subcmu_info *info = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&ctx->lock, flags); + exynos5_subcmu_clk_restore(ctx->reg_base, info->suspend_regs, + info->nr_suspend_regs); + spin_unlock_irqrestore(&ctx->lock, flags); + + return 0; +} + +static int __init exynos5_subcmu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct exynos5_subcmu_info *info = dev_get_drvdata(dev); + + pm_runtime_set_suspended(dev); + pm_runtime_enable(dev); + pm_runtime_get(dev); + + ctx->dev = dev; + samsung_clk_register_div(ctx, info->div_clks, info->nr_div_clks); + samsung_clk_register_gate(ctx, info->gate_clks, info->nr_gate_clks); + ctx->dev = NULL; + + pm_runtime_put_sync(dev); + + return 0; +} + +static const struct dev_pm_ops exynos5_subcmu_pm_ops = { + SET_RUNTIME_PM_OPS(exynos5_subcmu_suspend, + exynos5_subcmu_resume, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver exynos5_subcmu_driver __refdata = { + .driver = { + .name = "exynos5-subcmu", + .suppress_bind_attrs = true, + .pm = &exynos5_subcmu_pm_ops, + }, + .probe = exynos5_subcmu_probe, +}; + +static int __init exynos5_clk_register_subcmu(struct device *parent, + const struct exynos5_subcmu_info *info, + struct device_node *pd_node) +{ + struct of_phandle_args genpdspec = { .np = pd_node }; + struct platform_device *pdev; + + pdev = platform_device_alloc(info->pd_name, -1); + pdev->dev.parent = parent; + pdev->driver_override = "exynos5-subcmu"; + platform_set_drvdata(pdev, (void *)info); + of_genpd_add_device(&genpdspec, &pdev->dev); + platform_device_add(pdev); + + return 0; +} + +static int __init exynos5_clk_probe(struct platform_device *pdev) +{ + struct device_node *np; + const char *name; + int i; + + for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") { + if (of_property_read_string(np, "label", &name) < 0) + continue; + for (i = 0; i < nr_cmus; i++) + if (strcmp(cmu[i].pd_name, name) == 0) + exynos5_clk_register_subcmu(&pdev->dev, + &cmu[i], np); + } + return 0; +} + +static const struct of_device_id exynos5_clk_of_match[] = { + { }, +}; + +static struct platform_driver exynos5_clk_driver __refdata = { + .driver = { + .name = "exynos5-clock", + .of_match_table = exynos5_clk_of_match, + .suppress_bind_attrs = true, + }, + .probe = exynos5_clk_probe, +}; + +static int __init exynos5_clk_drv_init(void) +{ + platform_driver_register(&exynos5_clk_driver); + platform_driver_register(&exynos5_subcmu_driver); + return 0; +} +core_initcall(exynos5_clk_drv_init); diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.h b/drivers/clk/samsung/clk-exynos5-subcmu.h new file mode 100644 index 000000000000..755ee8aaa3de --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5-subcmu.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __CLK_EXYNOS5_SUBCMU_H +#define __CLK_EXYNOS5_SUBCMU_H + +struct exynos5_subcmu_reg_dump { + u32 offset; + u32 value; + u32 mask; + u32 save; +}; + +struct exynos5_subcmu_info { + const struct samsung_div_clock *div_clks; + unsigned int nr_div_clks; + const struct samsung_gate_clock *gate_clks; + unsigned int nr_gate_clks; + struct exynos5_subcmu_reg_dump *suspend_regs; + unsigned int nr_suspend_regs; + const char *pd_name; +}; + +void exynos5_subcmus_init(struct samsung_clk_provider *ctx, int nr_cmus, + const struct exynos5_subcmu_info *cmu); + +#endif