From patchwork Fri May 18 20:06:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 10412039 X-Patchwork-Delegate: rjw@sisk.pl 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 975F06031B for ; Fri, 18 May 2018 20:08:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 87DA328751 for ; Fri, 18 May 2018 20:08:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7BC0B28807; Fri, 18 May 2018 20:08:15 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI 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 B395528751 for ; Fri, 18 May 2018 20:08:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751924AbeERUH7 (ORCPT ); Fri, 18 May 2018 16:07:59 -0400 Received: from mail-lf0-f66.google.com ([209.85.215.66]:40671 "EHLO mail-lf0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752422AbeERUHc (ORCPT ); Fri, 18 May 2018 16:07:32 -0400 Received: by mail-lf0-f66.google.com with SMTP id u140-v6so3390156lff.7; Fri, 18 May 2018 13:07:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=rl+XAPkECY1ZRNrJOkBPoew/g2VOgb9MCdgd6bLxaPw=; b=VBC5tw9Pc5BK/8TaOUF9+YfdWOMauxAIksjiz0dwTLfrrNpBRuR4Ol3ppGCpHjSL6/ XDVZwnVHYeWuqk0dgLalf3CNfK6dKKp1y+nGWJV79qAYX7I4IIUI0m1qdl+V/0VUbr1+ MZ2t6wJLvZalXscA7UPBhDA9T0QtDAIOdWN0CN2g1dPsbSGsHkB6vw7VO4e5g7VFZ5n9 DAMaNRiy00blGuOtKpBUnViJdD8Fa0d/Gp0pMudWok00Sj0vq+4hKNMndE1AgU+KPD5B YVcspBrgBEuc4Jn2a0GQ82zD3VkFUk4gc80mFU9tux68t7Ahde8V5r3Om3bSZzoPVQjk k3sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=rl+XAPkECY1ZRNrJOkBPoew/g2VOgb9MCdgd6bLxaPw=; b=Io70Me17+6PqF4jJ3U1ry5nVUpYpQA0nAiuBOXcOB3x5v5fa+7pnLbOVZQN5PMjX7D Juv71MEz9kWjDZabHC9yU3jZcDObmsY7T366vshP33TbuAJKX1j1XOaRgILnN/1+Yyq5 8LWDeMB2EOsCe6XFQPOMA/sgjXOu1tiBpq2vfQIJLKfhj4GKNsOpDYEvBNXmohk1+MzU v+TLxK/jRNqQXnp/g7MS97shnKf4fngPVfFTebsrR5HAgFJ4MJfpH4/glVl7087o3A3H Mz2A4/dMYrFgku0/GKhqHXWgYKLxwYpp239BEoRuFgemu6xYoEW1lydi33iBre+kxpuL l0/A== X-Gm-Message-State: ALKqPwdyjBosy+U1n08cLf+3a+4ZutV+xqMwWY9XTdkg6aGgxI0mqmvu S+ZNfYtjxC6v2E00Yumo/CQ= X-Google-Smtp-Source: AB8JxZpBhq6XanGRA3a59KgVmrVC32AVFuWZ2wLjyUpGoNQxHwvDZ/5NeSYQhG2PDxNusc5RLgS4jg== X-Received: by 2002:a2e:8018:: with SMTP id j24-v6mr6420710ljg.92.1526674050341; Fri, 18 May 2018 13:07:30 -0700 (PDT) Received: from localhost.localdomain ([109.252.91.60]) by smtp.gmail.com with ESMTPSA id z132-v6sm2026987lfd.45.2018.05.18.13.07.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 13:07:29 -0700 (PDT) From: Dmitry Osipenko To: "Rafael J. Wysocki" , Viresh Kumar , Thierry Reding , Jonathan Hunter Cc: linux-tegra@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Peter Geis Subject: [PATCH v2 11/11] cpufreq: tegra20: Wrap cpufreq into platform driver Date: Fri, 18 May 2018 23:06:42 +0300 Message-Id: <20180518200642.24815-12-digetx@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180518200642.24815-1-digetx@gmail.com> References: <20180518200642.24815-1-digetx@gmail.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently tegra20-cpufreq kernel module isn't getting autoloaded because there is no device associated with the module, this is one of two patches that resolves the module autoloading. This patch adds a module alias that will associate the tegra20-cpufreq kernel module with the platform device, other patch will instantiate the actual platform device. And now it makes sense to wrap cpufreq driver into a platform driver for consistency. Signed-off-by: Dmitry Osipenko Acked-by: Viresh Kumar --- drivers/cpufreq/tegra20-cpufreq.c | 145 ++++++++++++++++++------------ 1 file changed, 86 insertions(+), 59 deletions(-) diff --git a/drivers/cpufreq/tegra20-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c index 7b425ebe81e7..05f57dcd5215 100644 --- a/drivers/cpufreq/tegra20-cpufreq.c +++ b/drivers/cpufreq/tegra20-cpufreq.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include static struct cpufreq_frequency_table freq_table[] = { @@ -36,15 +36,20 @@ static struct cpufreq_frequency_table freq_table[] = { { .frequency = CPUFREQ_TABLE_END }, }; -static struct clk *cpu_clk; -static struct clk *pll_x_clk; -static struct clk *pll_p_clk; -static bool pll_x_prepared; +struct tegra20_cpufreq { + struct device *dev; + struct cpufreq_driver driver; + struct clk *cpu_clk; + struct clk *pll_x_clk; + struct clk *pll_p_clk; + bool pll_x_prepared; +}; static unsigned int tegra_get_intermediate(struct cpufreq_policy *policy, unsigned int index) { - unsigned int ifreq = clk_get_rate(pll_p_clk) / 1000; + struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data(); + unsigned int ifreq = clk_get_rate(cpufreq->pll_p_clk) / 1000; /* * Don't switch to intermediate freq if: @@ -60,6 +65,7 @@ static unsigned int tegra_get_intermediate(struct cpufreq_policy *policy, static int tegra_target_intermediate(struct cpufreq_policy *policy, unsigned int index) { + struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data(); int ret; /* @@ -72,21 +78,22 @@ static int tegra_target_intermediate(struct cpufreq_policy *policy, * Also, we wouldn't be using pll_x anymore and must not take extra * reference to it, as it can be disabled now to save some power. */ - clk_prepare_enable(pll_x_clk); + clk_prepare_enable(cpufreq->pll_x_clk); - ret = clk_set_parent(cpu_clk, pll_p_clk); + ret = clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_p_clk); if (ret) - clk_disable_unprepare(pll_x_clk); + clk_disable_unprepare(cpufreq->pll_x_clk); else - pll_x_prepared = true; + cpufreq->pll_x_prepared = true; return ret; } static int tegra_target(struct cpufreq_policy *policy, unsigned int index) { + struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data(); unsigned long rate = freq_table[index].frequency; - unsigned int ifreq = clk_get_rate(pll_p_clk) / 1000; + unsigned int ifreq = clk_get_rate(cpufreq->pll_p_clk) / 1000; int ret; /* @@ -94,14 +101,14 @@ static int tegra_target(struct cpufreq_policy *policy, unsigned int index) * as it isn't used anymore. */ if (rate == ifreq) - return clk_set_parent(cpu_clk, pll_p_clk); + return clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_p_clk); - ret = clk_set_rate(pll_x_clk, rate * 1000); + ret = clk_set_rate(cpufreq->pll_x_clk, rate * 1000); /* Restore to earlier frequency on error, i.e. pll_x */ if (ret) - pr_err("Failed to change pll_x to %lu\n", rate); + dev_err(cpufreq->dev, "Failed to change pll_x to %lu\n", rate); - ret = clk_set_parent(cpu_clk, pll_x_clk); + ret = clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_x_clk); /* This shouldn't fail while changing or restoring */ WARN_ON(ret); @@ -109,9 +116,9 @@ static int tegra_target(struct cpufreq_policy *policy, unsigned int index) * Drop count to pll_x clock only if we switched to intermediate freq * earlier while transitioning to a target frequency. */ - if (pll_x_prepared) { - clk_disable_unprepare(pll_x_clk); - pll_x_prepared = false; + if (cpufreq->pll_x_prepared) { + clk_disable_unprepare(cpufreq->pll_x_clk); + cpufreq->pll_x_prepared = false; } return ret; @@ -119,91 +126,111 @@ static int tegra_target(struct cpufreq_policy *policy, unsigned int index) static int tegra_cpu_init(struct cpufreq_policy *policy) { + struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data(); int ret; - clk_prepare_enable(cpu_clk); + clk_prepare_enable(cpufreq->cpu_clk); /* FIXME: what's the actual transition time? */ ret = cpufreq_generic_init(policy, freq_table, 300 * 1000); if (ret) { - clk_disable_unprepare(cpu_clk); + clk_disable_unprepare(cpufreq->cpu_clk); return ret; } - policy->clk = cpu_clk; + policy->clk = cpufreq->cpu_clk; policy->suspend_freq = freq_table[0].frequency; return 0; } static int tegra_cpu_exit(struct cpufreq_policy *policy) { - clk_disable_unprepare(cpu_clk); + struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data(); + + clk_disable_unprepare(cpufreq->cpu_clk); return 0; } -static struct cpufreq_driver tegra_cpufreq_driver = { - .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, - .verify = cpufreq_generic_frequency_table_verify, - .get_intermediate = tegra_get_intermediate, - .target_intermediate = tegra_target_intermediate, - .target_index = tegra_target, - .get = cpufreq_generic_get, - .init = tegra_cpu_init, - .exit = tegra_cpu_exit, - .name = "tegra", - .attr = cpufreq_generic_attr, - .suspend = cpufreq_generic_suspend, -}; - -static int __init tegra_cpufreq_init(void) +static int tegra20_cpufreq_probe(struct platform_device *pdev) { + struct tegra20_cpufreq *cpufreq; int err; - if (!of_machine_is_compatible("nvidia,tegra20")) - return -ENODEV; + cpufreq = devm_kzalloc(&pdev->dev, sizeof(*cpufreq), GFP_KERNEL); + if (!cpufreq) + return -ENOMEM; - cpu_clk = clk_get_sys(NULL, "cclk"); - if (IS_ERR(cpu_clk)) - return PTR_ERR(cpu_clk); + cpufreq->cpu_clk = clk_get_sys(NULL, "cclk"); + if (IS_ERR(cpufreq->cpu_clk)) + return PTR_ERR(cpufreq->cpu_clk); - pll_x_clk = clk_get_sys(NULL, "pll_x"); - if (IS_ERR(pll_x_clk)) { - err = PTR_ERR(pll_x_clk); + cpufreq->pll_x_clk = clk_get_sys(NULL, "pll_x"); + if (IS_ERR(cpufreq->pll_x_clk)) { + err = PTR_ERR(cpufreq->pll_x_clk); goto put_cpu; } - pll_p_clk = clk_get_sys(NULL, "pll_p"); - if (IS_ERR(pll_p_clk)) { - err = PTR_ERR(pll_p_clk); + cpufreq->pll_p_clk = clk_get_sys(NULL, "pll_p"); + if (IS_ERR(cpufreq->pll_p_clk)) { + err = PTR_ERR(cpufreq->pll_p_clk); goto put_pll_x; } - err = cpufreq_register_driver(&tegra_cpufreq_driver); + cpufreq->dev = &pdev->dev; + cpufreq->driver.get = cpufreq_generic_get; + cpufreq->driver.attr = cpufreq_generic_attr; + cpufreq->driver.init = tegra_cpu_init; + cpufreq->driver.exit = tegra_cpu_exit; + cpufreq->driver.flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK; + cpufreq->driver.verify = cpufreq_generic_frequency_table_verify; + cpufreq->driver.suspend = cpufreq_generic_suspend; + cpufreq->driver.driver_data = cpufreq; + cpufreq->driver.target_index = tegra_target; + cpufreq->driver.get_intermediate = tegra_get_intermediate; + cpufreq->driver.target_intermediate = tegra_target_intermediate; + snprintf(cpufreq->driver.name, CPUFREQ_NAME_LEN, "tegra"); + + err = cpufreq_register_driver(&cpufreq->driver); if (err) goto put_pll_p; + platform_set_drvdata(pdev, cpufreq); + return 0; put_pll_p: - clk_put(pll_p_clk); + clk_put(cpufreq->pll_p_clk); put_pll_x: - clk_put(pll_x_clk); + clk_put(cpufreq->pll_x_clk); put_cpu: - clk_put(cpu_clk); + clk_put(cpufreq->cpu_clk); return err; } -static void __exit tegra_cpufreq_exit(void) +static int tegra20_cpufreq_remove(struct platform_device *pdev) { - cpufreq_unregister_driver(&tegra_cpufreq_driver); - clk_put(pll_p_clk); - clk_put(pll_x_clk); - clk_put(cpu_clk); + struct tegra20_cpufreq *cpufreq = platform_get_drvdata(pdev); + + cpufreq_unregister_driver(&cpufreq->driver); + + clk_put(cpufreq->pll_p_clk); + clk_put(cpufreq->pll_x_clk); + clk_put(cpufreq->cpu_clk); + + return 0; } +static struct platform_driver tegra20_cpufreq_driver = { + .probe = tegra20_cpufreq_probe, + .remove = tegra20_cpufreq_remove, + .driver = { + .name = "tegra20-cpufreq", + }, +}; +module_platform_driver(tegra20_cpufreq_driver); + +MODULE_ALIAS("platform:tegra20-cpufreq"); MODULE_AUTHOR("Colin Cross "); MODULE_DESCRIPTION("NVIDIA Tegra20 cpufreq driver"); MODULE_LICENSE("GPL"); -module_init(tegra_cpufreq_init); -module_exit(tegra_cpufreq_exit);