linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver
@ 2018-10-21 20:54 Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators Dmitry Osipenko
                   ` (16 more replies)
  0 siblings, 17 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Hello,

This series adds support for CPU frequency/voltage scaling on Tegra20/30,
it adds device tree support that allow to specify clock rate/voltages per
board and to implement thermal throttling. The tegra20-cpufreq driver has
been re-worked to support that all.

Note that this series depends on in-progress clock [0] and regulator [1]
patches.

Changelog:

v2:
    - Implemented DVFS support. Currently only CPU rail changes voltage,
      while CORE/RTC locked to maximum. The CORE can be unlocked once all
      of peripheral drivers will gain support for DVFS. See "TODO" comment
      in the driver. On Tegra20 CPU temperature is lower by 5-6 C during
      idling with DVFS. On Tegra30 CPU temperature is lower by 1-2 C, and
      it drops by 6-7 C if CORE rail scaling is unlocked.

    - Device-tree binding has been reworked to support voltage regulators
      and HW versioning. Now CPU OPP's are specified per HW version and
      include voltage entry. OPP values are taken from downstream kernel
      [2][3]. The "backup" clock has been renamed to "intermediate".

[0] https://lkml.org/lkml/2018/8/30/960
[1] https://lkml.org/lkml/2018/10/5/682
[2] https://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=blob;f=arch/arm/mach-tegra/tegra2_dvfs.c;hb=l4t/l4t-r16-r2
[3] https://nv-tegra.nvidia.com/gitweb/?p=linux-2.6.git;a=blob;f=arch/arm/mach-tegra/tegra3_dvfs.c;hb=l4t/l4t-r16-r2

Dmitry Osipenko (17):
  OPP: Allow to request stub voltage regulators
  soc/tegra: fuse: Export tegra_get_chip_id()
  dt-bindings: cpufreq: Add binding for NVIDIA Tegra20/30
  cpufreq: tegra20: Support OPP, thermal cooling, DVFS and Tegra30
  ARM: tegra: Create tegra20-cpufreq device on Tegra30
  ARM: dts: tegra20: Add CPU Operating Performance Points
  ARM: dts: tegra30: Add CPU Operating Performance Points
  ARM: dts: tegra20: colibri: Setup voltage regulators for DVFS
  ARM: dts: tegra20: harmony: Setup voltage regulators for DVFS
  ARM: dts: tegra20: paz00: Setup voltage regulators for DVFS
  ARM: dts: tegra20: seaboard: Setup voltage regulators for DVFS
  ARM: dts: tegra20: tamonten: Setup voltage regulators for DVFS
  ARM: dts: tegra20: ventana: Setup voltage regulators for DVFS
  ARM: dts: tegra30: apalis: Setup voltage regulators for DVFS
  ARM: dts: tegra30: beaver: Setup voltage regulators for DVFS
  ARM: dts: tegra30: cardhu: Setup voltage regulators for DVFS
  ARM: dts: tegra30: colibri: Setup voltage regulators for DVFS

 .../cpufreq/nvidia,tegra20-cpufreq.txt        |  96 ++
 arch/arm/boot/dts/tegra20-colibri.dtsi        |  31 +-
 arch/arm/boot/dts/tegra20-harmony.dts         |  31 +-
 arch/arm/boot/dts/tegra20-paz00.dts           |  31 +-
 arch/arm/boot/dts/tegra20-seaboard.dts        |  27 +-
 arch/arm/boot/dts/tegra20-tamonten.dtsi       |  31 +-
 arch/arm/boot/dts/tegra20-ventana.dts         |  31 +-
 arch/arm/boot/dts/tegra20.dtsi                | 277 ++++++
 arch/arm/boot/dts/tegra30-apalis.dtsi         |  19 +-
 arch/arm/boot/dts/tegra30-beaver.dts          |  19 +-
 arch/arm/boot/dts/tegra30-cardhu.dtsi         |  19 +-
 arch/arm/boot/dts/tegra30-colibri.dtsi        |  19 +-
 arch/arm/boot/dts/tegra30.dtsi                | 688 +++++++++++++++
 arch/arm/mach-tegra/tegra.c                   |   4 +
 drivers/cpufreq/Kconfig.arm                   |   2 +
 drivers/cpufreq/cpufreq-dt-platdev.c          |   2 +
 drivers/cpufreq/cpufreq-dt.c                  |   2 +-
 drivers/cpufreq/tegra20-cpufreq.c             | 832 +++++++++++++++---
 drivers/cpufreq/ti-cpufreq.c                  |   3 +-
 drivers/opp/core.c                            |   9 +-
 drivers/soc/tegra/fuse/tegra-apbmisc.c        |   1 +
 include/linux/pm_opp.h                        |   4 +-
 22 files changed, 2006 insertions(+), 172 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt

-- 
2.19.0


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-22  5:36   ` Viresh Kumar
  2018-10-21 20:54 ` [RFC PATCH v2 02/17] soc/tegra: fuse: Export tegra_get_chip_id() Dmitry Osipenko
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Voltage regulators may be not available on some variations of HW, allow to
request stub voltage regulators by OPP core in a such case to reduce code
churning within drivers.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/cpufreq/cpufreq-dt.c | 2 +-
 drivers/cpufreq/ti-cpufreq.c | 3 ++-
 drivers/opp/core.c           | 9 +++++++--
 include/linux/pm_opp.h       | 4 ++--
 4 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index e58bfcb1169e..6ebca472ec76 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -196,7 +196,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	 */
 	name = find_supply_name(cpu_dev);
 	if (name) {
-		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
+		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1, false);
 		if (IS_ERR(opp_table)) {
 			ret = PTR_ERR(opp_table);
 			dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
index 3f0e2a14895a..9099c8cdf447 100644
--- a/drivers/cpufreq/ti-cpufreq.c
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -268,7 +268,8 @@ static int ti_cpufreq_probe(struct platform_device *pdev)
 	if (opp_data->soc_data->multi_regulator) {
 		ti_opp_table = dev_pm_opp_set_regulators(opp_data->cpu_dev,
 							 reg_names,
-							 ARRAY_SIZE(reg_names));
+							 ARRAY_SIZE(reg_names),
+							 false);
 		if (IS_ERR(ti_opp_table)) {
 			dev_pm_opp_put_supported_hw(opp_data->opp_table);
 			ret =  PTR_ERR(ti_opp_table);
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 2c2df4e4fc14..fba1d7a1eb7c 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1365,6 +1365,7 @@ static void _free_set_opp_data(struct opp_table *opp_table)
  * @dev: Device for which regulator name is being set.
  * @names: Array of pointers to the names of the regulator.
  * @count: Number of regulators.
+ * @allow_stub_regulator: Some or all regulators can be missed.
  *
  * In order to support OPP switching, OPP layer needs to know the name of the
  * device's regulators, as the core would be required to switch voltages as
@@ -1374,7 +1375,8 @@ static void _free_set_opp_data(struct opp_table *opp_table)
  */
 struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
 					    const char * const names[],
-					    unsigned int count)
+					    unsigned int count,
+					    bool allow_stub_regulator)
 {
 	struct opp_table *opp_table;
 	struct regulator *reg;
@@ -1403,7 +1405,10 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
 	}
 
 	for (i = 0; i < count; i++) {
-		reg = regulator_get_optional(dev, names[i]);
+		if (allow_stub_regulator)
+			reg = regulator_get(dev, names[i]);
+		else
+			reg = regulator_get_optional(dev, names[i]);
 		if (IS_ERR(reg)) {
 			ret = PTR_ERR(reg);
 			if (ret != -EPROBE_DEFER)
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index 5d399eeef172..480666b0a008 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -120,7 +120,7 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev, const u32 *ver
 void dev_pm_opp_put_supported_hw(struct opp_table *opp_table);
 struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name);
 void dev_pm_opp_put_prop_name(struct opp_table *opp_table);
-struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count);
+struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count, bool allow_stub_regulator);
 void dev_pm_opp_put_regulators(struct opp_table *opp_table);
 struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name);
 void dev_pm_opp_put_clkname(struct opp_table *opp_table);
@@ -258,7 +258,7 @@ static inline struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, con
 
 static inline void dev_pm_opp_put_prop_name(struct opp_table *opp_table) {}
 
-static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count)
+static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count, bool allow_stub_regulator)
 {
 	return ERR_PTR(-ENOTSUPP);
 }
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 02/17] soc/tegra: fuse: Export tegra_get_chip_id()
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 21:33   ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 03/17] dt-bindings: cpufreq: Add binding for NVIDIA Tegra20/30 Dmitry Osipenko
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

This function is used by tegra20-cpufreq driver which can be built as a
kernel module.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/soc/tegra/fuse/tegra-apbmisc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index e5a4d8f98b10..c94dccf3eb30 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -51,6 +51,7 @@ u8 tegra_get_chip_id(void)
 {
 	return (tegra_read_chipid() >> 8) & 0xff;
 }
+EXPORT_SYMBOL_GPL(tegra_get_chip_id);
 
 u32 tegra_read_straps(void)
 {
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 03/17] dt-bindings: cpufreq: Add binding for NVIDIA Tegra20/30
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 02/17] soc/tegra: fuse: Export tegra_get_chip_id() Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-11-05 21:30   ` Rob Herring
  2018-10-21 20:54 ` [RFC PATCH v2 04/17] cpufreq: tegra20: Support OPP, thermal cooling, DVFS and Tegra30 Dmitry Osipenko
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Add device-tree binding that describes CPU frequency-scaling hardware
found on NVIDIA Tegra20/30 SoC's.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../cpufreq/nvidia,tegra20-cpufreq.txt        | 96 +++++++++++++++++++
 1 file changed, 96 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
new file mode 100644
index 000000000000..a8023ea7a99f
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
@@ -0,0 +1,96 @@
+Binding for NVIDIA Tegra20 CPUFreq
+==================================
+
+Required properties:
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - pll_x: main-parent for CPU clock, must be the first entry
+  - intermediate: intermediate-parent for CPU clock
+  - cclk: the CPU clock
+- operating-points-v2: See ../bindings/opp/opp.txt for details.
+- #cooling-cells: Should be 2. See ../thermal/thermal.txt for details.
+
+For each opp entry in 'operating-points-v2' table:
+- opp-supported-hw: Two bitfields indicating:
+	On Tegra20:
+	1. CPU process ID mask
+	2. SoC speedo ID mask
+
+	On Tegra30:
+	1. CPU process ID mask
+	2. CPU speedo ID mask
+
+	A bitwise AND is performed against these values and if any bit
+	matches, the OPP gets enabled.
+
+- opp-microvolt: CPU voltage triplet.
+
+Optional properties:
+- cpu-supply: Phandle to the CPU power supply.
+- core-supply: Phandle to the CORE power supply.
+- rtc-supply: Phandle to the RTC power supply, required only for Tegra20.
+
+Voltage supply requirements:
+- Tegra20:
+	CORE and RTC regulators must be coupled using the regulator-coupled-with
+	property and regulator-coupled-max-spread property must be set to no
+	more than 170mV.
+
+	See ../regulator/regulator.txt for more detail about the properties.
+
+- Tegra30:
+	CORE and CPU regulators must be coupled using the regulator-coupled-with
+	property and regulator-coupled-max-spread property must be set to no
+	more than 300mV. Each of CORE and CPU regulators must set
+	regulator-max-step-microvolt property to no more than 100mV.
+
+	See ../regulator/regulator.txt for more detail about the properties.
+
+
+Example:
+	regulators {
+		cpu_reg: regulator0 {
+			regulator-name = "vdd_cpu";
+		};
+
+		core_reg: regulator1 {
+			regulator-name = "vdd_core";
+			regulator-coupled-with = <&rtc_reg>;
+			regulator-coupled-max-spread = <170000>;
+		};
+
+		rtc_reg: regulator2 {
+			regulator-name = "vdd_rtc";
+			regulator-coupled-with = <&core_reg>;
+			regulator-coupled-max-spread = <170000>;
+		};
+	};
+
+	cpu0_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+
+		opp@456000000 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <825000 825000 1125000>;
+			opp-supported-hw = <0x03 0x0001>;
+			opp-hz = /bits/ 64 <456000000>;
+		};
+
+		...
+	};
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,cortex-a9";
+			clocks = <&tegra_car TEGRA20_CLK_PLL_X>,
+				 <&tegra_car TEGRA20_CLK_PLL_P>,
+				 <&tegra_car TEGRA20_CLK_CCLK>;
+			clock-names = "pll_x", "intermediate", "cclk";
+			operating-points-v2 = <&cpu0_opp_table>;
+			cpu-supply = <&cpu_reg>;
+			core-supply = <&core_reg>;
+			rtc-supply = <&rtc_reg>;
+			#cooling-cells = <2>;
+		};
+	};
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 04/17] cpufreq: tegra20: Support OPP, thermal cooling, DVFS and Tegra30
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 03/17] dt-bindings: cpufreq: Add binding for NVIDIA Tegra20/30 Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 05/17] ARM: tegra: Create tegra20-cpufreq device on Tegra30 Dmitry Osipenko
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Add support for thermal throttling, Operating Performance Points and DVFS.
Driver now relies on OPP's supplied via device tree and therefore will
work only on devices that use the updated device tree. The generalization
of the driver allows to transparently support Tegra30.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/cpufreq/Kconfig.arm          |   2 +
 drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
 drivers/cpufreq/tegra20-cpufreq.c    | 832 +++++++++++++++++++++++----
 3 files changed, 734 insertions(+), 102 deletions(-)

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 0cd8eb76ad59..78795d108f5e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -262,7 +262,9 @@ config ARM_TANGO_CPUFREQ
 
 config ARM_TEGRA20_CPUFREQ
 	tristate "Tegra20 CPUFreq support"
+	depends on !CPU_THERMAL || THERMAL
 	depends on ARCH_TEGRA
+	select PM_OPP
 	default y
 	help
 	  This adds the CPUFreq driver support for Tegra20 SOCs.
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index b1c5468dca16..ecc4d3d14850 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -118,6 +118,8 @@ static const struct of_device_id blacklist[] __initconst = {
 	{ .compatible = "mediatek,mt8173", },
 	{ .compatible = "mediatek,mt8176", },
 
+	{ .compatible = "nvidia,tegra20", },
+	{ .compatible = "nvidia,tegra30", },
 	{ .compatible = "nvidia,tegra124", },
 
 	{ .compatible = "qcom,apq8096", },
diff --git a/drivers/cpufreq/tegra20-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c
index 05f57dcd5215..a7d1c2899e3c 100644
--- a/drivers/cpufreq/tegra20-cpufreq.c
+++ b/drivers/cpufreq/tegra20-cpufreq.c
@@ -17,220 +17,848 @@
  */
 
 #include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpu_cooling.h>
 #include <linux/cpufreq.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/regulator/consumer.h>
 #include <linux/types.h>
+#include <linux/workqueue.h>
 
-static struct cpufreq_frequency_table freq_table[] = {
-	{ .frequency = 216000 },
-	{ .frequency = 312000 },
-	{ .frequency = 456000 },
-	{ .frequency = 608000 },
-	{ .frequency = 760000 },
-	{ .frequency = 816000 },
-	{ .frequency = 912000 },
-	{ .frequency = 1000000 },
-	{ .frequency = CPUFREQ_TABLE_END },
-};
+#include <soc/tegra/fuse.h>
+
+#define PLLX_PREPARE		BIT(0)
+#define PLLX_PREPARED		BIT(1)
 
-struct tegra20_cpufreq {
+struct tegra_cpufreq {
 	struct device *dev;
+	struct device *cpu_dev;
+	struct regulator *reg_cpu;
+	struct regulator *reg_core;
+	struct regulator *reg_rtc;
+	struct opp_table *opp_table;
 	struct cpufreq_driver driver;
+	struct thermal_cooling_device *cdev;
+	struct cpufreq_frequency_table *freq_table;
 	struct clk *cpu_clk;
 	struct clk *pll_x_clk;
-	struct clk *pll_p_clk;
-	bool pll_x_prepared;
+	struct clk *intermediate_clk;
+	unsigned long intermediate_rate;
+	unsigned int state;
+	unsigned int chip;
+	int cpu_speedo_id;
+
+	/* deferred voltage change */
+	struct delayed_work work;
+	struct dev_pm_opp_supply supply_cpu;
+	unsigned long actual_cpu_uV;
 };
 
+static unsigned int voltage_drop_interval_ms = 500;
+
 static unsigned int tegra_get_intermediate(struct cpufreq_policy *policy,
 					   unsigned int index)
 {
-	struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
-	unsigned int ifreq = clk_get_rate(cpufreq->pll_p_clk) / 1000;
+	struct tegra_cpufreq *cpufreq = cpufreq_get_driver_data();
+	struct clk *cpu_parent = clk_get_parent(cpufreq->cpu_clk);
+	unsigned long new_rate = cpufreq->freq_table[index].frequency * 1000;
+	int err;
 
 	/*
-	 * Don't switch to intermediate freq if:
-	 * - we are already at it, i.e. policy->cur == ifreq
-	 * - index corresponds to ifreq
+	 * Make sure that intermediate clock rate stays consistent during
+	 * transition by entering into critical section of the intermediate
+	 * clock.
 	 */
-	if (freq_table[index].frequency == ifreq || policy->cur == ifreq)
+	err = clk_rate_exclusive_get(cpufreq->intermediate_clk);
+	/* this shouldn't fail */
+	WARN_ON_ONCE(err);
+
+	/*
+	 * When target rate is equal to intermediate rate, we don't need to
+	 * switch to intermediate clock and so the intermediate routine isn't
+	 * called. Also, we wouldn't be using PLLX anymore and must not
+	 * take extra reference to it, as it can be disabled to save some
+	 * power.
+	 */
+	cpufreq->intermediate_rate = clk_get_rate(cpufreq->intermediate_clk);
+
+	if (new_rate == cpufreq->intermediate_rate)
+		cpufreq->state &= ~PLLX_PREPARE;
+	else
+		cpufreq->state |= PLLX_PREPARE;
+
+	/* don't switch to intermediate freq if we are already at it */
+	if (clk_is_match(cpu_parent, cpufreq->intermediate_clk))
 		return 0;
 
-	return ifreq;
+	return cpufreq->intermediate_rate / 1000;
 }
 
 static int tegra_target_intermediate(struct cpufreq_policy *policy,
 				     unsigned int index)
 {
-	struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
-	int ret;
+	struct tegra_cpufreq *cpufreq = cpufreq_get_driver_data();
+	unsigned int state = cpufreq->state;
+	int err;
 
 	/*
-	 * Take an extra reference to the main pll so it doesn't turn
-	 * off when we move the cpu off of it as enabling it again while we
-	 * switch to it from tegra_target() would take additional time.
-	 *
-	 * When target-freq is equal to intermediate freq we don't need to
-	 * switch to an intermediate freq and so this routine isn't called.
-	 * 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.
+	 * Take an extra reference to the main PLLX so it doesn't turn off
+	 * when we move the CPU clock to intermediate clock as enabling it
+	 * again  while we switch to it from tegra_target() would take
+	 * additional time.
 	 */
-	clk_prepare_enable(cpufreq->pll_x_clk);
+	if ((state & (PLLX_PREPARED | PLLX_PREPARE)) == PLLX_PREPARE) {
+		err = clk_prepare_enable(cpufreq->pll_x_clk);
+		if (WARN_ON_ONCE(err))
+			goto err_exclusive_put;
 
-	ret = clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_p_clk);
-	if (ret)
+		cpufreq->state |= PLLX_PREPARED;
+	}
+
+	err = clk_set_parent(cpufreq->cpu_clk, cpufreq->intermediate_clk);
+	if (WARN_ON_ONCE(err))
+		goto err_exclusive_put;
+
+	return 0;
+
+err_exclusive_put:
+	clk_rate_exclusive_put(cpufreq->intermediate_clk);
+
+	if (cpufreq->state & PLLX_PREPARED) {
 		clk_disable_unprepare(cpufreq->pll_x_clk);
-	else
-		cpufreq->pll_x_prepared = true;
+		cpufreq->state &= ~PLLX_PREPARED;
+	}
 
-	return ret;
+	return err;
 }
 
 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(cpufreq->pll_p_clk) / 1000;
+	struct tegra_cpufreq *cpufreq = cpufreq_get_driver_data();
+	unsigned long new_rate = cpufreq->freq_table[index].frequency * 1000;
+	unsigned int state = cpufreq->state;
 	int ret;
 
 	/*
-	 * target freq == pll_p, don't need to take extra reference to pll_x_clk
-	 * as it isn't used anymore.
+	 * Drop refcount to PLLX only if we switched to intermediate clock
+	 * earlier during transitioning to a target frequency and we are going
+	 * to stay with the intermediate clock.
 	 */
-	if (rate == ifreq)
-		return clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_p_clk);
+	if ((state & (PLLX_PREPARED | PLLX_PREPARE)) == PLLX_PREPARED) {
+		clk_disable_unprepare(cpufreq->pll_x_clk);
+		state &= ~PLLX_PREPARED;
+	}
 
-	ret = clk_set_rate(cpufreq->pll_x_clk, rate * 1000);
-	/* Restore to earlier frequency on error, i.e. pll_x */
+	/*
+	 * Switch to new OPP, note that this will change PLLX rate and
+	 * not the CCLK.
+	 */
+	ret = dev_pm_opp_set_rate(cpufreq->cpu_dev, new_rate);
 	if (ret)
-		dev_err(cpufreq->dev, "Failed to change pll_x to %lu\n", rate);
+		goto exclusive_put;
 
-	ret = clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_x_clk);
-	/* This shouldn't fail while changing or restoring */
-	WARN_ON(ret);
+	/*
+	 * Target rate == intermediate rate leaves PLLX turned off, CPU is
+	 * kept running off the intermediate clock. This should save us some
+	 * power by keeping one more PLL disabled because the intermediate
+	 * clock assumed to be always-on. In this case PLLX_PREPARE flag will
+	 * be omitted.
+	 */
+	if (state & PLLX_PREPARE) {
+		/*
+		 * CCF doesn't return error if clock-enabling fails on
+		 * re-parent, hence enable it now.
+		 */
+		ret = clk_prepare_enable(cpufreq->pll_x_clk);
+		if (WARN_ON_ONCE(ret))
+			goto exclusive_put;
+
+		ret = clk_set_parent(cpufreq->cpu_clk, cpufreq->pll_x_clk);
+
+		clk_disable_unprepare(cpufreq->pll_x_clk);
+	}
 
 	/*
-	 * Drop count to pll_x clock only if we switched to intermediate freq
-	 * earlier while transitioning to a target frequency.
+	 * Drop refcount to PLLX only if we switched to intermediate clock
+	 * earlier during transitioning to a target frequency.
 	 */
-	if (cpufreq->pll_x_prepared) {
+	if (state & PLLX_PREPARED) {
 		clk_disable_unprepare(cpufreq->pll_x_clk);
-		cpufreq->pll_x_prepared = false;
+		state &= ~PLLX_PREPARED;
 	}
 
+exclusive_put:
+	clk_rate_exclusive_put(cpufreq->intermediate_clk);
+
+	cpufreq->state = state;
+
 	return ret;
 }
 
-static int tegra_cpu_init(struct cpufreq_policy *policy)
+static int tegra_cpu_opp_set_core_voltage(struct tegra_cpufreq *cpufreq,
+					  struct dev_pm_opp_supply *cpu_supply)
+{
+	int min_core_uV = INT_MAX, max_core_uV = INT_MIN;
+	int min_rtc_uV = INT_MAX, max_rtc_uV = INT_MIN;
+	int err;
+
+	if (cpufreq->chip == TEGRA20) {
+		/* only Tegra20 require to adjust RTC domain voltage */
+		min_core_uV = cpu_supply->u_volt_min + 125000;
+		max_core_uV = 1300000;
+		min_rtc_uV  = cpu_supply->u_volt_min + 125000;
+		max_rtc_uV  = 1300000;
+	} else {
+		/*
+		 * On Tegra30 min CORE voltage vary depending on the CPU
+		 * voltage and grade of HW. Note that we assume here that
+		 * the default (validated) CPU voltages are being used.
+		 */
+		switch (cpu_supply->u_volt_min) {
+		case 0 ... 799999:
+			min_core_uV = 950000;
+			break;
+
+		case 800000 ... 899999:
+			min_core_uV = 1000000;
+			break;
+
+		case 900000 ... 999999:
+			min_core_uV = 1100000;
+			break;
+
+		case 1000000 ... 1099999:
+			min_core_uV = 1200000;
+			break;
+
+		case 1100000 ... 1250000:
+			switch (cpufreq->cpu_speedo_id) {
+			case 0 ... 1:
+			case 4:
+			case 7:
+			case 8:
+				min_core_uV = 1200000;
+				break;
+
+			default:
+				min_core_uV = 1300000;
+				break;
+			}
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		max_core_uV = 1350000;
+	}
+
+	/*
+	 * TODO: CORE and RTC voltages also depend on the status of
+	 * different peripherals in the system. Currently DVFS is
+	 * implemented only for CPU in the kernel, hence limit CORE
+	 * and RTC voltages to the max for now and remove the
+	 * limitations once system-wide DVFS will become available.
+	 */
+	min_core_uV = max_core_uV;
+	min_rtc_uV  = max_rtc_uV;
+
+	err = regulator_set_voltage(cpufreq->reg_core,
+				    min_core_uV, max_core_uV);
+	if (err) {
+		dev_err(cpufreq->dev,
+			"Failed to set CORE voltage (%d %d): %d\n",
+			min_core_uV, max_core_uV, err);
+		return err;
+	}
+
+	if (cpufreq->chip == TEGRA20) {
+		err = regulator_set_voltage(cpufreq->reg_rtc,
+					    min_rtc_uV, max_rtc_uV);
+		if (err) {
+			dev_err(cpufreq->dev,
+				"Failed to set RTC voltage (%d %d): %d\n",
+				min_rtc_uV, max_rtc_uV, err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int tegra_cpu_opp_set_cpu_voltage(struct tegra_cpufreq *cpufreq,
+					 struct dev_pm_opp_supply *supply)
 {
-	struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
 	int ret;
 
-	clk_prepare_enable(cpufreq->cpu_clk);
+	ret = regulator_set_voltage_triplet(cpufreq->reg_cpu,
+					    supply->u_volt_min,
+					    supply->u_volt,
+					    supply->u_volt_max);
+	if (ret)
+		dev_err(cpufreq->dev,
+			"Failed to set CPU voltage (%lu %lu %lu mV): %d\n",
+			supply->u_volt_min, supply->u_volt,
+			supply->u_volt_max, ret);
 
-	/* FIXME: what's the actual transition time? */
-	ret = cpufreq_generic_init(policy, freq_table, 300 * 1000);
-	if (ret) {
-		clk_disable_unprepare(cpufreq->cpu_clk);
-		return ret;
+	return ret;
+}
+
+static void tegra_cpu_deferred_voltage_drop(struct work_struct *work)
+{
+	struct tegra_cpufreq *cpufreq = container_of(work, struct tegra_cpufreq,
+						     work.work);
+	int err;
+
+	err = tegra_cpu_opp_set_cpu_voltage(cpufreq, &cpufreq->supply_cpu);
+	if (err)
+		return;
+
+	err = tegra_cpu_opp_set_core_voltage(cpufreq, &cpufreq->supply_cpu);
+	if (err)
+		return;
+
+	cpufreq->actual_cpu_uV = cpufreq->supply_cpu.u_volt;
+}
+
+static int tegra_cpu_opp_raise_voltage(struct tegra_cpufreq *cpufreq,
+				       struct dev_pm_opp_supply *supply_cpu)
+{
+	int err;
+
+	err = tegra_cpu_opp_set_core_voltage(cpufreq, supply_cpu);
+	if (err)
+		return err;
+
+	err = tegra_cpu_opp_set_cpu_voltage(cpufreq, supply_cpu);
+	if (err)
+		return err;
+
+	cpufreq->actual_cpu_uV = supply_cpu->u_volt;
+
+	return 0;
+}
+
+static void tegra_cpu_opp_schedule_voltage_drop(
+					struct tegra_cpufreq *cpufreq,
+					struct dev_pm_opp_supply *supply_cpu)
+{
+	cpufreq->supply_cpu = *supply_cpu;
+
+	schedule_delayed_work(&cpufreq->work,
+			      msecs_to_jiffies(voltage_drop_interval_ms));
+}
+
+static int tegra_cpu_set_opp(struct dev_pm_set_opp_data *data)
+{
+	struct tegra_cpufreq *cpufreq = cpufreq_get_driver_data();
+	struct dev_pm_opp_supply *supply_cpu;
+	int err;
+
+	cancel_delayed_work_sync(&cpufreq->work);
+
+	supply_cpu = &data->new_opp.supplies[0];
+
+	/* Scaling up? Scale voltage before frequency */
+	if (data->old_opp.rate < data->new_opp.rate) {
+		if (cpufreq->actual_cpu_uV < supply_cpu->u_volt) {
+			err = tegra_cpu_opp_raise_voltage(cpufreq, supply_cpu);
+			if (err)
+				return err;
+		} else {
+			tegra_cpu_opp_schedule_voltage_drop(cpufreq,
+							    supply_cpu);
+		}
 	}
 
-	policy->clk = cpufreq->cpu_clk;
-	policy->suspend_freq = freq_table[0].frequency;
+	err = clk_set_rate(data->clk, data->new_opp.rate);
+	if (err) {
+		dev_err(cpufreq->dev, "Failed to change PLLX clock rate: %d\n",
+			err);
+		return err;
+	}
+
+	if (data->old_opp.rate > data->new_opp.rate)
+		tegra_cpu_opp_schedule_voltage_drop(cpufreq, supply_cpu);
+
 	return 0;
 }
 
-static int tegra_cpu_exit(struct cpufreq_policy *policy)
+static int tegra_cpu_setup_opp(struct tegra_cpufreq *cpufreq)
 {
-	struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
+	const char * const regulators[] = { "cpu" };
+	struct device *dev = cpufreq->cpu_dev;
+	struct opp_table *opp_table;
+	u32 versions[2];
+	int err;
+
+	if (cpufreq->chip == TEGRA20) {
+		versions[0] = BIT(tegra_sku_info.cpu_process_id);
+		versions[1] = BIT(tegra_sku_info.soc_speedo_id);
+	} else {
+		versions[0] = BIT(tegra_sku_info.cpu_process_id);
+		versions[1] = BIT(tegra_sku_info.cpu_speedo_id);
+	}
+
+	cpufreq->opp_table = dev_pm_opp_set_supported_hw(dev, versions, 2);
+	if (IS_ERR(cpufreq->opp_table)) {
+		err = PTR_ERR(cpufreq->opp_table);
+		dev_err(cpufreq->dev,
+			"Failed to setup OPP supported HW: %d\n", err);
+		return err;
+	}
+
+	opp_table = dev_pm_opp_set_regulators(dev, regulators, 1, true);
+	if (IS_ERR(opp_table)) {
+		err = PTR_ERR(opp_table);
+		dev_err(dev,
+			"Failed to setup OPP regulators: %d\n", err);
+		goto err_put_supported_hw;
+	}
+
+	opp_table = dev_pm_opp_register_set_opp_helper(dev, tegra_cpu_set_opp);
+	if (IS_ERR(opp_table)) {
+		err = PTR_ERR(opp_table);
+		dev_err(cpufreq->dev,
+			"Failed to set OPP helper: %d\n", err);
+		goto err_put_regulators;
+	}
+
+	err = dev_pm_opp_of_cpumask_add_table(cpu_possible_mask);
+	if (err) {
+		dev_err(cpufreq->dev, "Failed to add OPP table: %d\n", err);
+		goto err_unregister_opp_helper;
+	}
+
+	err = dev_pm_opp_init_cpufreq_table(dev, &cpufreq->freq_table);
+	if (err) {
+		dev_err(cpufreq->dev,
+			"Failed to initialize OPP table: %d\n", err);
+		goto err_remove_table;
+	}
 
-	clk_disable_unprepare(cpufreq->cpu_clk);
 	return 0;
+
+err_remove_table:
+	dev_pm_opp_of_cpumask_remove_table(cpu_possible_mask);
+
+err_unregister_opp_helper:
+	dev_pm_opp_unregister_set_opp_helper(cpufreq->opp_table);
+
+err_put_regulators:
+	dev_pm_opp_put_regulators(cpufreq->opp_table);
+
+err_put_supported_hw:
+	dev_pm_opp_put_supported_hw(cpufreq->opp_table);
+
+	return err;
 }
 
-static int tegra20_cpufreq_probe(struct platform_device *pdev)
+static void tegra_cpu_release_opp(struct tegra_cpufreq *cpufreq)
+{
+	dev_pm_opp_free_cpufreq_table(cpufreq->cpu_dev, &cpufreq->freq_table);
+	dev_pm_opp_of_cpumask_remove_table(cpu_possible_mask);
+	dev_pm_opp_unregister_set_opp_helper(cpufreq->opp_table);
+	dev_pm_opp_put_regulators(cpufreq->opp_table);
+	dev_pm_opp_put_supported_hw(cpufreq->opp_table);
+}
+
+static int tegra_cpu_init_clocks(struct tegra_cpufreq *cpufreq)
+{
+	unsigned long intermediate_rate;
+	int ret;
+
+	ret = clk_rate_exclusive_get(cpufreq->intermediate_clk);
+	if (ret) {
+		dev_err(cpufreq->dev,
+			"Failed to make intermediate clock exclusive: %d\n",
+			ret);
+		goto err_exclusive_put_intermediate;
+	}
+
+	ret = clk_set_parent(cpufreq->cpu_clk, cpufreq->intermediate_clk);
+	if (ret) {
+		dev_err(cpufreq->dev,
+			"Failed to switch CPU to intermediate clock: %d\n",
+			ret);
+		goto err_exclusive_put_intermediate;
+	}
+
+	intermediate_rate = clk_get_rate(cpufreq->intermediate_clk);
+
+	/*
+	 * The CCLK has its own clock divider, that divider isn't getting
+	 * disabled on clock reparent. Hence set CCLK parent to intermediate
+	 * clock in order to disable the divider if it happens to be enabled,
+	 * otherwise clk_set_rate() has no effect.
+	 */
+	ret = clk_set_rate(cpufreq->cpu_clk, intermediate_rate);
+	if (ret) {
+		dev_err(cpufreq->dev,
+			"Failed to change CPU clock rate: %d\n", ret);
+		goto err_exclusive_put_intermediate;
+	}
+
+err_exclusive_put_intermediate:
+	clk_rate_exclusive_put(cpufreq->intermediate_clk);
+
+	return ret;
+}
+
+static int tegra_cpu_get_regulators(struct tegra_cpufreq *cpufreq)
 {
-	struct tegra20_cpufreq *cpufreq;
 	int err;
 
-	cpufreq = devm_kzalloc(&pdev->dev, sizeof(*cpufreq), GFP_KERNEL);
-	if (!cpufreq)
-		return -ENOMEM;
+	cpufreq->reg_cpu = regulator_get(cpufreq->cpu_dev, "cpu");
+	if (IS_ERR(cpufreq->reg_cpu)) {
+		err = PTR_ERR(cpufreq->reg_cpu);
+		dev_err(cpufreq->dev,
+			"Failed to get CPU regulator: %d\n", err);
+		return err;
+	}
+
+	cpufreq->reg_core = regulator_get(cpufreq->cpu_dev, "core");
+	if (IS_ERR(cpufreq->reg_core)) {
+		err = PTR_ERR(cpufreq->reg_core);
+		dev_err(cpufreq->dev,
+			"Failed to get CORE regulator: %d\n", err);
+		goto err_reg_cpu_put;
+	}
+
+	if (cpufreq->chip == TEGRA20) {
+		cpufreq->reg_rtc = regulator_get(cpufreq->cpu_dev, "rtc");
+		if (IS_ERR(cpufreq->reg_rtc)) {
+			err = PTR_ERR(cpufreq->reg_rtc);
+			dev_err(cpufreq->dev,
+				"Failed to get RTC regulator: %d\n", err);
+			goto err_reg_core_put;
+		}
+	}
+
+	return 0;
+
+err_reg_core_put:
+	regulator_put(cpufreq->reg_core);
+
+err_reg_cpu_put:
+	regulator_put(cpufreq->reg_cpu);
 
-	cpufreq->cpu_clk = clk_get_sys(NULL, "cclk");
-	if (IS_ERR(cpufreq->cpu_clk))
-		return PTR_ERR(cpufreq->cpu_clk);
+	return err;
+}
+
+static void tegra_cpu_put_regulators(struct tegra_cpufreq *cpufreq)
+{
+	if (cpufreq->chip == TEGRA20)
+		regulator_put(cpufreq->reg_rtc);
+
+	regulator_put(cpufreq->reg_core);
+	regulator_put(cpufreq->reg_cpu);
+}
+
+static int tegra_cpu_enable_regulators(struct tegra_cpufreq *cpufreq)
+{
+	int err;
+
+	if (cpufreq->chip == TEGRA20) {
+		err = regulator_enable(cpufreq->reg_rtc);
+		if (err) {
+			dev_err(cpufreq->dev,
+				"Failed to enable RTC regulator: %d\n", err);
+			return err;
+		}
+	}
+
+	err = regulator_enable(cpufreq->reg_core);
+	if (err) {
+		dev_err(cpufreq->dev,
+			"Failed to enable CORE regulator: %d\n", err);
+		goto err_reg_rtc_disable;
+	}
+
+	err = regulator_enable(cpufreq->reg_cpu);
+	if (err) {
+		dev_err(cpufreq->dev,
+			"Failed to enable CPU regulator: %d\n", err);
+		goto err_reg_core_disable;
+	}
+
+	return 0;
+
+err_reg_rtc_disable:
+	if (cpufreq->chip == TEGRA20)
+		regulator_put(cpufreq->reg_rtc);
 
-	cpufreq->pll_x_clk = clk_get_sys(NULL, "pll_x");
+err_reg_core_disable:
+	regulator_put(cpufreq->reg_core);
+
+	return err;
+}
+
+static void tegra_cpu_disable_regulators(struct tegra_cpufreq *cpufreq)
+{
+	regulator_disable(cpufreq->reg_cpu);
+	regulator_disable(cpufreq->reg_core);
+
+	if (cpufreq->chip == TEGRA20)
+		regulator_disable(cpufreq->reg_rtc);
+}
+
+static int tegra_cpu_get_clocks(struct tegra_cpufreq *cpufreq)
+{
+	int err;
+
+	cpufreq->cpu_clk = clk_get(cpufreq->cpu_dev, "cclk");
+	if (IS_ERR(cpufreq->cpu_clk)) {
+		err = PTR_ERR(cpufreq->cpu_clk);
+		dev_err(cpufreq->dev, "Failed to get CPU clock: %d\n", err);
+		dev_err(cpufreq->dev, "Please update your device tree\n");
+		return err;
+	}
+
+	cpufreq->pll_x_clk = clk_get(cpufreq->cpu_dev, "pll_x");
 	if (IS_ERR(cpufreq->pll_x_clk)) {
 		err = PTR_ERR(cpufreq->pll_x_clk);
-		goto put_cpu;
+		dev_err(cpufreq->dev, "Failed to get PLLX clock: %d\n", err);
+		goto err_clk_cpu_put;
+	}
+
+	cpufreq->intermediate_clk = clk_get(cpufreq->cpu_dev, "intermediate");
+	if (IS_ERR(cpufreq->intermediate_clk)) {
+		err = PTR_ERR(cpufreq->intermediate_clk);
+		dev_err(cpufreq->dev, "Failed to get intermediate clock: %d\n",
+			err);
+		goto err_clk_pll_x_put;
+	}
+
+	return 0;
+
+err_clk_pll_x_put:
+	clk_put(cpufreq->pll_x_clk);
+
+err_clk_cpu_put:
+	clk_put(cpufreq->cpu_clk);
+
+	return err;
+}
+
+static void tegra_cpu_put_clocks(struct tegra_cpufreq *cpufreq)
+{
+	clk_put(cpufreq->intermediate_clk);
+	clk_put(cpufreq->pll_x_clk);
+	clk_put(cpufreq->cpu_clk);
+}
+
+static int tegra_cpu_enable_clocks(struct tegra_cpufreq *cpufreq)
+{
+	int err;
+
+	err = clk_prepare_enable(cpufreq->cpu_clk);
+	if (err) {
+		dev_err(cpufreq->dev,
+			"Failed to enable CPU clock: %d\n", err);
+		return err;
 	}
 
-	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 = clk_prepare_enable(cpufreq->intermediate_clk);
+	if (err) {
+		dev_err(cpufreq->dev,
+			"Failed to enable intermediate clock: %d\n", err);
+		goto err_clk_cpu_disable;
 	}
 
+	return 0;
+
+err_clk_cpu_disable:
+	clk_disable_unprepare(cpufreq->cpu_clk);
+
+	return err;
+}
+
+static void tegra_cpu_disable_clocks(struct tegra_cpufreq *cpufreq)
+{
+	clk_disable_unprepare(cpufreq->intermediate_clk);
+	clk_disable_unprepare(cpufreq->cpu_clk);
+}
+
+static int tegra_cpu_get_resources(struct tegra_cpufreq *cpufreq)
+{
+	int err;
+
+	err = tegra_cpu_get_clocks(cpufreq);
+	if (err)
+		return err;
+
+	err = tegra_cpu_enable_clocks(cpufreq);
+	if (err)
+		goto err_put_clocks;
+
+	err = tegra_cpu_get_regulators(cpufreq);
+	if (err)
+		goto err_disable_clocks;
+
+	err = tegra_cpu_enable_regulators(cpufreq);
+	if (err)
+		goto err_put_regulators;
+
+	err = tegra_cpu_init_clocks(cpufreq);
+	if (err)
+		goto err_disable_regulators;
+
+	return 0;
+
+err_disable_regulators:
+	tegra_cpu_disable_regulators(cpufreq);
+
+err_put_regulators:
+	tegra_cpu_put_regulators(cpufreq);
+
+err_disable_clocks:
+	tegra_cpu_disable_clocks(cpufreq);
+
+err_put_clocks:
+	tegra_cpu_put_clocks(cpufreq);
+
+	return err;
+}
+
+static void tegra_cpu_release_resources(struct tegra_cpufreq *cpufreq)
+{
+	tegra_cpu_disable_regulators(cpufreq);
+	tegra_cpu_put_regulators(cpufreq);
+	tegra_cpu_disable_clocks(cpufreq);
+	tegra_cpu_put_clocks(cpufreq);
+}
+
+static int tegra_cpu_init(struct cpufreq_policy *policy)
+{
+	struct tegra_cpufreq *cpufreq = cpufreq_get_driver_data();
+	struct device *cpu = cpufreq->cpu_dev;
+	int err;
+
+	err = tegra_cpu_get_resources(cpufreq);
+	if (err)
+		return err;
+
+	err = tegra_cpu_setup_opp(cpufreq);
+	if (err)
+		goto err_release_resources;
+
+	err = cpufreq_generic_init(policy, cpufreq->freq_table,
+				   dev_pm_opp_get_max_clock_latency(cpu));
+	if (err)
+		goto err_release_opp;
+
+	policy->clk = cpufreq->cpu_clk;
+	policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu) / 1000;
+
+	return 0;
+
+err_release_opp:
+	tegra_cpu_release_opp(cpufreq);
+
+err_release_resources:
+	tegra_cpu_release_resources(cpufreq);
+
+	return err;
+}
+
+static int tegra_cpu_exit(struct cpufreq_policy *policy)
+{
+	struct tegra_cpufreq *cpufreq = cpufreq_get_driver_data();
+
+	flush_delayed_work(&cpufreq->work);
+	cpufreq_cooling_unregister(cpufreq->cdev);
+	tegra_cpu_release_opp(cpufreq);
+	tegra_cpu_release_resources(cpufreq);
+
+	return 0;
+}
+
+static void tegra_cpu_ready(struct cpufreq_policy *policy)
+{
+	struct tegra_cpufreq *cpufreq = cpufreq_get_driver_data();
+
+	cpufreq->cdev = of_cpufreq_cooling_register(policy);
+}
+
+static int tegra_cpu_suspend(struct cpufreq_policy *policy)
+{
+	struct tegra_cpufreq *cpufreq = cpufreq_get_driver_data();
+	int err;
+
+	err = cpufreq_generic_suspend(policy);
+	if (err)
+		return err;
+
+	flush_delayed_work(&cpufreq->work);
+
+	return 0;
+}
+
+static int tegra_cpufreq_probe(struct platform_device *pdev)
+{
+	struct tegra_cpufreq *cpufreq;
+	int err;
+
+	cpufreq = devm_kzalloc(&pdev->dev, sizeof(*cpufreq), GFP_KERNEL);
+	if (!cpufreq)
+		return -ENOMEM;
+
 	cpufreq->dev = &pdev->dev;
+	cpufreq->cpu_dev = get_cpu_device(0);
+	cpufreq->cpu_speedo_id = tegra_sku_info.cpu_speedo_id;
+	cpufreq->chip = tegra_get_chip_id();
 	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.ready = tegra_cpu_ready;
 	cpufreq->driver.flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK;
 	cpufreq->driver.verify = cpufreq_generic_frequency_table_verify;
-	cpufreq->driver.suspend = cpufreq_generic_suspend;
+	cpufreq->driver.suspend = tegra_cpu_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");
+	INIT_DELAYED_WORK(&cpufreq->work, tegra_cpu_deferred_voltage_drop);
 
 	err = cpufreq_register_driver(&cpufreq->driver);
 	if (err)
-		goto put_pll_p;
+		return err;
 
 	platform_set_drvdata(pdev, cpufreq);
 
 	return 0;
-
-put_pll_p:
-	clk_put(cpufreq->pll_p_clk);
-put_pll_x:
-	clk_put(cpufreq->pll_x_clk);
-put_cpu:
-	clk_put(cpufreq->cpu_clk);
-
-	return err;
 }
 
-static int tegra20_cpufreq_remove(struct platform_device *pdev)
+static int tegra_cpufreq_remove(struct platform_device *pdev)
 {
-	struct tegra20_cpufreq *cpufreq = platform_get_drvdata(pdev);
+	struct tegra_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,
+static struct platform_driver tegra_cpufreq_driver = {
+	.probe		= tegra_cpufreq_probe,
+	.remove		= tegra_cpufreq_remove,
 	.driver		= {
 		.name	= "tegra20-cpufreq",
 	},
 };
-module_platform_driver(tegra20_cpufreq_driver);
+module_platform_driver(tegra_cpufreq_driver);
+
+module_param(voltage_drop_interval_ms, uint, 0644);
 
 MODULE_ALIAS("platform:tegra20-cpufreq");
 MODULE_AUTHOR("Colin Cross <ccross@android.com>");
+MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
 MODULE_DESCRIPTION("NVIDIA Tegra20 cpufreq driver");
 MODULE_LICENSE("GPL");
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 05/17] ARM: tegra: Create tegra20-cpufreq device on Tegra30
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (3 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 04/17] cpufreq: tegra20: Support OPP, thermal cooling, DVFS and Tegra30 Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 06/17] ARM: dts: tegra20: Add CPU Operating Performance Points Dmitry Osipenko
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Tegra20-cpufreq driver require a platform device in order to be loaded,
instantiate a simple platform device for the driver during of the machines
late initialization. Driver now supports Tegra30 SoC's, hence create the
device on Tegra30 machines.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/mach-tegra/tegra.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 67d8ae60ac67..b559e22eab76 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -111,6 +111,10 @@ static void __init tegra_dt_init_late(void)
 	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
 	    of_machine_is_compatible("nvidia,tegra20"))
 		platform_device_register_simple("tegra20-cpufreq", -1, NULL, 0);
+
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) &&
+	    of_machine_is_compatible("nvidia,tegra30"))
+		platform_device_register_simple("tegra20-cpufreq", -1, NULL, 0);
 }
 
 static const char * const tegra_dt_board_compat[] = {
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 06/17] ARM: dts: tegra20: Add CPU Operating Performance Points
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (4 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 05/17] ARM: tegra: Create tegra20-cpufreq device on Tegra30 Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 07/17] ARM: dts: tegra30: " Dmitry Osipenko
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Add CPU's Operating Performance Points to the device tree, they are used
by the CPUFreq driver and allow to setup thermal throttling for the boards
by linking the cooling device (CPU) with thermal sensors via thermal-zones
description.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20.dtsi | 277 +++++++++++++++++++++++++++++++++
 1 file changed, 277 insertions(+)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 185cd074eeff..51ffb5d2b974 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -859,6 +859,271 @@
 		status = "disabled";
 	};
 
+	cpu0_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@216000000_750 {
+			clock-latency-ns = <2000>;
+			opp-microvolt = <750000 750000 1125000>;
+			opp-supported-hw = <0xFF 0xFFFF>;
+			opp-hz = /bits/ 64 <216000000>;
+			opp-suspend;
+		};
+
+		opp@314000000_750 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <750000 750000 1125000>;
+			opp-supported-hw = <0x03 0x0001>;
+			opp-hz = /bits/ 64 <314000000>;
+		};
+
+		opp@380000000_750 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <750000 750000 1125000>;
+			opp-supported-hw = <0x01 0x0002>;
+			opp-hz = /bits/ 64 <380000000>;
+		};
+
+		opp@389000000_750 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <750000 750000 1125000>;
+			opp-supported-hw = <0x02 0x0002>;
+			opp-hz = /bits/ 64 <389000000>;
+		};
+
+		opp@456000000_825 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <825000 825000 1125000>;
+			opp-supported-hw = <0x03 0x0001>;
+			opp-hz = /bits/ 64 <456000000>;
+		};
+
+		opp@494000000_750 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <750000 750000 1125000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <494000000>;
+		};
+
+		opp@503000000_800 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <800000 800000 1125000>;
+			opp-supported-hw = <0x03 0x0002>;
+			opp-hz = /bits/ 64 <503000000>;
+		};
+
+		opp@598000000_750 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <750000 750000 1125000>;
+			opp-supported-hw = <0x04 0x0002>;
+			opp-hz = /bits/ 64 <598000000>;
+		};
+
+		opp@608000000_900 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <900000 900000 1125000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <608000000>;
+		};
+
+		opp@618000000_900 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <900000 900000 1125000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <618000000>;
+		};
+
+		opp@655000000_850 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <850000 850000 1125000>;
+			opp-supported-hw = <0x03 0x0002>;
+			opp-hz = /bits/ 64 <655000000>;
+		};
+
+		opp@675000000_825 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <825000 825000 1125000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <675000000>;
+		};
+
+		opp@730000000_750 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <750000 750000 1125000>;
+			opp-supported-hw = <0x08 0x0003>;
+			opp-hz = /bits/ 64 <730000000>;
+		};
+
+		opp@750000000_800 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <800000 800000 1125000>;
+			opp-supported-hw = <0x04 0x0002>;
+			opp-hz = /bits/ 64 <750000000>;
+		};
+
+		opp@760000000_775 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <775000 775000 1125000>;
+			opp-supported-hw = <0x08 0x0003>;
+			opp-hz = /bits/ 64 <760000000>;
+		};
+
+		opp@760000000_875 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <875000 875000 1125000>;
+			opp-supported-hw = <0x02 0x0002>;
+			opp-hz = /bits/ 64 <760000000>;
+		};
+
+		opp@760000000_975 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <975000 975000 1125000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <760000000>;
+		};
+
+		opp@770000000_975 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <975000 975000 1125000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <770000000>;
+		};
+
+		opp@798000000_900 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <900000 900000 1125000>;
+			opp-supported-hw = <0x03 0x0002>;
+			opp-hz = /bits/ 64 <798000000>;
+		};
+
+		opp@817000000_875 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <875000 875000 1125000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <817000000>;
+		};
+
+		opp@817000000_1000 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <1000000 1000000 1125000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <817000000>;
+		};
+
+		opp@827000000_1000 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <1000000 1000000 1125000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <827000000>;
+		};
+
+		opp@845000000_800 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <800000 800000 1125000>;
+			opp-supported-hw = <0x08 0x0003>;
+			opp-hz = /bits/ 64 <845000000>;
+		};
+
+		opp@893000000_850 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <850000 850000 1125000>;
+			opp-supported-hw = <0x04 0x0002>;
+			opp-hz = /bits/ 64 <893000000>;
+		};
+
+		opp@902000000_950 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <950000 950000 1125000>;
+			opp-supported-hw = <0x01 0x0002>;
+			opp-hz = /bits/ 64 <902000000>;
+		};
+
+		opp@912000000_1050 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <1050000 1050000 1125000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <912000000>;
+		};
+
+		opp@922000000_925 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <925000 925000 1125000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <922000000>;
+		};
+
+		opp@922000000_1050 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <1050000 1050000 1125000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <922000000>;
+		};
+
+		opp@940000000_850 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <850000 850000 1125000>;
+			opp-supported-hw = <0x08 0x0003>;
+			opp-hz = /bits/ 64 <940000000>;
+		};
+
+		opp@950000000_950 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <950000 950000 1125000>;
+			opp-supported-hw = <0x02 0x0002>;
+			opp-hz = /bits/ 64 <950000000>;
+		};
+
+		opp@960000000_1000 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <1000000 1000000 1125000>;
+			opp-supported-hw = <0x01 0x0002>;
+			opp-hz = /bits/ 64 <960000000>;
+		};
+
+		opp@1000000000_875 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <875000 875000 1125000>;
+			opp-supported-hw = <0x08 0x0003>;
+			opp-hz = /bits/ 64 <1000000000>;
+		};
+
+		opp@1000000000_900 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <900000 900000 1125000>;
+			opp-supported-hw = <0x04 0x0002>;
+			opp-hz = /bits/ 64 <1000000000>;
+		};
+
+		opp@1000000000_975 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <975000 975000 1125000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <1000000000>;
+		};
+
+		opp@1000000000_1000 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <1000000 1000000 1125000>;
+			opp-supported-hw = <0x02 0x0002>;
+			opp-hz = /bits/ 64 <1000000000>;
+		};
+
+		opp@1000000000_1025 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <1025000 1025000 1125000>;
+			opp-supported-hw = <0x01 0x0002>;
+			opp-hz = /bits/ 64 <1000000000>;
+		};
+
+		opp@1000000000_1100 {
+			clock-latency-ns = <125000>;
+			opp-microvolt = <1100000 1100000 1125000>;
+			opp-supported-hw = <0x03 0x0001>;
+			opp-hz = /bits/ 64 <1000000000>;
+		};
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -867,12 +1132,24 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
+			clocks = <&tegra_car TEGRA20_CLK_PLL_X>,
+				 <&tegra_car TEGRA20_CLK_PLL_P>,
+				 <&tegra_car TEGRA20_CLK_CCLK>;
+			clock-names = "pll_x", "intermediate", "cclk";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>;
 		};
 
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
+			clocks = <&tegra_car TEGRA20_CLK_PLL_X>,
+				 <&tegra_car TEGRA20_CLK_PLL_P>,
+				 <&tegra_car TEGRA20_CLK_CCLK>;
+			clock-names = "pll_x", "intermediate", "cclk";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>;
 		};
 	};
 
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 07/17] ARM: dts: tegra30: Add CPU Operating Performance Points
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (5 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 06/17] ARM: dts: tegra20: Add CPU Operating Performance Points Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 08/17] ARM: dts: tegra20: colibri: Setup voltage regulators for DVFS Dmitry Osipenko
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Add CPU's Operating Performance Points to the device tree, they are used
by the CPUFreq driver and allow to setup thermal throttling for the boards
by linking the cooling device (CPU) with thermal sensors via thermal-zones
description.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra30.dtsi | 688 +++++++++++++++++++++++++++++++++
 1 file changed, 688 insertions(+)

diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 790d3fa7e6d2..0aefc8d9efab 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -980,6 +980,670 @@
 		status = "disabled";
 	};
 
+	cpu0_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@408000000_800 {
+			clock-latency-ns = <2000>;
+			opp-microvolt = <800000 800000 1250000>;
+			opp-supported-hw = <0xFF 0xFFFF>;
+			opp-hz = /bits/ 64 <408000000>;
+			opp-suspend;
+		};
+
+		opp@460000000_800 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <800000 800000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <460000000>;
+		};
+
+		opp@480000000_800 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <800000 800000 1250000>;
+			opp-supported-hw = <0x02 0x019E>;
+			opp-hz = /bits/ 64 <480000000>;
+		};
+
+		opp@520000000_800 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <800000 800000 1250000>;
+			opp-supported-hw = <0x04 0x019E>;
+			opp-hz = /bits/ 64 <520000000>;
+		};
+
+		opp@550000000_800 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <800000 800000 1250000>;
+			opp-supported-hw = <0x18 0x31FE>;
+			opp-hz = /bits/ 64 <550000000>;
+		};
+
+		opp@550000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <550000000>;
+		};
+
+		opp@600000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x1F 0x0800>;
+			opp-hz = /bits/ 64 <600000000>;
+		};
+
+		opp@650000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x02 0x019E>;
+			opp-hz = /bits/ 64 <650000000>;
+		};
+
+		opp@680000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <680000000>;
+		};
+
+		opp@684000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <684000000>;
+		};
+
+		opp@700000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x04 0x019E>;
+			opp-hz = /bits/ 64 <700000000>;
+		};
+
+		opp@770000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x18 0x31FE>;
+			opp-hz = /bits/ 64 <770000000>;
+		};
+
+		opp@780000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x02 0x019E>;
+			opp-hz = /bits/ 64 <780000000>;
+		};
+
+		opp@807000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <807000000>;
+		};
+
+		opp@817000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <817000000>;
+		};
+
+		opp@820000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <820000000>;
+		};
+
+		opp@860000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x04 0x019E>;
+			opp-hz = /bits/ 64 <860000000>;
+		};
+
+		opp@883000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <883000000>;
+		};
+
+		opp@900000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x1F 0x0400>;
+			opp-hz = /bits/ 64 <900000000>;
+		};
+
+		opp@900000000_912 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <912000 912000 1250000>;
+			opp-supported-hw = <0x1F 0x0200>;
+			opp-hz = /bits/ 64 <900000000>;
+		};
+
+		opp@910000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x08 0x31FE>;
+			opp-hz = /bits/ 64 <910000000>;
+		};
+
+		opp@931000000_850 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <850000 850000 1250000>;
+			opp-supported-hw = <0x08 0x0001>;
+			opp-hz = /bits/ 64 <931000000>;
+		};
+
+		opp@940000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x10 0x31E0>;
+			opp-hz = /bits/ 64 <940000000>;
+		};
+
+		opp@948000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <948000000>;
+		};
+
+		opp@970000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <970000000>;
+		};
+
+		opp@990000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x02 0x019E>;
+			opp-hz = /bits/ 64 <990000000>;
+		};
+
+		opp@1026000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <1026000000>;
+		};
+
+		opp@1039000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <1039000000>;
+		};
+
+		opp@1040000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x02 0x019E>;
+			opp-hz = /bits/ 64 <1040000000>;
+		};
+
+		opp@1040000000_1025 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1025000 1025000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <1040000000>;
+		};
+
+		opp@1050000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x04 0x019E>;
+			opp-hz = /bits/ 64 <1050000000>;
+		};
+
+		opp@1080000000_1050 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1050000 1050000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <1080000000>;
+		};
+
+		opp@1100000000_1025 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1025000 1025000 1250000>;
+			opp-supported-hw = <0x02 0x019E>;
+			opp-hz = /bits/ 64 <1100000000>;
+		};
+
+		opp@1102000000_900 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <900000 900000 1250000>;
+			opp-supported-hw = <0x08 0x0001>;
+			opp-hz = /bits/ 64 <1102000000>;
+		};
+
+		opp@1102000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <1102000000>;
+		};
+
+		opp@1117000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <1117000000>;
+		};
+
+		opp@1149000000_1025 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1025000 1025000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <1149000000>;
+		};
+
+		opp@1150000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x08 0x31FE>;
+			opp-hz = /bits/ 64 <1150000000>;
+		};
+
+		opp@1150000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x04 0x019E>;
+			opp-hz = /bits/ 64 <1150000000>;
+		};
+
+		opp@1150000000_1075 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1075000 1075000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <1150000000>;
+		};
+
+		opp@1160000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x10 0x31E0>;
+			opp-hz = /bits/ 64 <1160000000>;
+		};
+
+		opp@1171000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <1171000000>;
+		};
+
+		opp@1178000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <1178000000>;
+		};
+
+		opp@1187000000_1050 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1050000 1050000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <1187000000>;
+		};
+
+		opp@1200000000_1025 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1025000 1025000 1250000>;
+			opp-supported-hw = <0x04 0x019E>;
+			opp-hz = /bits/ 64 <1200000000>;
+		};
+
+		opp@1200000000_1050 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1050000 1050000 1250000>;
+			opp-supported-hw = <0x02 0x019E>;
+			opp-hz = /bits/ 64 <1200000000>;
+		};
+
+		opp@1200000000_1100 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1100000 1100000 1250000>;
+			opp-supported-hw = <0x01 0x0192>;
+			opp-hz = /bits/ 64 <1200000000>;
+		};
+
+		opp@1206000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x04 0x0001>;
+			opp-hz = /bits/ 64 <1206000000>;
+		};
+
+		opp@1206000000_1025 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1025000 1025000 1250000>;
+			opp-supported-hw = <0x02 0x0001>;
+			opp-hz = /bits/ 64 <1206000000>;
+		};
+
+		opp@1216000000_975 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <975000 975000 1250000>;
+			opp-supported-hw = <0x08 0x0001>;
+			opp-hz = /bits/ 64 <1216000000>;
+		};
+
+		opp@1225000000_1075 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1075000 1075000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <1225000000>;
+		};
+
+		opp@1230000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x08 0x31FE>;
+			opp-hz = /bits/ 64 <1230000000>;
+		};
+
+		opp@1240000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x10 0x3060>;
+			opp-hz = /bits/ 64 <1240000000>;
+		};
+
+		opp@1240000000_1125 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1125000 1125000 1250000>;
+			opp-supported-hw = <0x01 0x0010>;
+			opp-hz = /bits/ 64 <1240000000>;
+		};
+
+		opp@1250000000_1075 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1075000 1075000 1250000>;
+			opp-supported-hw = <0x02 0x001C>;
+			opp-hz = /bits/ 64 <1250000000>;
+		};
+
+		opp@1280000000_1025 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1025000 1025000 1250000>;
+			opp-supported-hw = <0x18 0x307C>;
+			opp-hz = /bits/ 64 <1280000000>;
+		};
+
+		opp@1280000000_1050 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1050000 1050000 1250000>;
+			opp-supported-hw = <0x04 0x001C>;
+			opp-hz = /bits/ 64 <1280000000>;
+		};
+
+		opp@1280000000_1125 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1125000 1125000 1250000>;
+			opp-supported-hw = <0x01 0x0182>;
+			opp-hz = /bits/ 64 <1280000000>;
+		};
+
+		opp@1280000000_1150 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1150000 1150000 1250000>;
+			opp-supported-hw = <0x01 0x0010>;
+			opp-hz = /bits/ 64 <1280000000>;
+		};
+
+		opp@1282000000_1100 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1100000 1100000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <1282000000>;
+		};
+
+		opp@1300000000_1000 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1000000 1000000 1250000>;
+			opp-supported-hw = <0x18 0x0181>;
+			opp-hz = /bits/ 64 <1300000000>;
+		};
+
+		opp@1300000000_1025 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1025000 1025000 1250000>;
+			opp-supported-hw = <0x0C 0x0183>;
+			opp-hz = /bits/ 64 <1300000000>;
+		};
+
+		opp@1300000000_1050 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1050000 1050000 1250000>;
+			opp-supported-hw = <0x0E 0x018F>;
+			opp-hz = /bits/ 64 <1300000000>;
+		};
+
+		opp@1300000000_1075 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1075000 1075000 1250000>;
+			opp-supported-hw = <0x06 0x019E>;
+			opp-hz = /bits/ 64 <1300000000>;
+		};
+
+		opp@1300000000_1100 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1100000 1100000 1250000>;
+			opp-supported-hw = <0x02 0x001C>;
+			opp-hz = /bits/ 64 <1300000000>;
+		};
+
+		opp@1300000000_1125 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1125000 1125000 1250000>;
+			opp-supported-hw = <0x01 0x0001>;
+			opp-hz = /bits/ 64 <1300000000>;
+		};
+
+		opp@1300000000_1150 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1150000 1150000 1250000>;
+			opp-supported-hw = <0x01 0x0182>;
+			opp-hz = /bits/ 64 <1300000000>;
+		};
+
+		opp@1320000000_1175 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1175000 1175000 1250000>;
+			opp-supported-hw = <0x01 0x0010>;
+			opp-hz = /bits/ 64 <1320000000>;
+		};
+
+		opp@1330000000_1050 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1050000 1050000 1250000>;
+			opp-supported-hw = <0x08 0x3070>;
+			opp-hz = /bits/ 64 <1330000000>;
+		};
+
+		opp@1330000000_1125 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1125000 1125000 1250000>;
+			opp-supported-hw = <0x02 0x001C>;
+			opp-hz = /bits/ 64 <1330000000>;
+		};
+
+		opp@1340000000_1100 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1100000 1100000 1250000>;
+			opp-supported-hw = <0x04 0x0010>;
+			opp-hz = /bits/ 64 <1340000000>;
+		};
+
+		opp@1350000000_1075 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1075000 1075000 1250000>;
+			opp-supported-hw = <0x08 0x000C>;
+			opp-hz = /bits/ 64 <1350000000>;
+		};
+
+		opp@1350000000_1100 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1100000 1100000 1250000>;
+			opp-supported-hw = <0x04 0x000C>;
+			opp-hz = /bits/ 64 <1350000000>;
+		};
+
+		opp@1360000000_1050 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1050000 1050000 1250000>;
+			opp-supported-hw = <0x10 0x3060>;
+			opp-hz = /bits/ 64 <1360000000>;
+		};
+
+		opp@1360000000_1150 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1150000 1150000 1250000>;
+			opp-supported-hw = <0x02 0x0010>;
+			opp-hz = /bits/ 64 <1360000000>;
+		};
+
+		opp@1360000000_1200 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1200000 1200000 1250000>;
+			opp-supported-hw = <0x01 0x0010>;
+			opp-hz = /bits/ 64 <1360000000>;
+		};
+
+		opp@1370000000_1075 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1075000 1075000 1250000>;
+			opp-supported-hw = <0x08 0x3070>;
+			opp-hz = /bits/ 64 <1370000000>;
+		};
+
+		opp@1380000000_1125 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1125000 1125000 1250000>;
+			opp-supported-hw = <0x04 0x0010>;
+			opp-hz = /bits/ 64 <1380000000>;
+		};
+
+		opp@1390000000_1075 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1075000 1075000 1250000>;
+			opp-supported-hw = <0x10 0x3060>;
+			opp-hz = /bits/ 64 <1390000000>;
+		};
+
+		opp@1400000000_1100 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1100000 1100000 1250000>;
+			opp-supported-hw = <0x08 0x307C>;
+			opp-hz = /bits/ 64 <1400000000>;
+		};
+
+		opp@1400000000_1125 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1125000 1125000 1250000>;
+			opp-supported-hw = <0x04 0x000C>;
+			opp-hz = /bits/ 64 <1400000000>;
+		};
+
+		opp@1400000000_1150 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1150000 1150000 1250000>;
+			opp-supported-hw = <0x02 0x000C>;
+			opp-hz = /bits/ 64 <1400000000>;
+		};
+
+		opp@1400000000_1175 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1175000 1175000 1250000>;
+			opp-supported-hw = <0x02 0x0010>;
+			opp-hz = /bits/ 64 <1400000000>;
+		};
+
+		opp@1470000000_1100 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1100000 1100000 1250000>;
+			opp-supported-hw = <0x10 0x3060>;
+			opp-hz = /bits/ 64 <1470000000>;
+		};
+
+		opp@1470000000_1125 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1125000 1125000 1250000>;
+			opp-supported-hw = <0x08 0x3060>;
+			opp-hz = /bits/ 64 <1470000000>;
+		};
+
+		opp@1500000000_1125 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1125000 1125000 1250000>;
+			opp-supported-hw = <0x18 0x3070>;
+			opp-hz = /bits/ 64 <1500000000>;
+		};
+
+		opp@1500000000_1150 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1150000 1150000 1250000>;
+			opp-supported-hw = <0x0C 0x3070>;
+			opp-hz = /bits/ 64 <1500000000>;
+		};
+
+		opp@1500000000_1200 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1200000 1200000 1250000>;
+			opp-supported-hw = <0x02 0x0010>;
+			opp-hz = /bits/ 64 <1500000000>;
+		};
+
+		opp@1500000000_1237 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1237000 1237000 1250000>;
+			opp-supported-hw = <0x01 0x0010>;
+			opp-hz = /bits/ 64 <1500000000>;
+		};
+
+		opp@1520000000_1150 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1150000 1150000 1250000>;
+			opp-supported-hw = <0x10 0x3060>;
+			opp-hz = /bits/ 64 <1520000000>;
+		};
+
+		opp@1540000000_1200 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1200000 1200000 1250000>;
+			opp-supported-hw = <0x08 0x3060>;
+			opp-hz = /bits/ 64 <1540000000>;
+		};
+
+		opp@1590000000_1200 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1200000 1200000 1250000>;
+			opp-supported-hw = <0x10 0x3060>;
+			opp-hz = /bits/ 64 <1590000000>;
+		};
+
+		opp@1700000000_1212 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1212000 1212000 1250000>;
+			opp-supported-hw = <0x10 0x3060>;
+			opp-hz = /bits/ 64 <1700000000>;
+		};
+
+		opp@1700000000_1237 {
+			clock-latency-ns = <50000>;
+			opp-microvolt = <1237000 1237000 1250000>;
+			opp-supported-hw = <0x08 0x3060>;
+			opp-hz = /bits/ 64 <1700000000>;
+		};
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -988,24 +1652,48 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
+			clocks = <&tegra_car TEGRA30_CLK_PLL_X>,
+				 <&tegra_car TEGRA30_CLK_PLL_P>,
+				 <&tegra_car TEGRA30_CLK_CCLK_G>;
+			clock-names = "pll_x", "intermediate", "cclk";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>;
 		};
 
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
+			clocks = <&tegra_car TEGRA30_CLK_PLL_X>,
+				 <&tegra_car TEGRA30_CLK_PLL_P>,
+				 <&tegra_car TEGRA30_CLK_CCLK_G>;
+			clock-names = "pll_x", "intermediate", "cclk";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>;
 		};
 
 		cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <2>;
+			clocks = <&tegra_car TEGRA30_CLK_PLL_X>,
+				 <&tegra_car TEGRA30_CLK_PLL_P>,
+				 <&tegra_car TEGRA30_CLK_CCLK_G>;
+			clock-names = "pll_x", "intermediate", "cclk";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>;
 		};
 
 		cpu@3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <3>;
+			clocks = <&tegra_car TEGRA30_CLK_PLL_X>,
+				 <&tegra_car TEGRA30_CLK_PLL_P>,
+				 <&tegra_car TEGRA30_CLK_CCLK_G>;
+			clock-names = "pll_x", "intermediate", "cclk";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>;
 		};
 	};
 
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 08/17] ARM: dts: tegra20: colibri: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (6 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 07/17] ARM: dts: tegra30: " Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 09/17] ARM: dts: tegra20: harmony: " Dmitry Osipenko
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20-colibri.dtsi | 31 ++++++++++++++++++--------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-colibri.dtsi b/arch/arm/boot/dts/tegra20-colibri.dtsi
index 6162d193e12c..5b3155dbf47a 100644
--- a/arch/arm/boot/dts/tegra20-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra20-colibri.dtsi
@@ -495,17 +495,19 @@
 					regulator-always-on;
 				};
 
-				sm0 {
+				core_vdd_reg: sm0 {
 					regulator-name = "VDD_CORE_1.2V";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&rtc_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
 					regulator-always-on;
 				};
 
-				sm1 {
+				cpu_vdd_reg: sm1 {
 					regulator-name = "VDD_CPU_1.0V";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <1125000>;
 					regulator-always-on;
 				};
 
@@ -530,10 +532,13 @@
 					regulator-always-on;
 				};
 
-				ldo2 {
+				rtc_vdd_reg: ldo2 {
 					regulator-name = "VDD_RTC_1.2V";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
+					regulator-always-on;
 				};
 
 				/* LDO3 is not connected to anything */
@@ -740,6 +745,14 @@
 			 <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&cpu_vdd_reg>;
+			core-supply = <&core_vdd_reg>;
+			rtc-supply = <&rtc_vdd_reg>;
+		};
+	};
 };
 
 &gpio {
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 09/17] ARM: dts: tegra20: harmony: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (7 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 08/17] ARM: dts: tegra20: colibri: Setup voltage regulators for DVFS Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-22 15:33   ` Stephen Warren
  2018-10-21 20:54 ` [RFC PATCH v2 10/17] ARM: dts: tegra20: paz00: " Dmitry Osipenko
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20-harmony.dts | 31 +++++++++++++++++++--------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index 1d96d92b72a7..9d720743fd4e 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -339,17 +339,19 @@
 					regulator-always-on;
 				};
 
-				sm0 {
+				core_vdd_reg: sm0 {
 					regulator-name = "vdd_sm0,vdd_core";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&rtc_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
 					regulator-always-on;
 				};
 
-				sm1 {
+				cpu_vdd_reg: sm1 {
 					regulator-name = "vdd_sm1,vdd_cpu";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <1125000>;
 					regulator-always-on;
 				};
 
@@ -373,10 +375,13 @@
 					regulator-always-on;
 				};
 
-				ldo2 {
+				rtc_vdd_reg: ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
+					regulator-always-on;
 				};
 
 				ldo3 {
@@ -779,4 +784,12 @@
 			 <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&cpu_vdd_reg>;
+			core-supply = <&core_vdd_reg>;
+			rtc-supply = <&rtc_vdd_reg>;
+		};
+	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 10/17] ARM: dts: tegra20: paz00: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (8 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 09/17] ARM: dts: tegra20: harmony: " Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 11/17] ARM: dts: tegra20: seaboard: " Dmitry Osipenko
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20-paz00.dts | 31 ++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index 8861e0976e37..51a09ae99f3a 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -337,17 +337,19 @@
 					regulator-always-on;
 				};
 
-				sm0 {
+				core_vdd_reg: sm0 {
 					regulator-name = "+1.2vs_sm0,vdd_core";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&rtc_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
 					regulator-always-on;
 				};
 
-				sm1 {
+				cpu_vdd_reg: sm1 {
 					regulator-name = "+1.0vs_sm1,vdd_cpu";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <1125000>;
 					regulator-always-on;
 				};
 
@@ -367,10 +369,13 @@
 					regulator-always-on;
 				};
 
-				ldo2 {
+				rtc_vdd_reg: ldo2 {
 					regulator-name = "+1.2vs_ldo2,vdd_rtc";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
+					regulator-always-on;
 				};
 
 				ldo3 {
@@ -603,4 +608,12 @@
 			 <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&cpu_vdd_reg>;
+			core-supply = <&core_vdd_reg>;
+			rtc-supply = <&rtc_vdd_reg>;
+		};
+	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 11/17] ARM: dts: tegra20: seaboard: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (9 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 10/17] ARM: dts: tegra20: paz00: " Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 12/17] ARM: dts: tegra20: tamonten: " Dmitry Osipenko
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20-seaboard.dts | 27 +++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index f91441683aad..85bf7e89ebbe 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -444,16 +444,18 @@
 					regulator-always-on;
 				};
 
-				sm0 {
+				core_vdd_reg: sm0 {
 					regulator-name = "vdd_sm0,vdd_core";
-					regulator-min-microvolt = <1300000>;
+					regulator-min-microvolt = <1000000>;
 					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&rtc_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
 					regulator-always-on;
 				};
 
-				sm1 {
+				cpu_vdd_reg: sm1 {
 					regulator-name = "vdd_sm1,vdd_cpu";
-					regulator-min-microvolt = <1125000>;
+					regulator-min-microvolt = <750000>;
 					regulator-max-microvolt = <1125000>;
 					regulator-always-on;
 				};
@@ -474,10 +476,13 @@
 					regulator-always-on;
 				};
 
-				ldo2 {
+				rtc_vdd_reg: ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
+					regulator-always-on;
 				};
 
 				ldo3 {
@@ -938,4 +943,12 @@
 			 <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&cpu_vdd_reg>;
+			core-supply = <&core_vdd_reg>;
+			rtc-supply = <&rtc_vdd_reg>;
+		};
+	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 12/17] ARM: dts: tegra20: tamonten: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (10 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 11/17] ARM: dts: tegra20: seaboard: " Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 13/17] ARM: dts: tegra20: ventana: " Dmitry Osipenko
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20-tamonten.dtsi | 31 ++++++++++++++++++-------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
index 20137fc578b1..e9db60f4c317 100644
--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -357,17 +357,19 @@
 					regulator-always-on;
 				};
 
-				sm0 {
+				core_vdd_reg: sm0 {
 					regulator-name = "vdd_sys_sm0,vdd_core";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&rtc_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
 					regulator-always-on;
 				};
 
-				sm1 {
+				cpu_vdd_reg: sm1 {
 					regulator-name = "vdd_sys_sm1,vdd_cpu";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <1125000>;
 					regulator-always-on;
 				};
 
@@ -391,10 +393,13 @@
 					regulator-always-on;
 				};
 
-				ldo2 {
+				rtc_vdd_reg: ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
+					regulator-always-on;
 				};
 
 				ldo3 {
@@ -531,4 +536,12 @@
 			enable-active-high;
 		};
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&cpu_vdd_reg>;
+			core-supply = <&core_vdd_reg>;
+			rtc-supply = <&rtc_vdd_reg>;
+		};
+	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 13/17] ARM: dts: tegra20: ventana: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (11 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 12/17] ARM: dts: tegra20: tamonten: " Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 14/17] ARM: dts: tegra30: apalis: " Dmitry Osipenko
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20-ventana.dts | 31 +++++++++++++++++++--------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index f44551e2d9d0..ef9cdd7335ae 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -419,17 +419,19 @@
 					regulator-always-on;
 				};
 
-				sm0 {
+				core_vdd_reg: sm0 {
 					regulator-name = "vdd_sm0,vdd_core";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&rtc_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
 					regulator-always-on;
 				};
 
-				sm1 {
+				cpu_vdd_reg: sm1 {
 					regulator-name = "vdd_sm1,vdd_cpu";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <1125000>;
 					regulator-always-on;
 				};
 
@@ -449,10 +451,13 @@
 					regulator-always-on;
 				};
 
-				ldo2 {
+				rtc_vdd_reg: ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <150000>;
+					regulator-always-on;
 				};
 
 				ldo3 {
@@ -704,4 +709,12 @@
 			 <&tegra_car TEGRA20_CLK_CDEV1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&cpu_vdd_reg>;
+			core-supply = <&core_vdd_reg>;
+			rtc-supply = <&rtc_vdd_reg>;
+		};
+	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 14/17] ARM: dts: tegra30: apalis: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (12 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 13/17] ARM: dts: tegra20: ventana: " Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:54 ` [RFC PATCH v2 15/17] ARM: dts: tegra30: beaver: " Dmitry Osipenko
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra30-apalis.dtsi | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi
index 7f112f192fe9..1ca9bec8380f 100644
--- a/arch/arm/boot/dts/tegra30-apalis.dtsi
+++ b/arch/arm/boot/dts/tegra30-apalis.dtsi
@@ -890,8 +890,11 @@
 
 				vddctrl_reg: vddctrl {
 					regulator-name = "+V1.0_VDD_CPU";
-					regulator-min-microvolt = <1150000>;
-					regulator-max-microvolt = <1150000>;
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <300000>;
+					regulator-max-step-microvolt = <100000>;
 					regulator-always-on;
 				};
 
