diff mbox series

[v3] soc/tegra: Add devm_tegra_core_dev_init_opp_table()

Message ID 20210121190117.25235-1-digetx@gmail.com (mailing list archive)
State Superseded, archived
Headers show
Series [v3] soc/tegra: Add devm_tegra_core_dev_init_opp_table() | expand

Commit Message

Dmitry Osipenko Jan. 21, 2021, 7:01 p.m. UTC
Add common helper which initializes OPP table for Tegra SoC core devices.

Tested-by: Peter Geis <pgwipeout@gmail.com> # Ouya T30
Tested-by: Dmitry Osipenko <digetx@gmail.com> # A500 T20 and Nexus7 T30
Tested-by: Nicolas Chauvet <kwizart@gmail.com> # PAZ00 T20 and TK1 T124
Tested-by: Matt Merhar <mattmerhar@protonmail.com> # Ouya T30
[tested on some other non-upstreamed-yet T20/30/114 devices as well]
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---

Changelog:

v3: - This patch is factored out from [1] to ease merging of the patches
      that will use the new helper. The goal is to get this new helper
      into 5.12, this should remove dependency on this patch for a several
      patchsets of a different subsystems (DRM, media, memory, etc) that
      will target 5.13.

      @Thierry/Jon, please review and apply this patch for 5.12!

      [1] https://patchwork.ozlabs.org/project/linux-tegra/list/?series=221130

    - The v3 got couple very minor cleanup improvements in comparison to [1],
      like a removed unused variable and improved comments in the code.

 drivers/soc/tegra/common.c | 137 +++++++++++++++++++++++++++++++++++++
 include/soc/tegra/common.h |  30 ++++++++
 2 files changed, 167 insertions(+)

Comments

Viresh Kumar Jan. 22, 2021, 6:35 a.m. UTC | #1
On 21-01-21, 22:01, Dmitry Osipenko wrote:
> Add common helper which initializes OPP table for Tegra SoC core devices.
> 
> Tested-by: Peter Geis <pgwipeout@gmail.com> # Ouya T30
> Tested-by: Dmitry Osipenko <digetx@gmail.com> # A500 T20 and Nexus7 T30
> Tested-by: Nicolas Chauvet <kwizart@gmail.com> # PAZ00 T20 and TK1 T124
> Tested-by: Matt Merhar <mattmerhar@protonmail.com> # Ouya T30
> [tested on some other non-upstreamed-yet T20/30/114 devices as well]
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
> 
> Changelog:
> 
> v3: - This patch is factored out from [1] to ease merging of the patches
>       that will use the new helper. The goal is to get this new helper
>       into 5.12, this should remove dependency on this patch for a several
>       patchsets of a different subsystems (DRM, media, memory, etc) that
>       will target 5.13.
> 
>       @Thierry/Jon, please review and apply this patch for 5.12!

This is not how stuff works in kernel Dmitry, every commit in the
kernel tree should build(at least)/boot fine. Your patch can only be
applied once your base tree has all the patches on which your work is
based of, otherwise this will lead to build failure (stuff like git
bisect breaks with that). It would be better if you take this patch in
5.13, or after 5.12-rc2 once all other stuff lands.
Dmitry Osipenko Jan. 22, 2021, 2:41 p.m. UTC | #2
22.01.2021 09:35, Viresh Kumar пишет:
> On 21-01-21, 22:01, Dmitry Osipenko wrote:
>> Add common helper which initializes OPP table for Tegra SoC core devices.
>>
>> Tested-by: Peter Geis <pgwipeout@gmail.com> # Ouya T30
>> Tested-by: Dmitry Osipenko <digetx@gmail.com> # A500 T20 and Nexus7 T30
>> Tested-by: Nicolas Chauvet <kwizart@gmail.com> # PAZ00 T20 and TK1 T124
>> Tested-by: Matt Merhar <mattmerhar@protonmail.com> # Ouya T30
>> [tested on some other non-upstreamed-yet T20/30/114 devices as well]
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>>
>> Changelog:
>>
>> v3: - This patch is factored out from [1] to ease merging of the patches
>>       that will use the new helper. The goal is to get this new helper
>>       into 5.12, this should remove dependency on this patch for a several
>>       patchsets of a different subsystems (DRM, media, memory, etc) that
>>       will target 5.13.
>>
>>       @Thierry/Jon, please review and apply this patch for 5.12!
> 
> This is not how stuff works in kernel Dmitry, every commit in the
> kernel tree should build(at least)/boot fine. Your patch can only be
> applied once your base tree has all the patches on which your work is
> based of, otherwise this will lead to build failure (stuff like git
> bisect breaks with that). It would be better if you take this patch in
> 5.13, or after 5.12-rc2 once all other stuff lands.
> 

