From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFF62C433F5 for ; Sun, 21 Nov 2021 23:28:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233370AbhKUXbK (ORCPT ); Sun, 21 Nov 2021 18:31:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43434 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231954AbhKUXbA (ORCPT ); Sun, 21 Nov 2021 18:31:00 -0500 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 48DC5C06175B for ; Sun, 21 Nov 2021 15:27:53 -0800 (PST) Received: by mail-lf1-x134.google.com with SMTP id t26so71889486lfk.9 for ; Sun, 21 Nov 2021 15:27:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ASvzk7ohHyiTP3YMvvAST+eBDkFoGlnVX0ALjg78UAc=; b=SNK18cDfgnV/g2hvAq8DXWOiW6z5wss10k0z6+X4KtVMTsHxppPlFQPrB4m5rPHoMc puyBZt0Mu+1tOKVTAJf28wlSKfMB/re3wZsryRf4Kf/kyyKd8eV74RY4II8KVE9scbhF SA4Umlr3ynyheVernvW8XrU4eRL0p7POuV1t4LxUxtYeRJD0GdAPTk/OyrVd3p/RcwDS 4GombRiX4dUu8zXjR6aUfKQQchz39qD1yN85R9WHzdboT/GgAaoYULpRqwcErdbwbh8O c9GpGwOp7+KCLBcokbFUtQPfffKL411LShZummAlfWYPUQi3KnwCSbFfpI2/OkEL6Tck LWow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ASvzk7ohHyiTP3YMvvAST+eBDkFoGlnVX0ALjg78UAc=; b=8PbSmsc8znNmmMr+xOo5zyMI1TY92fHnk9xpZxCZBSXY9DqepxnYSmy+b/Woi353Gq G/Brz1j1Q00DMCqpTM/NR5BgUY5Ez6KyQptNey2mldqeM+fxlJTN6YVz7tZlr+OI7t0h fVZYW9dQJj9tHRv5HpQDYAbmT2raVlE9dPM8zamz0wlJR9TbOx54RuSTjSZ2yjW66/o6 riDIrB9jHbjnf9YAYUDXWyiUu5WNwgyeykPvbxnM9wAiVb5wiGFP8bNue4jZS1jddC/r Z2PxsiH7DyHvWlDfXdnB8doOxkkeKFhD8JcHSZqvR5SnGV4VZJDZPZztwfwI8pIuY7fq kj5g== X-Gm-Message-State: AOAM533nF5OLgqMX4f3gQgtiDXeY+YPw3i7Yl+LN6S54hC1oMdktiOfK lkO8FxOgXnYN09hQNqdYpiWTKQ== X-Google-Smtp-Source: ABdhPJwtGR/mGT3UelM1AbYFFy9HrkIkg9VjocR5ySYmzAvkZVbdsD2rBubXI6grFTWAgbjb3xc0Lw== X-Received: by 2002:a2e:9703:: with SMTP id r3mr46831569lji.422.1637537271615; Sun, 21 Nov 2021 15:27:51 -0800 (PST) Received: from localhost ([31.134.121.151]) by smtp.gmail.com with ESMTPSA id v6sm888012lfa.170.2021.11.21.15.27.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 21 Nov 2021 15:27:51 -0800 (PST) From: Sam Protsenko To: Sylwester Nawrocki , Krzysztof Kozlowski , Chanwoo Choi , Tomasz Figa , Rob Herring , Stephen Boyd , Michael Turquette Cc: David Virag , =?UTF-8?q?Pawe=C5=82=20Chmiel?= , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-samsung-soc@vger.kernel.org Subject: [PATCH 5/6] clk: samsung: exynos850: Register clocks early Date: Mon, 22 Nov 2021 01:27:40 +0200 Message-Id: <20211121232741.6967-6-semen.protsenko@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211121232741.6967-1-semen.protsenko@linaro.org> References: <20211121232741.6967-1-semen.protsenko@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Some clocks must be registered before init calls. For example MCT clock (from CMU_PERI) is needed for MCT timer driver, which is registered with TIMER_OF_DECLARE(). By the time we get to core_initcall() used for clk-exynos850 platform driver init, it's already too late. Inability to get "mct" clock in MCT driver leads to kernel panic, as functions registered with *_OF_DECLARE() can't do deferred calls. MCT timer driver can't be fixed either, as it's acting as a clock source and it's essential to register it in start_kernel() -> time_init(). Let's register CMU_PERI clocks early, using CLK_OF_DECLARE_DRIVER(), and do all stuff relying on "struct dev" object (like runtime PM) later in platform driver probe. Basically CLK_OF_DECLARE_DRIVER() matches CMU compatible, but clears OF_POPULATED flag, which allows the same device to be matched again later. CMU_TOP generates clocks needed for CMU_PERI, but it's already registered early. While at it, let's cleanup the code a bit, by extracting everything related to CMU initialization and registration to the separate function. Similar issue was discussed at [1] and addressed in commit 1f7db7bbf031 ("clk: renesas: cpg-mssr: Add early clock support"), as well as in drivers/clk/mediatek/clk-mt2712.c. [1] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20180829132954.64862-2-chris.brandt@renesas.com/ Signed-off-by: Sam Protsenko Reviewed-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-exynos850.c | 68 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c index 0eab7a115b44..1d257bca8b37 100644 --- a/drivers/clk/samsung/clk-exynos850.c +++ b/drivers/clk/samsung/clk-exynos850.c @@ -60,6 +60,43 @@ static void __init exynos850_init_clocks(struct device_node *np, iounmap(reg_base); } +/** + * exynos850_register_cmu - Register specified Exynos850 CMU domain + * @dev: Device object; may be NULL if this function is not being + * called from platform driver probe function + * @np: CMU device tree node + * @cmu: CMU data + * + * Register specified CMU domain, which includes next steps: + * + * 1. Enable parent clock of @cmu CMU + * 2. Set initial registers configuration for @cmu CMU clocks + * 3. Register @cmu CMU clocks using Samsung clock framework API + */ +static void __init exynos850_register_cmu(struct device *dev, + struct device_node *np, const struct samsung_cmu_info *cmu) +{ + /* Keep CMU parent clock running (needed for CMU registers access) */ + if (cmu->clk_name) { + struct clk *parent_clk; + + if (dev) + parent_clk = clk_get(dev, cmu->clk_name); + else + parent_clk = of_clk_get_by_name(np, cmu->clk_name); + + if (IS_ERR(parent_clk)) { + pr_err("%s: could not find bus clock %s; err = %ld\n", + __func__, cmu->clk_name, PTR_ERR(parent_clk)); + } else { + clk_prepare_enable(parent_clk); + } + } + + exynos850_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs); + samsung_cmu_register_one(np, cmu); +} + /* ---- CMU_TOP ------------------------------------------------------------- */ /* Register Offset definitions for CMU_TOP (0x120e0000) */ @@ -367,10 +404,10 @@ static const struct samsung_cmu_info top_cmu_info __initconst = { static void __init exynos850_cmu_top_init(struct device_node *np) { - exynos850_init_clocks(np, top_clk_regs, ARRAY_SIZE(top_clk_regs)); - samsung_cmu_register_one(np, &top_cmu_info); + exynos850_register_cmu(NULL, np, &top_cmu_info); } +/* Register CMU_TOP early, as it's a dependency for other early domains */ CLK_OF_DECLARE(exynos850_cmu_top, "samsung,exynos850-cmu-top", exynos850_cmu_top_init); @@ -850,6 +887,15 @@ static const struct samsung_cmu_info peri_cmu_info __initconst = { .clk_name = "dout_peri_bus", }; +static void __init exynos850_cmu_peri_init(struct device_node *np) +{ + exynos850_register_cmu(NULL, np, &peri_cmu_info); +} + +/* Register CMU_PERI early, as it's needed for MCT timer */ +CLK_OF_DECLARE_DRIVER(exynos850_cmu_peri, "samsung,exynos850-cmu-peri", + exynos850_cmu_peri_init); + /* ---- CMU_CORE ------------------------------------------------------------ */ /* Register Offset definitions for CMU_CORE (0x12000000) */ @@ -1014,24 +1060,12 @@ static int __init exynos850_cmu_probe(struct platform_device *pdev) { const struct samsung_cmu_info *info; struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; info = of_device_get_match_data(dev); - exynos850_init_clocks(np, info->clk_regs, info->nr_clk_regs); - samsung_cmu_register_one(np, info); - /* Keep bus clock running, so it's possible to access CMU registers */ - if (info->clk_name) { - struct clk *bus_clk; - - bus_clk = clk_get(dev, info->clk_name); - if (IS_ERR(bus_clk)) { - pr_err("%s: could not find bus clock %s; err = %ld\n", - __func__, info->clk_name, PTR_ERR(bus_clk)); - } else { - clk_prepare_enable(bus_clk); - } - } + /* Early clocks are already registered using CLK_OF_DECLARE_DRIVER() */ + if (info != &peri_cmu_info) + exynos850_register_cmu(dev, dev->of_node, info); return 0; } -- 2.30.2