@@ -1013,13 +1016,16 @@
 		};
 
 		/* SW: +V1.2_VDD_CORE */
-		regulator@60 {
+		core_vdd_reg: regulator@60 {
 			compatible = "ti,tps62362";
 			reg = <0x60>;
 
 			regulator-name = "tps62362-vout";
 			regulator-min-microvolt = <900000>;
 			regulator-max-microvolt = <1400000>;
+			regulator-coupled-with = <&vddctrl_reg>;
+			regulator-coupled-max-spread = <300000>;
+			regulator-max-step-microvolt = <100000>;
 			regulator-boot-on;
 			regulator-always-on;
 			ti,vsel0-state-low;
@@ -1168,4 +1174,11 @@
 			 <&tegra_car TEGRA30_CLK_EXTERN1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&vddctrl_reg>;
+			core-supply = <&core_vdd_reg>;
+		};
+	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 15/17] ARM: dts: tegra30: beaver: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (13 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 14/17] ARM: dts: tegra30: apalis: " Dmitry Osipenko
@ 2018-10-21 20:54 ` Dmitry Osipenko
  2018-10-21 20:55 ` [RFC PATCH v2 16/17] ARM: dts: tegra30: cardhu: " Dmitry Osipenko
  2018-10-21 20:55 ` [RFC PATCH v2 17/17] ARM: dts: tegra30: colibri: " Dmitry Osipenko
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:54 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra30-beaver.dts | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts
index b0d40ac8ac6e..39941489d005 100644
--- a/arch/arm/boot/dts/tegra30-beaver.dts
+++ b/arch/arm/boot/dts/tegra30-beaver.dts
@@ -1806,8 +1806,11 @@
 
 				vddctrl_reg: vddctrl {
 					regulator-name = "vdd_cpu,vdd_sys";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <300000>;
+					regulator-max-step-microvolt = <100000>;
 					regulator-always-on;
 				};
 
@@ -1868,13 +1871,16 @@
 			};
 		};
 
-		tps62361@60 {
+		core_vdd_reg: tps62361@60 {
 			compatible = "ti,tps62361";
 			reg = <0x60>;
 
 			regulator-name = "tps62361-vout";
 			regulator-min-microvolt = <500000>;
 			regulator-max-microvolt = <1500000>;
+			regulator-coupled-with = <&vddctrl_reg>;
+			regulator-coupled-max-spread = <300000>;
+			regulator-max-step-microvolt = <100000>;
 			regulator-boot-on;
 			regulator-always-on;
 			ti,vsel0-state-high;
@@ -2114,4 +2120,11 @@
 			 <&tegra_car TEGRA30_CLK_EXTERN1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&vddctrl_reg>;
+			core-supply = <&core_vdd_reg>;
+		};
+	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 16/17] ARM: dts: tegra30: cardhu: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (14 preceding siblings ...)
  2018-10-21 20:54 ` [RFC PATCH v2 15/17] ARM: dts: tegra30: beaver: " Dmitry Osipenko