OMG, I completely missed that the devm series from Yangtao Li isn't
merged yet.

Viresh / Yangtao, will be it be okay if I'll collect all the
prerequisite devm patches from Yangtao + add this patch into a single
series that could be merged via the OPP tree for 5.12?

Of course Thierry or Jon will need to give the ack for the Tegra changes
in that case.
Viresh Kumar Jan. 25, 2021, 3:07 a.m. UTC | #3
On 22-01-21, 17:41, Dmitry Osipenko wrote:
> 22.01.2021 09:35, Viresh Kumar пишет:
> > On 21-01-21, 22:01, Dmitry Osipenko wrote:
> >> Add common helper which initializes OPP table for Tegra SoC core devices.
> >>
> >> Tested-by: Peter Geis <pgwipeout@gmail.com> # Ouya T30
> >> Tested-by: Dmitry Osipenko <digetx@gmail.com> # A500 T20 and Nexus7 T30
> >> Tested-by: Nicolas Chauvet <kwizart@gmail.com> # PAZ00 T20 and TK1 T124
> >> Tested-by: Matt Merhar <mattmerhar@protonmail.com> # Ouya T30
> >> [tested on some other non-upstreamed-yet T20/30/114 devices as well]
> >> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> >> ---
> >>
> >> Changelog:
> >>
> >> v3: - This patch is factored out from [1] to ease merging of the patches
> >>       that will use the new helper. The goal is to get this new helper
> >>       into 5.12, this should remove dependency on this patch for a several
> >>       patchsets of a different subsystems (DRM, media, memory, etc) that
> >>       will target 5.13.
> >>
> >>       @Thierry/Jon, please review and apply this patch for 5.12!
> > 
> > This is not how stuff works in kernel Dmitry, every commit in the
> > kernel tree should build(at least)/boot fine. Your patch can only be
> > applied once your base tree has all the patches on which your work is
> > based of, otherwise this will lead to build failure (stuff like git
> > bisect breaks with that). It would be better if you take this patch in
> > 5.13, or after 5.12-rc2 once all other stuff lands.
> > 
> 
> OMG, I completely missed that the devm series from Yangtao Li isn't
> merged yet.
> 
> Viresh / Yangtao, will be it be okay if I'll collect all the
> prerequisite devm patches from Yangtao + add this patch into a single
> series that could be merged via the OPP tree for 5.12?
> 
> Of course Thierry or Jon will need to give the ack for the Tegra changes
> in that case.