@ 2018-10-21 20:55 ` Dmitry Osipenko
  2018-10-21 20:55 ` [RFC PATCH v2 17/17] ARM: dts: tegra30: colibri: " Dmitry Osipenko
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:55 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra30-cardhu.dtsi | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index fb9222b479d2..5fcf5ac09530 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -272,8 +272,11 @@
 
 				vddctrl_reg: vddctrl {
 					regulator-name = "vdd_cpu,vdd_sys";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <300000>;
+					regulator-max-step-microvolt = <100000>;
 					regulator-always-on;
 				};
 
@@ -342,13 +345,16 @@
 			interrupts = <TEGRA_GPIO(CC, 2) IRQ_TYPE_LEVEL_LOW>;
 		};
 
-		tps62361@60 {
+		core_vdd_reg: tps62361@60 {
 			compatible = "ti,tps62361";
 			reg = <0x60>;
 
 			regulator-name = "tps62361-vout";
 			regulator-min-microvolt = <500000>;
 			regulator-max-microvolt = <1500000>;
+			regulator-coupled-with = <&vddctrl_reg>;
+			regulator-coupled-max-spread = <300000>;
+			regulator-max-step-microvolt = <100000>;
 			regulator-boot-on;
 			regulator-always-on;
 			ti,vsel0-state-high;
@@ -649,4 +655,11 @@
 			debounce-interval = <10>;
 		};
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&vddctrl_reg>;
+			core-supply = <&core_vdd_reg>;
+		};
+	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [RFC PATCH v2 17/17] ARM: dts: tegra30: colibri: Setup voltage regulators for DVFS
  2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
                   ` (15 preceding siblings ...)
  2018-10-21 20:55 ` [RFC PATCH v2 16/17] ARM: dts: tegra30: cardhu: " Dmitry Osipenko
@ 2018-10-21 20:55 ` Dmitry Osipenko
  16 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 20:55 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler
  Cc: linux-tegra, linux-pm, devicetree, linux-kernel

Set min/max regulators voltage and add CPU node that hooks up CPU with
voltage regulators.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra30-colibri.dtsi | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/tegra30-colibri.dtsi b/arch/arm/boot/dts/tegra30-colibri.dtsi
index 35af03ca9e90..c59099c1e2c3 100644
--- a/arch/arm/boot/dts/tegra30-colibri.dtsi
+++ b/arch/arm/boot/dts/tegra30-colibri.dtsi
@@ -763,8 +763,11 @@
 
 				vddctrl_reg: vddctrl {
 					regulator-name = "+V1.0_VDD_CPU";
-					regulator-min-microvolt = <1150000>;
-					regulator-max-microvolt = <1150000>;
+					regulator-min-microvolt = <800000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-coupled-with = <&core_vdd_reg>;
+					regulator-coupled-max-spread = <300000>;
+					regulator-max-step-microvolt = <100000>;
 					regulator-always-on;
 				};
 
@@ -882,13 +885,16 @@
 		};
 
 		/* SW: +V1.2_VDD_CORE */
-		regulator@60 {
+		core_vdd_reg: regulator@60 {
 			compatible = "ti,tps62362";
 			reg = <0x60>;
 
 			regulator-name = "tps62362-vout";
 			regulator-min-microvolt = <900000>;
 			regulator-max-microvolt = <1400000>;
+			regulator-coupled-with = <&vddctrl_reg>;
+			regulator-coupled-max-spread = <300000>;
+			regulator-max-step-microvolt = <100000>;
 			regulator-boot-on;
 			regulator-always-on;
 			ti,vsel0-state-low;
@@ -1027,6 +1033,13 @@
 			 <&tegra_car TEGRA30_CLK_EXTERN1>;
 		clock-names = "pll_a", "pll_a_out0", "mclk";
 	};
+
+	cpus {
+		cpu0: cpu@0 {
+			cpu-supply = <&vddctrl_reg>;
+			core-supply = <&core_vdd_reg>;
+		};
+	};
 };
 
 &gpio {
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 02/17] soc/tegra: fuse: Export tegra_get_chip_id()
  2018-10-21 20:54 ` [RFC PATCH v2 02/17] soc/tegra: fuse: Export tegra_get_chip_id() Dmitry Osipenko