I haven't heard back from Yangtao since his last post, not sure what's going on.
It is normally better if he keeps posting his series, unless he is busy and will
not be able to do it.
Dmitry Osipenko Jan. 25, 2021, 5:23 p.m. UTC | #4
25.01.2021 06:07, Viresh Kumar пишет:
> On 22-01-21, 17:41, Dmitry Osipenko wrote:
>> 22.01.2021 09:35, Viresh Kumar пишет:
>>> On 21-01-21, 22:01, Dmitry Osipenko wrote:
>>>> Add common helper which initializes OPP table for Tegra SoC core devices.
>>>>
>>>> Tested-by: Peter Geis <pgwipeout@gmail.com> # Ouya T30
>>>> Tested-by: Dmitry Osipenko <digetx@gmail.com> # A500 T20 and Nexus7 T30
>>>> Tested-by: Nicolas Chauvet <kwizart@gmail.com> # PAZ00 T20 and TK1 T124
>>>> Tested-by: Matt Merhar <mattmerhar@protonmail.com> # Ouya T30
>>>> [tested on some other non-upstreamed-yet T20/30/114 devices as well]
>>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>>> ---
>>>>
>>>> Changelog:
>>>>
>>>> v3: - This patch is factored out from [1] to ease merging of the patches
>>>>       that will use the new helper. The goal is to get this new helper
>>>>       into 5.12, this should remove dependency on this patch for a several
>>>>       patchsets of a different subsystems (DRM, media, memory, etc) that
>>>>       will target 5.13.
>>>>
>>>>       @Thierry/Jon, please review and apply this patch for 5.12!
>>>
>>> This is not how stuff works in kernel Dmitry, every commit in the
>>> kernel tree should build(at least)/boot fine. Your patch can only be
>>> applied once your base tree has all the patches on which your work is
>>> based of, otherwise this will lead to build failure (stuff like git
>>> bisect breaks with that). It would be better if you take this patch in
>>> 5.13, or after 5.12-rc2 once all other stuff lands.
>>>
>>
>> OMG, I completely missed that the devm series from Yangtao Li isn't
>> merged yet.
>>
>> Viresh / Yangtao, will be it be okay if I'll collect all the
>> prerequisite devm patches from Yangtao + add this patch into a single
>> series that could be merged via the OPP tree for 5.12?
>>
>> Of course Thierry or Jon will need to give the ack for the Tegra changes
>> in that case.
> 
> I haven't heard back from Yangtao since his last post, not sure what's going on.
> It is normally better if he keeps posting his series, unless he is busy and will
> not be able to do it.
> 

Indeed, it will be much better if Yangtao could make the update, no
doubt about this.

If devm_tegra_core_dev_init_opp_table() will miss 5.12, then it will
likely put on hold couple Tegra patches for a another 2+ months, which
isn't critical, but it's a bit difficult to accept morally :)

Yangtao, could you please let us know the current status of yours
series? If you don't have spare time right now to finish v2, then I'd
like to pick up couple patches from yours v1 which add the devm_*
helpers that are used by this patch to make a small patchset that could
go into 5.12.
diff mbox series

Patch

diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index 3dc54f59cafe..6b965471db30 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -3,9 +3,16 @@ 
  * Copyright (C) 2014 NVIDIA CORPORATION.  All rights reserved.
  */
 
+#define dev_fmt(fmt)	"tegra-soc: " fmt
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/export.h>
 #include <linux/of.h>
+#include <linux/pm_opp.h>
 
 #include <soc/tegra/common.h>
+#include <soc/tegra/fuse.h>
 
 static const struct of_device_id tegra_machine_match[] = {
 	{ .compatible = "nvidia,tegra20", },
@@ -31,3 +38,133 @@  bool soc_is_tegra(void)
 
 	return match != NULL;
 }