@ 2018-10-21 21:33   ` Dmitry Osipenko
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 21:33 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter
  Cc: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Nishanth Menon,
	Stephen Boyd, Marcel Ziswiler, linux-tegra, linux-pm, devicetree,
	linux-kernel

On 10/21/18 11:54 PM, Dmitry Osipenko wrote:
> This function is used by tegra20-cpufreq driver which can be built as a
> kernel module.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/soc/tegra/fuse/tegra-apbmisc.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
> index e5a4d8f98b10..c94dccf3eb30 100644
> --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
> +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
> @@ -51,6 +51,7 @@ u8 tegra_get_chip_id(void)
>  {
>  	return (tegra_read_chipid() >> 8) & 0xff;
>  }
> +EXPORT_SYMBOL_GPL(tegra_get_chip_id);
>  
>  u32 tegra_read_straps(void)
>  {
> 

A quick note.. I just recalled about existence of the of_machine_is_compatible() which will be more appropriate to use in the driver, hence this patch won't be needed.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-21 20:54 ` [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators Dmitry Osipenko
@ 2018-10-22  5:36   ` Viresh Kumar
  2018-10-22 11:29     ` Dmitry Osipenko
  0 siblings, 1 reply; 33+ messages in thread
From: Viresh Kumar @ 2018-10-22  5:36 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 21-10-18, 23:54, Dmitry Osipenko wrote:
> Voltage regulators may be not available on some variations of HW, allow to
> request stub voltage regulators by OPP core in a such case to reduce code
> churning within drivers.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/cpufreq/cpufreq-dt.c | 2 +-
>  drivers/cpufreq/ti-cpufreq.c | 3 ++-
>  drivers/opp/core.c           | 9 +++++++--
>  include/linux/pm_opp.h       | 4 ++--
>  4 files changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
> index e58bfcb1169e..6ebca472ec76 100644
> --- a/drivers/cpufreq/cpufreq-dt.c
> +++ b/drivers/cpufreq/cpufreq-dt.c
> @@ -196,7 +196,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
>  	 */
>  	name = find_supply_name(cpu_dev);
>  	if (name) {
> -		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
> +		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1, false);
>  		if (IS_ERR(opp_table)) {
>  			ret = PTR_ERR(opp_table);
>  			dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",

Have you actually tested this stuff ? The cpufreq-dt driver will
probably fail to probe if the CPU node has a "-supply" property, but
no regulator matching that.

-- 
viresh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-22  5:36   ` Viresh Kumar
@ 2018-10-22 11:29     ` Dmitry Osipenko
  2018-10-22 11:32       ` Viresh Kumar
  0 siblings, 1 reply; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-22 11:29 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 10/22/18 8:36 AM, Viresh Kumar wrote:
> On 21-10-18, 23:54, Dmitry Osipenko wrote:
>> Voltage regulators may be not available on some variations of HW, allow to
>> request stub voltage regulators by OPP core in a such case to reduce code
>> churning within drivers.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>>  drivers/cpufreq/cpufreq-dt.c | 2 +-
>>  drivers/cpufreq/ti-cpufreq.c | 3 ++-
>>  drivers/opp/core.c           | 9 +++++++--
>>  include/linux/pm_opp.h       | 4 ++--
>>  4 files changed, 12 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
>> index e58bfcb1169e..6ebca472ec76 100644
>> --- a/drivers/cpufreq/cpufreq-dt.c
>> +++ b/drivers/cpufreq/cpufreq-dt.c
>> @@ -196,7 +196,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
>>  	 */
>>  	name = find_supply_name(cpu_dev);
>>  	if (name) {
>> -		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
>> +		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1, false);
>>  		if (IS_ERR(opp_table)) {
>>  			ret = PTR_ERR(opp_table);
>>  			dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
> 
> Have you actually tested this stuff ? The cpufreq-dt driver will
> probably fail to probe if the CPU node has a "-supply" property, but
> no regulator matching that.
> 

Please notice that this patch doesn't change the original behaviour and I suppose that failing in a case of missing regulator is the expected behaviour for cpufreq-dt. Hence can't see any problem here.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-22 11:29     ` Dmitry Osipenko
@ 2018-10-22 11:32       ` Viresh Kumar
  2018-10-22 12:12         ` Dmitry Osipenko
  0 siblings, 1 reply; 33+ messages in thread
From: Viresh Kumar @ 2018-10-22 11:32 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 22-10-18, 14:29, Dmitry Osipenko wrote:
> On 10/22/18 8:36 AM, Viresh Kumar wrote:
> > On 21-10-18, 23:54, Dmitry Osipenko wrote:
> >> Voltage regulators may be not available on some variations of HW, allow to
> >> request stub voltage regulators by OPP core in a such case to reduce code
> >> churning within drivers.
> >>
> >> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> >> ---
> >>  drivers/cpufreq/cpufreq-dt.c | 2 +-
> >>  drivers/cpufreq/ti-cpufreq.c | 3 ++-
> >>  drivers/opp/core.c           | 9 +++++++--
> >>  include/linux/pm_opp.h       | 4 ++--
> >>  4 files changed, 12 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
> >> index e58bfcb1169e..6ebca472ec76 100644
> >> --- a/drivers/cpufreq/cpufreq-dt.c
> >> +++ b/drivers/cpufreq/cpufreq-dt.c
> >> @@ -196,7 +196,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
> >>  	 */
> >>  	name = find_supply_name(cpu_dev);
> >>  	if (name) {
> >> -		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
> >> +		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1, false);
> >>  		if (IS_ERR(opp_table)) {
> >>  			ret = PTR_ERR(opp_table);
> >>  			dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
> > 
> > Have you actually tested this stuff ? The cpufreq-dt driver will
> > probably fail to probe if the CPU node has a "-supply" property, but
> > no regulator matching that.
> > 
> 
> Please notice that this patch doesn't change the original behaviour
> and I suppose that failing in a case of missing regulator is the
> expected behaviour for cpufreq-dt. Hence can't see any problem here.

So why have this patch then ?

-- 
viresh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-22 11:32       ` Viresh Kumar
@ 2018-10-22 12:12         ` Dmitry Osipenko
  2018-10-24  6:41           ` Viresh Kumar
  0 siblings, 1 reply; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-22 12:12 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 10/22/18 2:32 PM, Viresh Kumar wrote:
> On 22-10-18, 14:29, Dmitry Osipenko wrote:
>> On 10/22/18 8:36 AM, Viresh Kumar wrote:
>>> On 21-10-18, 23:54, Dmitry Osipenko wrote:
>>>> Voltage regulators may be not available on some variations of HW, allow to
>>>> request stub voltage regulators by OPP core in a such case to reduce code
>>>> churning within drivers.
>>>>
>>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>>> ---
>>>>  drivers/cpufreq/cpufreq-dt.c | 2 +-
>>>>  drivers/cpufreq/ti-cpufreq.c | 3 ++-
>>>>  drivers/opp/core.c           | 9 +++++++--
>>>>  include/linux/pm_opp.h       | 4 ++--
>>>>  4 files changed, 12 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
>>>> index e58bfcb1169e..6ebca472ec76 100644
>>>> --- a/drivers/cpufreq/cpufreq-dt.c
>>>> +++ b/drivers/cpufreq/cpufreq-dt.c
>>>> @@ -196,7 +196,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
>>>>  	 */
>>>>  	name = find_supply_name(cpu_dev);
>>>>  	if (name) {
>>>> -		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
>>>> +		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1, false);
>>>>  		if (IS_ERR(opp_table)) {
>>>>  			ret = PTR_ERR(opp_table);
>>>>  			dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
>>>
>>> Have you actually tested this stuff ? The cpufreq-dt driver will
>>> probably fail to probe if the CPU node has a "-supply" property, but
>>> no regulator matching that.
>>>
>>
>> Please notice that this patch doesn't change the original behaviour
>> and I suppose that failing in a case of missing regulator is the
>> expected behaviour for cpufreq-dt. Hence can't see any problem here.
> 
> So why have this patch then ?

Because there is one Tegra20 board (tegra20-trimslice) that doesn't declare necessary regulators, but we want to have CPU frequency scaling. I couldn't find board schematics and so don't know if CPU / CORE voltages are fixed on Trim-Slice or it is just preferable not to have DVFS for that board, it is an outlet-powered device [0]. Hence tegra20-cpufreq driver will request a dummy regulators when appropriate. 

[0] http://www.compulab.co.il/utilite-computer/web/trim-slice

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 09/17] ARM: dts: tegra20: harmony: Setup voltage regulators for DVFS
  2018-10-21 20:54 ` [RFC PATCH v2 09/17] ARM: dts: tegra20: harmony: " Dmitry Osipenko
@ 2018-10-22 15:33   ` Stephen Warren
  2018-10-22 22:59     ` Dmitry Osipenko
  0 siblings, 1 reply; 33+ messages in thread
From: Stephen Warren @ 2018-10-22 15:33 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler,
	linux-tegra, linux-pm, devicetree, linux-kernel

On 10/21/18 2:54 PM, Dmitry Osipenko wrote:
> Set min/max regulators voltage and add CPU node that hooks up CPU with
> voltage regulators.

> diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts

> -				sm0 {
> +				core_vdd_reg: sm0 {
>   					regulator-name = "vdd_sm0,vdd_core";
> -					regulator-min-microvolt = <1200000>;
> -					regulator-max-microvolt = <1200000>;
> +					regulator-min-microvolt = <1000000>;
> +					regulator-max-microvolt = <1300000>;
> +					regulator-coupled-with = <&rtc_vdd_reg>;
> +					regulator-coupled-max-spread = <150000>;
>   					regulator-always-on;
>   				};

How do you know for sure that these increased ranges are safe (high end) 
and stable (low end) for this particular board? IIRC the safe/legal 
range depends on the chip SKU, and to be honest I have no idea which SKU 
is present on Harmony... For public boards like Colibri I imagine 
there's enough information out there to tell what will work, but maybe 
not our internal boards like Harmony, unless you checked our ancient 
downstream kernels?

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 09/17] ARM: dts: tegra20: harmony: Setup voltage regulators for DVFS
  2018-10-22 15:33   ` Stephen Warren
@ 2018-10-22 22:59     ` Dmitry Osipenko
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-22 22:59 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Rafael J. Wysocki, Viresh Kumar, Rob Herring, Thierry Reding,
	Jonathan Hunter, Nishanth Menon, Stephen Boyd, Marcel Ziswiler,
	linux-tegra, linux-pm, devicetree, linux-kernel

On 10/22/18 6:33 PM, Stephen Warren wrote:
> On 10/21/18 2:54 PM, Dmitry Osipenko wrote:
>> Set min/max regulators voltage and add CPU node that hooks up CPU with
>> voltage regulators.
> 
>> diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
> 
>> -                sm0 {
>> +                core_vdd_reg: sm0 {
>>                       regulator-name = "vdd_sm0,vdd_core";
>> -                    regulator-min-microvolt = <1200000>;
>> -                    regulator-max-microvolt = <1200000>;
>> +                    regulator-min-microvolt = <1000000>;
>> +                    regulator-max-microvolt = <1300000>;
>> +                    regulator-coupled-with = <&rtc_vdd_reg>;
>> +                    regulator-coupled-max-spread = <150000>;
>>                       regulator-always-on;
>>                   };
> 
> How do you know for sure that these increased ranges are safe (high end) and stable (low end) for this particular board? IIRC the safe/legal range depends on the chip SKU, and to be honest I have no idea which SKU is present on Harmony... For public boards like Colibri I imagine there's enough information out there to tell what will work, but maybe not our internal boards like Harmony, unless you checked our ancient downstream kernels?

Yes, the ranges could be inaccurate in these DT patches. But it shouldn't matter much because only OPP's that match actual HW SKU will be used for DVFS. Though certainly it will be nice if we could specify exactly correct ranges.

Looks like downstream doesn't specify safe ranges for any of the boards and it is relying on the SKU-VOLTAGE DVFS table values only. 

For now there are quite few obstacles that need to be resolved in order to get a properly working system-wide DVFS, but things are getting a bit closer. Thank you very much for your input!

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-22 12:12         ` Dmitry Osipenko
@ 2018-10-24  6:41           ` Viresh Kumar
  2018-10-26 12:03             ` Dmitry Osipenko
  0 siblings, 1 reply; 33+ messages in thread
From: Viresh Kumar @ 2018-10-24  6:41 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 22-10-18, 15:12, Dmitry Osipenko wrote:
> Because there is one Tegra20 board (tegra20-trimslice) that doesn't declare
> necessary regulators, but we want to have CPU frequency scaling. I couldn't
> find board schematics and so don't know if CPU / CORE voltages are fixed on
> Trim-Slice or it is just preferable not to have DVFS for that board, it is an
> outlet-powered device [0]. Hence tegra20-cpufreq driver will request a dummy
> regulators when appropriate. 

We have been using the regulator_get_optional() variant until now in the OPP
core to make sure that we don't do DVFS for the CPU without the mandatory
regulators being present, as that may make things unstable and cause harm to the
SoC if we try to take CPU to frequency range over the currently programmed
regulator can support.

Now coming back to tegra-20 SoC, which actually requires a regulator normally by
design. On one of the boards (which is outlet powered), you aren't sure if there
is a programmable regulator or not, or if DVFS should really be done or not.
Isn't it worth checking the same from Tegra maintainers, or whomsoever has
information on that board ? What would happen if there actually was a regulator
and its default settings aren't good enough for high end frequencies ?

On the other hand, the tegra20 cpufreq driver is common across a lot of boards.
What will happen if the DT for some of the boards isn't correct and missed the
necessary regulator node ? And because you are moving to regulator_get() API for
the entire SoC (i.e. its cpufreq driver), people will never find the missing
regulator.

If we can do it safely for all tegra20 boards, why not migrate to using
regulator_get() instead of regulator_get_optional() in the OPP core API itself
for everyone ?

-- 
viresh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-24  6:41           ` Viresh Kumar
@ 2018-10-26 12:03             ` Dmitry Osipenko
  2018-10-26 15:37               ` Lucas Stach
  2018-10-29  6:53               ` Viresh Kumar
  0 siblings, 2 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-26 12:03 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 10/24/18 9:41 AM, Viresh Kumar wrote:
> On 22-10-18, 15:12, Dmitry Osipenko wrote:
>> Because there is one Tegra20 board (tegra20-trimslice) that doesn't declare
>> necessary regulators, but we want to have CPU frequency scaling. I couldn't
>> find board schematics and so don't know if CPU / CORE voltages are fixed on
>> Trim-Slice or it is just preferable not to have DVFS for that board, it is an
>> outlet-powered device [0]. Hence tegra20-cpufreq driver will request a dummy
>> regulators when appropriate. 
> 
> We have been using the regulator_get_optional() variant until now in the OPP
> core to make sure that we don't do DVFS for the CPU without the mandatory
> regulators being present, as that may make things unstable and cause harm to the
> SoC if we try to take CPU to frequency range over the currently programmed
> regulator can support.
> 
> Now coming back to tegra-20 SoC, which actually requires a regulator normally by
> design. On one of the boards (which is outlet powered), you aren't sure if there
> is a programmable regulator or not, or if DVFS should really be done or not.
> Isn't it worth checking the same from Tegra maintainers, or whomsoever has
> information on that board ?

I'll try to find out more detailed information for the next revision of the patchset.

 What would happen if there actually was a regulator
> and its default settings aren't good enough for high end frequencies ?

Usually this causes kernel/applications crashes and/or machine hang.

> On the other hand, the tegra20 cpufreq driver is common across a lot of boards.
> What will happen if the DT for some of the boards isn't correct and missed the
> necessary regulator node ?

AFAIK, there is assumption that bootloader should setup regulators in a way that kernel could work properly at max clock rates. Otherwise things won't work.

 And because you are moving to regulator_get() API for
> the entire SoC (i.e. its cpufreq driver), people will never find the missing
> regulator.

Regulators core prints info message when dummy regulator is being used.

> If we can do it safely for all tegra20 boards, why not migrate to using
> regulator_get() instead of regulator_get_optional() in the OPP core API itself
> for everyone ?
> 

This should be a platform-specific decision. For Tegra we know that regulators should be in a good state at kernel boot time, I don't think that this applies to other platforms.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-26 12:03             ` Dmitry Osipenko
@ 2018-10-26 15:37               ` Lucas Stach
  2018-10-28 12:58                 ` Dmitry Osipenko
  2018-10-29  6:53               ` Viresh Kumar
  1 sibling, 1 reply; 33+ messages in thread
From: Lucas Stach @ 2018-10-26 15:37 UTC (permalink / raw)
  To: Dmitry Osipenko, Viresh Kumar
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

Am Freitag, den 26.10.2018, 15:03 +0300 schrieb Dmitry Osipenko:
[...]
> > On the other hand, the tegra20 cpufreq driver is common across a lot of boards.
> > What will happen if the DT for some of the boards isn't correct and missed the
> > necessary regulator node ?
> 
> AFAIK, there is assumption that bootloader should setup regulators in
> a way that kernel could work properly at max clock rates. Otherwise
> things won't work.

This isn't true. The assumption is that the bootloader sets up the
regulators such that stable operation at the CPU speed used by the
bootloader is guaranteed.

Often the bootloader doesn't know about specific SKUs, so drives things
at a rate/voltage that is safe across all SKUs [1], in which case the
bootloader is totally unaware of the voltage needed to run the CPU at
highest possible clock frequency.

Regards,
Lucas

[1] http://git.denx.de/?p=u-boot.git;a=commit;h=2364e151e432b4ccf32dc9e6147121253d4ff86d

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-26 15:37               ` Lucas Stach
@ 2018-10-28 12:58                 ` Dmitry Osipenko
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-28 12:58 UTC (permalink / raw)
  To: Lucas Stach, Viresh Kumar
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 10/26/18 6:37 PM, Lucas Stach wrote:
> Am Freitag, den 26.10.2018, 15:03 +0300 schrieb Dmitry Osipenko:
> [...]
>>> On the other hand, the tegra20 cpufreq driver is common across a lot of boards.
>>> What will happen if the DT for some of the boards isn't correct and missed the
>>> necessary regulator node ?
>>
>> AFAIK, there is assumption that bootloader should setup regulators in
>> a way that kernel could work properly at max clock rates. Otherwise
>> things won't work.
> 
> This isn't true. The assumption is that the bootloader sets up the
> regulators such that stable operation at the CPU speed used by the
> bootloader is guaranteed.
> 
> Often the bootloader doesn't know about specific SKUs, so drives things
> at a rate/voltage that is safe across all SKUs [1], in which case the
> bootloader is totally unaware of the voltage needed to run the CPU at
> highest possible clock frequency.
> 
> Regards,
> Lucas
> 
> [1] http://git.denx.de/?p=u-boot.git;a=commit;h=2364e151e432b4ccf32dc9e6147121253d4ff86d
> 

Oh, okay. Thank you for pointing at [1], though the assumption is true for T20. 

I agree that it's better not to rely on configuration left from bootloader in general.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-26 12:03             ` Dmitry Osipenko
  2018-10-26 15:37               ` Lucas Stach
@ 2018-10-29  6:53               ` Viresh Kumar
  2018-10-30 15:48                 ` Dmitry Osipenko
  1 sibling, 1 reply; 33+ messages in thread
From: Viresh Kumar @ 2018-10-29  6:53 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 26-10-18, 15:03, Dmitry Osipenko wrote:
> On 10/24/18 9:41 AM, Viresh Kumar wrote:
> > On 22-10-18, 15:12, Dmitry Osipenko wrote:
> >> Because there is one Tegra20 board (tegra20-trimslice) that doesn't declare
> >> necessary regulators, but we want to have CPU frequency scaling. I couldn't
> >> find board schematics and so don't know if CPU / CORE voltages are fixed on
> >> Trim-Slice or it is just preferable not to have DVFS for that board, it is an
> >> outlet-powered device [0]. Hence tegra20-cpufreq driver will request a dummy
> >> regulators when appropriate. 
> > 
> > We have been using the regulator_get_optional() variant until now in the OPP
> > core to make sure that we don't do DVFS for the CPU without the mandatory
> > regulators being present, as that may make things unstable and cause harm to the
> > SoC if we try to take CPU to frequency range over the currently programmed
> > regulator can support.
> > 
> > Now coming back to tegra-20 SoC, which actually requires a regulator normally by
> > design. On one of the boards (which is outlet powered), you aren't sure if there
> > is a programmable regulator or not, or if DVFS should really be done or not.
> > Isn't it worth checking the same from Tegra maintainers, or whomsoever has
> > information on that board ?
> 
> I'll try to find out more detailed information for the next revision of the patchset.

Thanks Dmitry.

>  What would happen if there actually was a regulator

Please preserve the '>' from previous replies at the beginning of the
lines. Otherwise it looks as if you have written the above line. :)

> > and its default settings aren't good enough for high end frequencies ?
> 
> Usually this causes kernel/applications crashes and/or machine hang.

Sure. I also do remember from some guys (maybe TI), where they
mentioned that such scenarios can harm the hardware as well sometimes.
Don't remember the details though.

>  And because you are moving to regulator_get() API for
> > the entire SoC (i.e. its cpufreq driver), people will never find the missing
> > regulator.
> 
> Regulators core prints info message when dummy regulator is being used.

Sure, but they are easy to miss and they are only seen by developers
not regular users of a machine.

> > If we can do it safely for all tegra20 boards, why not migrate to using
> > regulator_get() instead of regulator_get_optional() in the OPP core API itself
> > for everyone ?
> > 
> 
> This should be a platform-specific decision. For Tegra we know that regulators should be in a good state at kernel boot time, I don't think that this applies to other platforms.

Based on the other discussion with Lucas on this thread, I don't think
this is correct any more ?

Don't get me wrong, I am all good for changes and another API change
doesn't matter much to me. I am just wondering if it would be the
right approach to fix the issue. Why not rather call
dev_pm_opp_set_regulators() conditionally and avoid calling it for the
specific tegra20 board.

-- 
viresh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators
  2018-10-29  6:53               ` Viresh Kumar
@ 2018-10-30 15:48                 ` Dmitry Osipenko
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-10-30 15:48 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael J. Wysocki, Rob Herring, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 10/29/18 9:53 AM, Viresh Kumar wrote:
> On 26-10-18, 15:03, Dmitry Osipenko wrote:
>> On 10/24/18 9:41 AM, Viresh Kumar wrote:
>>> On 22-10-18, 15:12, Dmitry Osipenko wrote:
>>>> Because there is one Tegra20 board (tegra20-trimslice) that doesn't declare
>>>> necessary regulators, but we want to have CPU frequency scaling. I couldn't
>>>> find board schematics and so don't know if CPU / CORE voltages are fixed on
>>>> Trim-Slice or it is just preferable not to have DVFS for that board, it is an
>>>> outlet-powered device [0]. Hence tegra20-cpufreq driver will request a dummy
>>>> regulators when appropriate. 
>>>
>>> We have been using the regulator_get_optional() variant until now in the OPP
>>> core to make sure that we don't do DVFS for the CPU without the mandatory
>>> regulators being present, as that may make things unstable and cause harm to the
>>> SoC if we try to take CPU to frequency range over the currently programmed
>>> regulator can support.
>>>
>>> Now coming back to tegra-20 SoC, which actually requires a regulator normally by
>>> design. On one of the boards (which is outlet powered), you aren't sure if there
>>> is a programmable regulator or not, or if DVFS should really be done or not.
>>> Isn't it worth checking the same from Tegra maintainers, or whomsoever has
>>> information on that board ?
>>
>> I'll try to find out more detailed information for the next revision of the patchset.
> 
> Thanks Dmitry.
> 
>>  What would happen if there actually was a regulator
> 
> Please preserve the '>' from previous replies at the beginning of the
> lines. Otherwise it looks as if you have written the above line. :)
> 
>>> and its default settings aren't good enough for high end frequencies ?
>>
>> Usually this causes kernel/applications crashes and/or machine hang.
> 
> Sure. I also do remember from some guys (maybe TI), where they
> mentioned that such scenarios can harm the hardware as well sometimes.
> Don't remember the details though.
> 
>>  And because you are moving to regulator_get() API for
>>> the entire SoC (i.e. its cpufreq driver), people will never find the missing
>>> regulator.
>>
>> Regulators core prints info message when dummy regulator is being used.
> 
> Sure, but they are easy to miss and they are only seen by developers
> not regular users of a machine.
> 
>>> If we can do it safely for all tegra20 boards, why not migrate to using
>>> regulator_get() instead of regulator_get_optional() in the OPP core API itself
>>> for everyone ?
>>>
>>
>> This should be a platform-specific decision. For Tegra we know that regulators should be in a good state at kernel boot time, I don't think that this applies to other platforms.
> 
> Based on the other discussion with Lucas on this thread, I don't think
> this is correct any more ?
> 
> Don't get me wrong, I am all good for changes and another API change
> doesn't matter much to me. I am just wondering if it would be the
> right approach to fix the issue. Why not rather call
> dev_pm_opp_set_regulators() conditionally and avoid calling it for the
> specific tegra20 board.

The right approach should be to specify device tree correctly. Probably we won't need this change at all with the correct DT, will see.

Calling dev_pm_opp_set_regulators() conditionally should work, but that is extra churning in the driver that I tried to avoid.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 03/17] dt-bindings: cpufreq: Add binding for NVIDIA Tegra20/30
  2018-10-21 20:54 ` [RFC PATCH v2 03/17] dt-bindings: cpufreq: Add binding for NVIDIA Tegra20/30 Dmitry Osipenko
@ 2018-11-05 21:30   ` Rob Herring
  2018-11-08 16:48     ` Dmitry Osipenko
  0 siblings, 1 reply; 33+ messages in thread
From: Rob Herring @ 2018-11-05 21:30 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rafael J. Wysocki, Viresh Kumar, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On Sun, Oct 21, 2018 at 11:54:47PM +0300, Dmitry Osipenko wrote:
> Add device-tree binding that describes CPU frequency-scaling hardware
> found on NVIDIA Tegra20/30 SoC's.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../cpufreq/nvidia,tegra20-cpufreq.txt        | 96 +++++++++++++++++++
>  1 file changed, 96 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
> 
> diff --git a/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
> new file mode 100644
> index 000000000000..a8023ea7a99f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
> @@ -0,0 +1,96 @@
> +Binding for NVIDIA Tegra20 CPUFreq
> +==================================
> +
> +Required properties:
> +- clocks: Must contain an entry for each entry in clock-names.
> +  See ../clocks/clock-bindings.txt for details.
> +- clock-names: Must include the following entries:
> +  - pll_x: main-parent for CPU clock, must be the first entry
> +  - intermediate: intermediate-parent for CPU clock
> +  - cclk: the CPU clock
> +- operating-points-v2: See ../bindings/opp/opp.txt for details.
> +- #cooling-cells: Should be 2. See ../thermal/thermal.txt for details.
> +
> +For each opp entry in 'operating-points-v2' table:
> +- opp-supported-hw: Two bitfields indicating:
> +	On Tegra20:
> +	1. CPU process ID mask
> +	2. SoC speedo ID mask
> +
> +	On Tegra30:
> +	1. CPU process ID mask
> +	2. CPU speedo ID mask
> +
> +	A bitwise AND is performed against these values and if any bit
> +	matches, the OPP gets enabled.
> +
> +- opp-microvolt: CPU voltage triplet.
> +
> +Optional properties:
> +- cpu-supply: Phandle to the CPU power supply.
> +- core-supply: Phandle to the CORE power supply.
> +- rtc-supply: Phandle to the RTC power supply, required only for Tegra20.
> +
> +Voltage supply requirements:
> +- Tegra20:
> +	CORE and RTC regulators must be coupled using the regulator-coupled-with
> +	property and regulator-coupled-max-spread property must be set to no
> +	more than 170mV.
> +
> +	See ../regulator/regulator.txt for more detail about the properties.
> +
> +- Tegra30:
> +	CORE and CPU regulators must be coupled using the regulator-coupled-with
> +	property and regulator-coupled-max-spread property must be set to no
> +	more than 300mV. Each of CORE and CPU regulators must set
> +	regulator-max-step-microvolt property to no more than 100mV.
> +
> +	See ../regulator/regulator.txt for more detail about the properties.
> +
> +
> +Example:
> +	regulators {
> +		cpu_reg: regulator0 {
> +			regulator-name = "vdd_cpu";
> +		};
> +
> +		core_reg: regulator1 {
> +			regulator-name = "vdd_core";
> +			regulator-coupled-with = <&rtc_reg>;
> +			regulator-coupled-max-spread = <170000>;
> +		};
> +
> +		rtc_reg: regulator2 {
> +			regulator-name = "vdd_rtc";
> +			regulator-coupled-with = <&core_reg>;
> +			regulator-coupled-max-spread = <170000>;
> +		};
> +	};
> +
> +	cpu0_opp_table: opp_table0 {
> +		compatible = "operating-points-v2";
> +
> +		opp@456000000 {
> +			clock-latency-ns = <125000>;
> +			opp-microvolt = <825000 825000 1125000>;
> +			opp-supported-hw = <0x03 0x0001>;
> +			opp-hz = /bits/ 64 <456000000>;
> +		};
> +
> +		...
> +	};
> +
> +	cpus {
> +		cpu@0 {
> +			compatible = "arm,cortex-a9";
> +			clocks = <&tegra_car TEGRA20_CLK_PLL_X>,
> +				 <&tegra_car TEGRA20_CLK_PLL_P>,
> +				 <&tegra_car TEGRA20_CLK_CCLK>;
> +			clock-names = "pll_x", "intermediate", "cclk";

I still object to having clocks (and supplies) which don't reflect the 
h/w and are documented in the CA9 TRM.

> +			operating-points-v2 = <&cpu0_opp_table>;
> +			cpu-supply = <&cpu_reg>;
> +			core-supply = <&core_reg>;
> +			rtc-supply = <&rtc_reg>;

Supplies are suspect too, but perhaps supplies and power domains are 
beyond the scope of the TRM and part of the physical design.

Rob

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC PATCH v2 03/17] dt-bindings: cpufreq: Add binding for NVIDIA Tegra20/30
  2018-11-05 21:30   ` Rob Herring
@ 2018-11-08 16:48     ` Dmitry Osipenko
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Osipenko @ 2018-11-08 16:48 UTC (permalink / raw)
  To: Rob Herring
  Cc: Rafael J. Wysocki, Viresh Kumar, Thierry Reding, Jonathan Hunter,
	Nishanth Menon, Stephen Boyd, Marcel Ziswiler, linux-tegra,
	linux-pm, devicetree, linux-kernel

On 06.11.2018 0:30, Rob Herring wrote:
> On Sun, Oct 21, 2018 at 11:54:47PM +0300, Dmitry Osipenko wrote:
>> Add device-tree binding that describes CPU frequency-scaling hardware
>> found on NVIDIA Tegra20/30 SoC's.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>>  .../cpufreq/nvidia,tegra20-cpufreq.txt        | 96 +++++++++++++++++++
>>  1 file changed, 96 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
>>
>> diff --git a/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
>> new file mode 100644
>> index 000000000000..a8023ea7a99f
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/cpufreq/nvidia,tegra20-cpufreq.txt
>> @@ -0,0 +1,96 @@
>> +Binding for NVIDIA Tegra20 CPUFreq
>> +==================================
>> +
>> +Required properties:
>> +- clocks: Must contain an entry for each entry in clock-names.
>> +  See ../clocks/clock-bindings.txt for details.
>> +- clock-names: Must include the following entries:
>> +  - pll_x: main-parent for CPU clock, must be the first entry
>> +  - intermediate: intermediate-parent for CPU clock
>> +  - cclk: the CPU clock
>> +- operating-points-v2: See ../bindings/opp/opp.txt for details.
>> +- #cooling-cells: Should be 2. See ../thermal/thermal.txt for details.
>> +
>> +For each opp entry in 'operating-points-v2' table:
>> +- opp-supported-hw: Two bitfields indicating:
>> +	On Tegra20:
>> +	1. CPU process ID mask
>> +	2. SoC speedo ID mask
>> +
>> +	On Tegra30:
>> +	1. CPU process ID mask
>> +	2. CPU speedo ID mask
>> +
>> +	A bitwise AND is performed against these values and if any bit
>> +	matches, the OPP gets enabled.
>> +
>> +- opp-microvolt: CPU voltage triplet.
>> +
>> +Optional properties:
>> +- cpu-supply: Phandle to the CPU power supply.
>> +- core-supply: Phandle to the CORE power supply.
>> +- rtc-supply: Phandle to the RTC power supply, required only for Tegra20.
>> +
>> +Voltage supply requirements:
>> +- Tegra20:
>> +	CORE and RTC regulators must be coupled using the regulator-coupled-with
>> +	property and regulator-coupled-max-spread property must be set to no
>> +	more than 170mV.
>> +
>> +	See ../regulator/regulator.txt for more detail about the properties.
>> +
>> +- Tegra30:
>> +	CORE and CPU regulators must be coupled using the regulator-coupled-with
>> +	property and regulator-coupled-max-spread property must be set to no
>> +	more than 300mV. Each of CORE and CPU regulators must set
>> +	regulator-max-step-microvolt property to no more than 100mV.
>> +
>> +	See ../regulator/regulator.txt for more detail about the properties.
>> +
>> +
>> +Example:
>> +	regulators {
>> +		cpu_reg: regulator0 {
>> +			regulator-name = "vdd_cpu";
>> +		};
>> +
>> +		core_reg: regulator1 {
>> +			regulator-name = "vdd_core";
>> +			regulator-coupled-with = <&rtc_reg>;
>> +			regulator-coupled-max-spread = <170000>;
>> +		};
>> +
>> +		rtc_reg: regulator2 {
>> +			regulator-name = "vdd_rtc";
>> +			regulator-coupled-with = <&core_reg>;
>> +			regulator-coupled-max-spread = <170000>;
>> +		};
>> +	};
>> +
>> +	cpu0_opp_table: opp_table0 {
>> +		compatible = "operating-points-v2";
>> +
>> +		opp@456000000 {
>> +			clock-latency-ns = <125000>;
>> +			opp-microvolt = <825000 825000 1125000>;
>> +			opp-supported-hw = <0x03 0x0001>;
>> +			opp-hz = /bits/ 64 <456000000>;
>> +		};
>> +
>> +		...
>> +	};
>> +
>> +	cpus {
>> +		cpu@0 {
>> +			compatible = "arm,cortex-a9";
>> +			clocks = <&tegra_car TEGRA20_CLK_PLL_X>,
>> +				 <&tegra_car TEGRA20_CLK_PLL_P>,
>> +				 <&tegra_car TEGRA20_CLK_CCLK>;
>> +			clock-names = "pll_x", "intermediate", "cclk";
> 
> I still object to having clocks (and supplies) which don't reflect the 
> h/w and are documented in the CA9 TRM.
> 
>> +			operating-points-v2 = <&cpu0_opp_table>;
>> +			cpu-supply = <&cpu_reg>;
>> +			core-supply = <&core_reg>;
>> +			rtc-supply = <&rtc_reg>;
> 
> Supplies are suspect too, but perhaps supplies and power domains are 
> beyond the scope of the TRM and part of the physical design.

Is it possible to have a "firmware" device-tree node specifically for cpufreq driver? Something like this:

cpufreq {
	compatible = "nvidia,tegra20-cpufreq";
	clocks = <&tegra_car TEGRA20_CLK_PLL_X>,
		 <&tegra_car TEGRA20_CLK_PLL_P>;
	clock-names = "pll_x", "intermediate";
};

We may also need a Tegra-specific DVFS helper-driver that will help to manage CPU-CORE voltage dependency. Yet I'll have to examine this all in more details, but maybe it will be nicer if DVFS could be instantiated via device-tree as well. It will provide a Tegra-specific DVFS API and manage CORE / RTC dependencies for the CPUFreq and peripheral drivers, also helping to maintain proper voltages during kernel boot-up until all drivers are brought into action.

cpufreq {
	compatible = "nvidia,tegra20-dvfs";
	cpu-supply = <&cpu_vdd_reg>;
	core-supply = <&core_vdd_reg>;
	rtc-supply = <&rtc_vdd_reg>;
};

So my question is:

Is it possible to have device-tree nodes that solely describe firmware? Kernel drivers in this case.

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2018-11-08 16:49 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-21 20:54 [RFC PATCH v2 00/17] CPUFREQ OPP's, DVFS and Tegra30 support by tegra20-cpufreq driver Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 01/17] OPP: Allow to request stub voltage regulators Dmitry Osipenko
2018-10-22  5:36   ` Viresh Kumar
2018-10-22 11:29     ` Dmitry Osipenko
2018-10-22 11:32       ` Viresh Kumar
2018-10-22 12:12         ` Dmitry Osipenko
2018-10-24  6:41           ` Viresh Kumar
2018-10-26 12:03             ` Dmitry Osipenko
2018-10-26 15:37               ` Lucas Stach
2018-10-28 12:58                 ` Dmitry Osipenko
2018-10-29  6:53               ` Viresh Kumar
2018-10-30 15:48                 ` Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 02/17] soc/tegra: fuse: Export tegra_get_chip_id() Dmitry Osipenko
2018-10-21 21:33   ` Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 03/17] dt-bindings: cpufreq: Add binding for NVIDIA Tegra20/30 Dmitry Osipenko
2018-11-05 21:30   ` Rob Herring
2018-11-08 16:48     ` Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 04/17] cpufreq: tegra20: Support OPP, thermal cooling, DVFS and Tegra30 Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 05/17] ARM: tegra: Create tegra20-cpufreq device on Tegra30 Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 06/17] ARM: dts: tegra20: Add CPU Operating Performance Points Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 07/17] ARM: dts: tegra30: " Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 08/17] ARM: dts: tegra20: colibri: Setup voltage regulators for DVFS Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 09/17] ARM: dts: tegra20: harmony: " Dmitry Osipenko
2018-10-22 15:33   ` Stephen Warren
2018-10-22 22:59     ` Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 10/17] ARM: dts: tegra20: paz00: " Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 11/17] ARM: dts: tegra20: seaboard: " Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 12/17] ARM: dts: tegra20: tamonten: " Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 13/17] ARM: dts: tegra20: ventana: " Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 14/17] ARM: dts: tegra30: apalis: " Dmitry Osipenko
2018-10-21 20:54 ` [RFC PATCH v2 15/17] ARM: dts: tegra30: beaver: " Dmitry Osipenko
2018-10-21 20:55 ` [RFC PATCH v2 16/17] ARM: dts: tegra30: cardhu: " Dmitry Osipenko
2018-10-21 20:55 ` [RFC PATCH v2 17/17] ARM: dts: tegra30: colibri: " Dmitry Osipenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).