+
+static int tegra_core_dev_init_opp_state(struct device *dev)
+{
+	struct dev_pm_opp *opp;
+	unsigned long rate;
+	struct clk *clk;
+	int err;
+
+	clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(dev, "failed to get clk: %pe\n", clk);
+		return PTR_ERR(clk);
+	}
+
+	/*
+	 * If voltage regulator presents, then we could select the fastest
+	 * clock rate, but driver doesn't support power management and
+	 * frequency scaling yet, hence the top freq OPP will vote for a
+	 * very high voltage that will produce lot's of heat.  Let's select
+	 * OPP for the current/default rate for now.
+	 *
+	 * Clock rate should be pre-initialized (i.e. it's non-zero) either
+	 * by clock driver or by assigned clocks in a device-tree.
+	 */
+	rate = clk_get_rate(clk);
+	if (!rate) {
+		dev_err(dev, "failed to get clk rate\n");
+		return -EINVAL;
+	}
+
+	/* find suitable OPP for the clock rate and supportable by hardware */
+	opp = dev_pm_opp_find_freq_ceil(dev, &rate);
+
+	/*
+	 * dev_pm_opp_set_rate() doesn't search for a floor clock rate and it
+	 * will error out if default clock rate is too high, i.e. unsupported
+	 * by a SoC hardware version.  Hence will find floor rate by ourselves.
+	 */
+	if (opp == ERR_PTR(-ERANGE))
+		opp = dev_pm_opp_find_freq_floor(dev, &rate);
+
+	err = PTR_ERR_OR_ZERO(opp);
+	if (err) {
+		dev_err(dev, "failed to get OPP for %ld Hz: %d\n",
+			rate, err);
+		return err;
+	}
+
+	dev_pm_opp_put(opp);
+
+	/*
+	 * First dummy rate-set initializes voltage vote by setting voltage
+	 * in accordance to the clock rate.  We need to do this because some
+	 * drivers currently don't support power management and clock is
+	 * permanently enabled.
+	 */
+	err = dev_pm_opp_set_rate(dev, rate);
+	if (err) {
+		dev_err(dev, "failed to initialize OPP clock: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+/**
+ * devm_tegra_core_dev_init_opp_table() - initialize OPP table
+ * @cfg: pointer to the OPP table configuration
+ *
+ * This function will initialize OPP table and sync OPP state of a Tegra SoC
+ * core device.
+ *
+ * Return: 0 on success or errorno.
+ */
+int devm_tegra_core_dev_init_opp_table(struct device *dev,
+				       struct tegra_core_opp_params *params)
+{
+	struct opp_table *opp_table;
+	u32 hw_version;
+	int err;
+
+	opp_table = devm_pm_opp_set_clkname(dev, NULL);
+	if (IS_ERR(opp_table)) {
+		dev_err(dev, "failed to set OPP clk %pe\n", opp_table);
+		return PTR_ERR(opp_table);
+	}
+
+	/* Tegra114+ doesn't support OPP yet */
+	if (!of_machine_is_compatible("nvidia,tegra20") &&
+	    !of_machine_is_compatible("nvidia,tegra30"))
+		return -ENODEV;
+
+	if (of_machine_is_compatible("nvidia,tegra20"))
+		hw_version = BIT(tegra_sku_info.soc_process_id);
+	else
+		hw_version = BIT(tegra_sku_info.soc_speedo_id);
+
+	opp_table = devm_pm_opp_set_supported_hw(dev, &hw_version, 1);
+	if (IS_ERR(opp_table)) {
+		dev_err(dev, "failed to set OPP supported HW: %pe\n", opp_table);
+		return PTR_ERR(opp_table);
+	}
+
+	/*
+	 * Older device-trees have an empty OPP table, hence we will get
+	 * -ENODEV from devm_pm_opp_of_add_table() for the older DTBs.
+	 *
+	 * The OPP table presence also varies per-device and depending
+	 * on a SoC generation, hence -ENODEV is expected to happen for
+	 * the newer DTs as well.
+	 */
+	err = devm_pm_opp_of_add_table(dev);
+	if (err) {
+		if (err == -ENODEV)
+			dev_err_once(dev, "OPP table not found, please update device-tree\n");
+		else
+			dev_err(dev, "failed to add OPP table: %d\n", err);
+
+		return err;
+	}
+
+	if (params->init_state) {
+		err = tegra_core_dev_init_opp_state(dev);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_tegra_core_dev_init_opp_table);
diff --git a/include/soc/tegra/common.h b/include/soc/tegra/common.h
index 98027a76ce3d..18e562496f2a 100644
--- a/include/soc/tegra/common.h
+++ b/include/soc/tegra/common.h
@@ -6,6 +6,36 @@ 
 #ifndef __SOC_TEGRA_COMMON_H__
 #define __SOC_TEGRA_COMMON_H__
 
+#include <linux/errno.h>
+#include <linux/types.h>
+
+struct device;
+
+/**
+ * Tegra SoC core device OPP table configuration
+ *
+ * @init_state: pre-initialize OPP state of a device
+ */
+struct tegra_core_opp_params {
+	bool init_state;
+};
+
+#ifdef CONFIG_ARCH_TEGRA
 bool soc_is_tegra(void);
+int devm_tegra_core_dev_init_opp_table(struct device *dev,
+				       struct tegra_core_opp_params *cfg);
+#else
+static inline bool soc_is_tegra(void)
+{
+	return false;
+}
+
+static inline int
+devm_tegra_core_dev_init_opp_table(struct device *dev,
+				   struct tegra_core_opp_params *cfg)
+{
+	return -ENODEV;
+}
+#endif
 
 #endif /* __SOC_TEGRA_COMMON_H__ */