linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
@ 2020-11-04 23:43 Dmitry Osipenko
  2020-11-04 23:43 ` [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties Dmitry Osipenko
                   ` (32 more replies)
  0 siblings, 33 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:43 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs, which reduces
power consumption and heating of the Tegra chips. Tegra SoC has multiple
hardware units which belong to a core power domain of the SoC and share
the core voltage. The voltage must be selected in accordance to a minimum
requirement of every core hardware unit.

The minimum core voltage requirement depends on:

  1. Clock enable state of a hardware unit.
  2. Clock frequency.
  3. Unit's internal idling/active state.

This series is tested on Acer A500 (T20), AC100 (T20), Nexus 7 (T30) and
Ouya (T30) devices. I also added voltage scaling to the Ventana (T20) and
Cardhu (T30) boards which are tested by NVIDIA's CI farm. Tegra30 is now up
to 5C cooler on Nexus 7 and stays cool on Ouya (instead of becoming burning
hot) while system is idling. It should be possible to improve this further
by implementing a more advanced power management features for the kernel
drivers.

The DVFS support is opt-in for all boards, meaning that older DTBs will
continue to work like they did it before this series. It should be possible
to easily add the core voltage scaling support for Tegra114+ SoCs based on
this grounding work later on, if anyone will want to implement it.

WARNING(!) This series is made on top of the memory interconnect patches
           which are currently under review [1]. The Tegra EMC driver
           and devicetree-related patches need to be applied on top of
           the ICC series.

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

Dmitry Osipenko (30):
  dt-bindings: host1x: Document OPP and voltage regulator properties
  dt-bindings: mmc: tegra: Document OPP and voltage regulator properties
  dt-bindings: pwm: tegra: Document OPP and voltage regulator properties
  media: dt: bindings: tegra-vde: Document OPP and voltage regulator
    properties
  dt-binding: usb: ci-hdrc-usb2:  Document OPP and voltage regulator
    properties
  dt-bindings: usb: tegra-ehci: Document OPP and voltage regulator
    properties
  soc/tegra: Add sync state API
  soc/tegra: regulators: Support Tegra SoC device sync state API
  soc/tegra: regulators: Fix lockup when voltage-spread is out of range
  regulator: Allow skipping disabled regulators in
    regulator_check_consumers()
  drm/tegra: dc: Support OPP and SoC core voltage scaling
  drm/tegra: gr2d: Correct swapped device-tree compatibles
  drm/tegra: gr2d: Support OPP and SoC core voltage scaling
  drm/tegra: gr3d: Support OPP and SoC core voltage scaling
  drm/tegra: hdmi: Support OPP and SoC core voltage scaling
  gpu: host1x: Support OPP and SoC core voltage scaling
  mmc: sdhci-tegra: Support OPP and core voltage scaling
  pwm: tegra: Support OPP and core voltage scaling
  media: staging: tegra-vde: Support OPP and SoC core voltage scaling
  usb: chipidea: tegra: Support OPP and SoC core voltage scaling
  usb: host: ehci-tegra: Support OPP and SoC core voltage scaling
  memory: tegra20-emc: Support Tegra SoC device state syncing
  memory: tegra30-emc: Support Tegra SoC device state syncing
  ARM: tegra: Add OPP tables for Tegra20 peripheral devices
  ARM: tegra: Add OPP tables for Tegra30 peripheral devices
  ARM: tegra: ventana: Add voltage supplies to DVFS-capable devices
  ARM: tegra: paz00: Add voltage supplies to DVFS-capable devices
  ARM: tegra: acer-a500: Add voltage supplies to DVFS-capable devices
  ARM: tegra: cardhu-a04: Add voltage supplies to DVFS-capable devices
  ARM: tegra: nexus7: Add voltage supplies to DVFS-capable devices

 .../display/tegra/nvidia,tegra20-host1x.txt   |  56 +++
 .../bindings/media/nvidia,tegra-vde.txt       |  12 +
 .../bindings/mmc/nvidia,tegra20-sdhci.txt     |  12 +
 .../bindings/pwm/nvidia,tegra20-pwm.txt       |  13 +
 .../devicetree/bindings/usb/ci-hdrc-usb2.txt  |   4 +
 .../bindings/usb/nvidia,tegra20-ehci.txt      |   2 +
 .../boot/dts/tegra20-acer-a500-picasso.dts    |  30 +-
 arch/arm/boot/dts/tegra20-paz00.dts           |  40 +-
 .../arm/boot/dts/tegra20-peripherals-opp.dtsi | 386 ++++++++++++++++
 arch/arm/boot/dts/tegra20-ventana.dts         |  65 ++-
 arch/arm/boot/dts/tegra20.dtsi                |  14 +
 .../tegra30-asus-nexus7-grouper-common.dtsi   |  23 +
 arch/arm/boot/dts/tegra30-cardhu-a04.dts      |  44 ++
 .../arm/boot/dts/tegra30-peripherals-opp.dtsi | 415 ++++++++++++++++++
 arch/arm/boot/dts/tegra30.dtsi                |  13 +
 drivers/gpu/drm/tegra/Kconfig                 |   1 +
 drivers/gpu/drm/tegra/dc.c                    | 138 +++++-
 drivers/gpu/drm/tegra/dc.h                    |   5 +
 drivers/gpu/drm/tegra/gr2d.c                  | 140 +++++-
 drivers/gpu/drm/tegra/gr3d.c                  | 136 ++++++
 drivers/gpu/drm/tegra/hdmi.c                  |  63 ++-
 drivers/gpu/host1x/Kconfig                    |   1 +
 drivers/gpu/host1x/dev.c                      |  87 ++++
 drivers/memory/tegra/tegra20-emc.c            |   8 +-
 drivers/memory/tegra/tegra30-emc.c            |   8 +-
 drivers/mmc/host/Kconfig                      |   1 +
 drivers/mmc/host/sdhci-tegra.c                |  70 ++-
 drivers/pwm/Kconfig                           |   1 +
 drivers/pwm/pwm-tegra.c                       |  84 +++-
 drivers/regulator/core.c                      |  12 +-
 .../soc/samsung/exynos-regulator-coupler.c    |   2 +-
 drivers/soc/tegra/common.c                    | 152 ++++++-
 drivers/soc/tegra/regulators-tegra20.c        |  25 +-
 drivers/soc/tegra/regulators-tegra30.c        |  30 +-
 drivers/staging/media/tegra-vde/Kconfig       |   1 +
 drivers/staging/media/tegra-vde/vde.c         | 127 ++++++
 drivers/staging/media/tegra-vde/vde.h         |   1 +
 drivers/usb/chipidea/Kconfig                  |   1 +
 drivers/usb/chipidea/ci_hdrc_tegra.c          |  79 ++++
 drivers/usb/host/Kconfig                      |   1 +
 drivers/usb/host/ehci-tegra.c                 |  79 ++++
 include/linux/regulator/coupler.h             |   6 +-
 include/soc/tegra/common.h                    |  22 +
 43 files changed, 2360 insertions(+), 50 deletions(-)

-- 
2.27.0


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

* [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
@ 2020-11-04 23:43 ` Dmitry Osipenko
  2020-11-09 18:57   ` Rob Herring
  2020-11-11 11:45   ` Ulf Hansson
  2020-11-04 23:43 ` [PATCH v1 02/30] dt-bindings: mmc: tegra: " Dmitry Osipenko
                   ` (31 subsequent siblings)
  32 siblings, 2 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:43 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Document new DVFS OPP table and voltage regulator properties of the
Host1x bus and devices sitting on the bus.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../display/tegra/nvidia,tegra20-host1x.txt   | 56 +++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 34d993338453..0593c8df70bb 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -20,6 +20,18 @@ Required properties:
 - reset-names: Must include the following entries:
   - host1x
 
+Optional properties:
+- operating-points-v2: See ../bindings/opp/opp.txt for details.
+- core-supply: Phandle of voltage regulator of the SoC "core" power domain.
+
+For each opp entry in 'operating-points-v2' table of host1x and its modules:
+- opp-supported-hw: One bitfield indicating:
+	On Tegra20: SoC process ID mask
+	On Tegra30+: SoC speedo ID mask
+
+	A bitwise AND is performed against the value and if any bit
+	matches, the OPP gets enabled.
+
 Each host1x client module having to perform DMA through the Memory Controller
 should have the interconnect endpoints set to the Memory Client and External
 Memory respectively.
@@ -45,6 +57,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
     interconnect entry. Consult TRM documentation for information about
     available memory clients, see MEMORY CONTROLLER section.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
 
 - vi: video input
 
@@ -128,6 +142,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
     interconnect entry. Consult TRM documentation for information about
     available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 - epp: encoder pre-processor
 
@@ -147,6 +163,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
     interconnect entry. Consult TRM documentation for information about
     available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 - isp: image signal processor
 
@@ -166,6 +184,7 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
     interconnect entry. Consult TRM documentation for information about
     available memory clients, see MEMORY CONTROLLER section.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 - gr2d: 2D graphics engine
 
@@ -185,6 +204,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
     interconnect entry. Consult TRM documentation for information about
     available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 - gr3d: 3D graphics engine
 
@@ -209,6 +230,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
     interconnect entry. Consult TRM documentation for information about
     available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 - dc: display controller
 
@@ -241,6 +264,8 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
     interconnect entry. Consult TRM documentation for information about
     available memory clients, see MEMORY CONTROLLER section.
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 - hdmi: High Definition Multimedia Interface
 
@@ -267,6 +292,8 @@ of the following host1x client modules:
   - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
   - nvidia,edid: supplies a binary EDID blob
   - nvidia,panel: phandle of a display panel
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 - tvo: TV encoder output
 
@@ -277,6 +304,10 @@ of the following host1x client modules:
   - clocks: Must contain one entry, for the module clock.
     See ../clocks/clock-bindings.txt for details.
 
+  Optional properties:
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
+
 - dsi: display serial interface
 
   Required properties:
@@ -305,6 +336,8 @@ of the following host1x client modules:
   - nvidia,panel: phandle of a display panel
   - nvidia,ganged-mode: contains a phandle to a second DSI controller to gang
     up with in order to support up to 8 data lanes
+  - operating-points-v2: See ../bindings/opp/opp.txt for details.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 - sor: serial output resource
 
@@ -394,6 +427,7 @@ of the following host1x client modules:
   - interconnect-names: Must include name of the interconnect path for each
     interconnect entry. Consult TRM documentation for information about
     available memory clients, see MEMORY CONTROLLER section.
+  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
 
 Example:
 
@@ -408,6 +442,8 @@ Example:
 		clocks = <&tegra_car TEGRA20_CLK_HOST1X>;
 		resets = <&tegra_car 28>;
 		reset-names = "host1x";
+		operating-points-v2 = <&dvfs_opp_table>;
+		core-supply = <&vdd_core>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -421,6 +457,8 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_MPE>;
 			resets = <&tegra_car 60>;
 			reset-names = "mpe";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 		};
 
 		vi@54080000 {
@@ -429,6 +467,8 @@ Example:
 			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
 			assigned-clocks = <&tegra_car TEGRA210_CLK_VI>;
 			assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>;
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 
 			clocks = <&tegra_car TEGRA210_CLK_VI>;
 			power-domains = <&pd_venc>;
@@ -510,6 +550,8 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_EPP>;
 			resets = <&tegra_car 19>;
 			reset-names = "epp";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 		};
 
 		isp {
@@ -528,6 +570,8 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_GR2D>;
 			resets = <&tegra_car 21>;
 			reset-names = "2d";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 		};
 
 		gr3d {
@@ -536,6 +580,8 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_GR3D>;
 			resets = <&tegra_car 24>;
 			reset-names = "3d";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 		};
 
 		dc@54200000 {
@@ -547,6 +593,8 @@ Example:
 			clock-names = "dc", "parent";
 			resets = <&tegra_car 27>;
 			reset-names = "dc";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 
 			interconnects = <&mc TEGRA20_MC_DISPLAY0A &emc>,
 					<&mc TEGRA20_MC_DISPLAY0B &emc>,
@@ -571,6 +619,8 @@ Example:
 			clock-names = "dc", "parent";
 			resets = <&tegra_car 26>;
 			reset-names = "dc";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 
 			interconnects = <&mc TEGRA20_MC_DISPLAY0AB &emc>,
 					<&mc TEGRA20_MC_DISPLAY0BB &emc>,
@@ -596,6 +646,8 @@ Example:
 			resets = <&tegra_car 51>;
 			reset-names = "hdmi";
 			status = "disabled";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 		};
 
 		tvo {
@@ -604,6 +656,8 @@ Example:
 			interrupts = <0 76 0x04>;
 			clocks = <&tegra_car TEGRA20_CLK_TVO>;
 			status = "disabled";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 		};
 
 		dsi {
@@ -615,6 +669,8 @@ Example:
 			resets = <&tegra_car 48>;
 			reset-names = "dsi";
 			status = "disabled";
+			operating-points-v2 = <&dvfs_opp_table>;
+			core-supply = <&vdd_core>;
 		};
 	};
 
-- 
2.27.0


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

* [PATCH v1 02/30] dt-bindings: mmc: tegra: Document OPP and voltage regulator properties
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
  2020-11-04 23:43 ` [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties Dmitry Osipenko
@ 2020-11-04 23:43 ` Dmitry Osipenko
  2020-11-09 18:58   ` Rob Herring
  2020-11-04 23:44 ` [PATCH v1 03/30] dt-bindings: pwm: " Dmitry Osipenko
                   ` (30 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:43 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Document new DVFS OPP table and voltage regulator properties of the
SDHCI controller.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
index 96c0b1440c9c..1beb0416ae5f 100644
--- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -31,6 +31,16 @@ Required properties:
 
 Optional properties:
 - power-gpios : Specify GPIOs for power control
+- operating-points-v2: See ../bindings/opp/opp.txt for details.
+- core-supply: Phandle of voltage regulator of the SoC "core" power domain.
+
+For each opp entry in 'operating-points-v2' table:
+- opp-supported-hw: One bitfield indicating:
+	On Tegra20: SoC process ID mask
+	On Tegra30+: SoC speedo ID mask
+
+	A bitwise AND is performed against the value and if any bit
+	matches, the OPP gets enabled.
 
 Example:
 
@@ -45,6 +55,8 @@ sdhci@c8000200 {
 	wp-gpios = <&gpio 57 0>; /* gpio PH1 */
 	power-gpios = <&gpio 155 0>; /* gpio PT3 */
 	bus-width = <8>;
+	operating-points-v2 = <&dvfs_opp_table>;
+	core-supply = <&vdd_core>;
 };
 
 Optional properties for Tegra210, Tegra186 and Tegra194:
-- 
2.27.0


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

* [PATCH v1 03/30] dt-bindings: pwm: tegra: Document OPP and voltage regulator properties
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
  2020-11-04 23:43 ` [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties Dmitry Osipenko
  2020-11-04 23:43 ` [PATCH v1 02/30] dt-bindings: mmc: tegra: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-09 19:00   ` Rob Herring
  2020-11-04 23:44 ` [PATCH v1 04/30] media: dt: bindings: tegra-vde: " Dmitry Osipenko
                   ` (29 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Document new DVFS OPP table and voltage regulator properties of the
PWM controller.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../devicetree/bindings/pwm/nvidia,tegra20-pwm.txt  | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
index 74c41e34c3b6..d4d1c44a2c04 100644
--- a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
@@ -32,6 +32,17 @@ The PWM node will have following optional properties.
 pinctrl-names:	Pin state names. Must be "default" and "sleep".
 pinctrl-0:	phandle for the default/active state of pin configurations.
 pinctrl-1:	phandle for the sleep state of pin configurations.
+core-supply:	phandle for voltage regulator of the SoC "core" power domain.
+
+operating-points-v2: see ../bindings/opp/opp.txt for details.
+
+For each opp entry in 'operating-points-v2' table:
+- opp-supported-hw: One bitfield indicating:
+	On Tegra20: SoC process ID mask
+	On Tegra30+: SoC speedo ID mask
+
+	A bitwise AND is performed against the value and if any bit
+	matches, the OPP gets enabled.
 
 Example:
 
@@ -42,6 +53,8 @@ Example:
 		clocks = <&tegra_car 17>;
 		resets = <&tegra_car 17>;
 		reset-names = "pwm";
+		operating-points-v2 = <&dvfs_opp_table>;
+		core-supply = <&vdd_core>;
 	};
 
 
-- 
2.27.0


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

* [PATCH v1 04/30] media: dt: bindings: tegra-vde: Document OPP and voltage regulator properties
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 03/30] dt-bindings: pwm: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-09 19:01   ` Rob Herring
  2020-11-04 23:44 ` [PATCH v1 05/30] dt-binding: usb: ci-hdrc-usb2: " Dmitry Osipenko
                   ` (28 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Document new DVFS OPP table and voltage regulator properties of the
video decoder engine.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../devicetree/bindings/media/nvidia,tegra-vde.txt   | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
index 602169b8aa19..9854fa9d3cd3 100644
--- a/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
+++ b/Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
@@ -36,6 +36,16 @@ Optional properties:
 - reset-names : Must include the following entries:
   - mc
 - iommus: Must contain phandle to the IOMMU device node.
+- operating-points-v2: See ../bindings/opp/opp.txt for details.
+- core-supply: Phandle to voltage regulator of the SoC "core" power domain.
+
+For each opp entry in 'operating-points-v2' table:
+- opp-supported-hw: One bitfield indicating:
+	On Tegra20: SoC process ID mask
+	On Tegra30+: SoC speedo ID mask
+
+	A bitwise AND is performed against the value and if any bit
+	matches, the OPP gets enabled.
 
 Example:
 
@@ -61,4 +71,6 @@ video-codec@6001a000 {
 	reset-names = "vde", "mc";
 	resets = <&tegra_car 61>, <&mc TEGRA20_MC_RESET_VDE>;
 	iommus = <&mc TEGRA_SWGROUP_VDE>;
+	operating-points-v2 = <&dvfs_opp_table>;
+	core-supply = <&vdd_core>;
 };
-- 
2.27.0


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

* [PATCH v1 05/30] dt-binding: usb: ci-hdrc-usb2:  Document OPP and voltage regulator properties
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (3 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 04/30] media: dt: bindings: tegra-vde: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-09 19:01   ` Rob Herring
  2020-11-04 23:44 ` [PATCH v1 06/30] dt-bindings: usb: tegra-ehci: " Dmitry Osipenko
                   ` (27 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Document new OPP table and NVIDIA Tegra-specific voltage regulator
properties.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index a5c5db6a0b2d..f02a98201062 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -90,6 +90,7 @@ Optional properties:
   case, the "idle" state needs to pull down the data and strobe pin
   and the "active" state needs to pull up the strobe pin.
 - pinctrl-n: alternate pin modes
+- operating-points-v2: See ../bindings/opp/opp.txt for details.
 
 i.mx specific properties
 - fsl,usbmisc: phandler of non-core register device, with one
@@ -110,6 +111,9 @@ i.mx specific properties
   The range is from 0x0 to 0xf, the default value is 0x3.
   Details can refer to TXVREFTUNE0 bits of USBNC_n_PHY_CFG1.
 
+Tegra specific properties
+- core-supply: phandle of voltage regulator of the SoC "core" power domain
+
 Example:
 
 	usb@f7ed0000 {
-- 
2.27.0


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

* [PATCH v1 06/30] dt-bindings: usb: tegra-ehci: Document OPP and voltage regulator properties
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (4 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 05/30] dt-binding: usb: ci-hdrc-usb2: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-09 19:01   ` Rob Herring
  2020-11-04 23:44 ` [PATCH v1 07/30] soc/tegra: Add sync state API Dmitry Osipenko
                   ` (26 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Document new DVFS OPP table and voltage regulator properties of the
Tegra EHCI controller.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
index f60785f73d3d..e4070ae21fd9 100644
--- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
@@ -21,3 +21,5 @@ Required properties :
 Optional properties:
  - nvidia,needs-double-reset : boolean is to be set for some of the Tegra20
    USB ports, which need reset twice due to hardware issues.
+ - operating-points-v2: See ../bindings/opp/opp.txt for details.
+ - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
-- 
2.27.0


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

* [PATCH v1 07/30] soc/tegra: Add sync state API
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (5 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 06/30] dt-bindings: usb: tegra-ehci: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-10 20:47   ` Thierry Reding
  2020-11-04 23:44 ` [PATCH v1 08/30] soc/tegra: regulators: Support Tegra SoC device " Dmitry Osipenko
                   ` (25 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Introduce sync state API that will be used by Tegra device drivers. This
new API is primarily needed for syncing state of SoC devices that are left
ON after bootloader or permanently enabled. All these devices belong to a
shared CORE voltage domain, and thus, we needed to bring all the devices
into expected state before the voltage scaling could be performed.

All drivers of DVFS-critical devices shall sync theirs the state before
Tegra's voltage regulator coupler will be allowed to perform a system-wide
voltage scaling.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/soc/tegra/common.c | 152 ++++++++++++++++++++++++++++++++++++-
 include/soc/tegra/common.h |  22 ++++++
 2 files changed, 170 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index 3dc54f59cafe..f9b2b6f57887 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -3,13 +3,52 @@
  * Copyright (C) 2014 NVIDIA CORPORATION.  All rights reserved.
  */
 
+#define dev_fmt(fmt)	"%s: " fmt, __func__
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <soc/tegra/common.h>
 
+#define terga_soc_for_each_device(__dev) \
+	for ((__dev) = tegra_soc_devices; (__dev) && (__dev)->compatible; \
+	     (__dev)++)
+
+struct tegra_soc_device {
+	const char *compatible;
+	const bool dvfs_critical;
+	unsigned int sync_count;
+};
+
+static DEFINE_MUTEX(tegra_soc_lock);
+static struct tegra_soc_device *tegra_soc_devices;
+
+/*
+ * DVFS-critical devices are either active at a boot time or permanently
+ * active, like EMC for example.  System-wide DVFS should be deferred until
+ * drivers of the critical devices synced theirs state.
+ */
+
+static struct tegra_soc_device tegra20_soc_devices[] = {
+	{ .compatible = "nvidia,tegra20-dc", .dvfs_critical = true, },
+	{ .compatible = "nvidia,tegra20-emc", .dvfs_critical = true, },
+	{ }
+};
+
+static struct tegra_soc_device tegra30_soc_devices[] = {
+	{ .compatible = "nvidia,tegra30-dc", .dvfs_critical = true, },
+	{ .compatible = "nvidia,tegra30-emc", .dvfs_critical = true, },
+	{ .compatible = "nvidia,tegra30-pwm", .dvfs_critical = true, },
+	{ }
+};
+
 static const struct of_device_id tegra_machine_match[] = {
-	{ .compatible = "nvidia,tegra20", },
-	{ .compatible = "nvidia,tegra30", },
+	{ .compatible = "nvidia,tegra20", .data = tegra20_soc_devices, },
+	{ .compatible = "nvidia,tegra30", .data = tegra30_soc_devices, },
 	{ .compatible = "nvidia,tegra114", },
 	{ .compatible = "nvidia,tegra124", },
 	{ .compatible = "nvidia,tegra132", },
@@ -17,7 +56,7 @@ static const struct of_device_id tegra_machine_match[] = {
 	{ }
 };
 
-bool soc_is_tegra(void)
+static const struct of_device_id *tegra_soc_of_match(void)
 {
 	const struct of_device_id *match;
 	struct device_node *root;
@@ -29,5 +68,110 @@ bool soc_is_tegra(void)
 	match = of_match_node(tegra_machine_match, root);
 	of_node_put(root);
 
-	return match != NULL;
+	return match;
+}
+
+bool soc_is_tegra(void)
+{
+	return tegra_soc_of_match() != NULL;
+}
+
+void tegra_soc_device_sync_state(struct device *dev)
+{
+	struct tegra_soc_device *soc_dev;
+
+	mutex_lock(&tegra_soc_lock);
+	terga_soc_for_each_device(soc_dev) {
+		if (!of_device_is_compatible(dev->of_node, soc_dev->compatible))
+			continue;
+
+		if (!soc_dev->sync_count) {
+			dev_err(dev, "already synced\n");
+			break;
+		}
+
+		/*
+		 * All DVFS-capable devices should have the CORE regulator
+		 * phandle.  Older device-trees don't have it, hence state
+		 * won't be synced for the older DTBs, allowing them to work
+		 * properly.
+		 */
+		if (soc_dev->dvfs_critical &&
+		    !device_property_present(dev, "core-supply")) {
+			dev_dbg(dev, "doesn't have core supply\n");
+			break;
+		}
+
+		soc_dev->sync_count--;
+		dev_dbg(dev, "sync_count=%u\n", soc_dev->sync_count);
+		break;
+	}
+	mutex_unlock(&tegra_soc_lock);
+}
+EXPORT_SYMBOL_GPL(tegra_soc_device_sync_state);
+
+bool tegra_soc_dvfs_state_synced(void)
+{
+	struct tegra_soc_device *soc_dev;
+	bool synced_state = true;
+
+	/*
+	 * CORE voltage scaling is limited until drivers of the critical
+	 * devices synced theirs state.
+	 */
+	mutex_lock(&tegra_soc_lock);
+	terga_soc_for_each_device(soc_dev) {
+		if (!soc_dev->sync_count || !soc_dev->dvfs_critical)
+			continue;
+
+		pr_debug_ratelimited("%s: sync_count=%u\n",
+				     soc_dev->compatible, soc_dev->sync_count);
+
+		synced_state = false;
+		break;
+	}
+	mutex_unlock(&tegra_soc_lock);
+
+	return synced_state;
+}
+
+static int __init tegra_soc_devices_init(void)
+{
+	struct device_node *np, *prev_np = NULL;
+	struct tegra_soc_device *soc_dev;
+	const struct of_device_id *match;
+
+	if (!soc_is_tegra())
+		return 0;
+
+	match = tegra_soc_of_match();
+	tegra_soc_devices = (void *)match->data;
+
+	/*
+	 * If device node is disabled in a device-tree, then we shouldn't
+	 * care about this device. Even if device is active during boot,
+	 * its clock will be disabled by CCF as unused.
+	 */
+	terga_soc_for_each_device(soc_dev) {
+		do {
+			/*
+			 * Devices like display controller have multiple
+			 * instances with the same compatible. Hence we need
+			 * to walk up the whole tree in order to account those
+			 * multiple instances.
+			 */
+			np = of_find_compatible_node(prev_np, NULL,
+						     soc_dev->compatible);
+			of_node_put(prev_np);
+			prev_np = np;
+
+			if (of_device_is_available(np)) {
+				pr_debug("added %s\n", soc_dev->compatible);
+				soc_dev->sync_count++;
+			}
+		} while (np);
+	}
+
+	return 0;
 }
+postcore_initcall_sync(tegra_soc_devices_init);
diff --git a/include/soc/tegra/common.h b/include/soc/tegra/common.h
index 98027a76ce3d..d3ddb96d0fe2 100644
--- a/include/soc/tegra/common.h
+++ b/include/soc/tegra/common.h
@@ -6,6 +6,28 @@
 #ifndef __SOC_TEGRA_COMMON_H__
 #define __SOC_TEGRA_COMMON_H__
 
+#include <linux/types.h>
+
+struct device;
+
+#ifdef CONFIG_ARCH_TEGRA
 bool soc_is_tegra(void);
+void tegra_soc_device_sync_state(struct device *dev);
+bool tegra_soc_dvfs_state_synced(void);
+#else
+static inline bool soc_is_tegra(void)
+{
+	return false;
+}
+
+static inline void tegra_soc_device_sync_state(struct device *dev)
+{
+}
+
+static inline tegra_soc_dvfs_state_synced(void)
+{
+	return false;
+}
+#endif
 
 #endif /* __SOC_TEGRA_COMMON_H__ */
-- 
2.27.0


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

* [PATCH v1 08/30] soc/tegra: regulators: Support Tegra SoC device sync state API
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (6 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 07/30] soc/tegra: Add sync state API Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 09/30] soc/tegra: regulators: Fix lockup when voltage-spread is out of range Dmitry Osipenko
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Downscale of the CORE voltage isn't allowed because some hardware units,
which are supplied by the CORE regulator, usually left ON at a boot time.
The new sync state API resolves this problem for us. All drivers of the
devices that are known to be ON at a boot time now should sync theirs
state. Once everything is synced, the voltage of the CORE domain could
be scaled without any limitations.

Make Tegra20/30 regulator couplers to use the new sync state API.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/soc/tegra/regulators-tegra20.c | 19 ++++++++++++++++++-
 drivers/soc/tegra/regulators-tegra30.c | 22 +++++++++++++++++++++-
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/regulators-tegra20.c b/drivers/soc/tegra/regulators-tegra20.c
index 367a71a3cd10..8782e399a58c 100644
--- a/drivers/soc/tegra/regulators-tegra20.c
+++ b/drivers/soc/tegra/regulators-tegra20.c
@@ -16,6 +16,8 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 
+#include <soc/tegra/common.h>
+
 struct tegra_regulator_coupler {
 	struct regulator_coupler coupler;
 	struct regulator_dev *core_rdev;
@@ -38,6 +40,21 @@ static int tegra20_core_limit(struct tegra_regulator_coupler *tegra,
 	int core_cur_uV;
 	int err;
 
+	/*
+	 * Tegra20 SoC has critical DVFS-capable devices that are
+	 * permanently-active or active at a boot time, like EMC
+	 * (DRAM controller) or Host1x bus for example.
+	 *
+	 * The voltage of a CORE SoC power domain shall not be dropped below
+	 * a minimum level, which is determined by device's clock rate.
+	 * This means that we can't fully allow CORE voltage scaling until
+	 * the state of all DVFS-critical CORE devices is synced.
+	 */
+	if (tegra_soc_dvfs_state_synced()) {
+		pr_info_once("voltage state synced\n");
+		return 0;
+	}
+
 	if (tegra->core_min_uV > 0)
 		return tegra->core_min_uV;
 
@@ -58,7 +75,7 @@ static int tegra20_core_limit(struct tegra_regulator_coupler *tegra,
 	 */
 	tegra->core_min_uV = core_max_uV;
 
-	pr_info("core minimum voltage limited to %duV\n", tegra->core_min_uV);
+	pr_info("core voltage initialized to %duV\n", tegra->core_min_uV);
 
 	return tegra->core_min_uV;
 }
diff --git a/drivers/soc/tegra/regulators-tegra30.c b/drivers/soc/tegra/regulators-tegra30.c
index 7f21f31de09d..f7a5260edffe 100644
--- a/drivers/soc/tegra/regulators-tegra30.c
+++ b/drivers/soc/tegra/regulators-tegra30.c
@@ -16,6 +16,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 
+#include <soc/tegra/common.h>
 #include <soc/tegra/fuse.h>
 
 struct tegra_regulator_coupler {
@@ -39,6 +40,21 @@ static int tegra30_core_limit(struct tegra_regulator_coupler *tegra,
 	int core_cur_uV;
 	int err;
 
+	/*
+	 * Tegra30 SoC has critical DVFS-capable devices that are
+	 * permanently-active or active at a boot time, like EMC
+	 * (DRAM controller) or Host1x bus for example.
+	 *
+	 * The voltage of a CORE SoC power domain shall not be dropped below
+	 * a minimum level, which is determined by device's clock rate.
+	 * This means that we can't fully allow CORE voltage scaling until
+	 * the state of all DVFS-critical CORE devices is synced.
+	 */
+	if (tegra_soc_dvfs_state_synced()) {
+		pr_info_once("voltage state synced\n");
+		return 0;
+	}
+
 	if (tegra->core_min_uV > 0)
 		return tegra->core_min_uV;
 
@@ -59,7 +75,7 @@ static int tegra30_core_limit(struct tegra_regulator_coupler *tegra,
 	 */
 	tegra->core_min_uV = core_max_uV;
 
-	pr_info("core minimum voltage limited to %duV\n", tegra->core_min_uV);
+	pr_info("core voltage initialized to %duV\n", tegra->core_min_uV);
 
 	return tegra->core_min_uV;
 }
@@ -143,6 +159,10 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,
 	if (core_min_uV < 0)
 		return core_min_uV;
 
+	err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV);
+	if (err)
+		return err;
+
 	err = regulator_check_consumers(core_rdev, &core_min_uV, &core_max_uV,
 					PM_SUSPEND_ON);
 	if (err)
-- 
2.27.0


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

* [PATCH v1 09/30] soc/tegra: regulators: Fix lockup when voltage-spread is out of range
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (7 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 08/30] soc/tegra: regulators: Support Tegra SoC device " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 10/30] regulator: Allow skipping disabled regulators in regulator_check_consumers() Dmitry Osipenko
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Fix voltage coupler lockup which happens when voltage-spread is out
of range due to a bug in the code. The max-spread requirement shall be
accounted when CPU regulator doesn't have consumers. This problem is
observed on Tegra30 Ouya game console once system-wide DVFS is enabled
in a device-tree.

Fixes: 783807436f36 ("soc/tegra: regulators: Add regulators coupler for Tegra30")
Cc: stable@vger.kernel.org
Tested-by: Peter Geis <pgwipeout@gmail.com>
Reported-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/soc/tegra/regulators-tegra30.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soc/tegra/regulators-tegra30.c b/drivers/soc/tegra/regulators-tegra30.c
index f7a5260edffe..fcf824f73131 100644
--- a/drivers/soc/tegra/regulators-tegra30.c
+++ b/drivers/soc/tegra/regulators-tegra30.c
@@ -198,7 +198,7 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,
 	 * survive the voltage drop if it's running on a higher frequency.
 	 */
 	if (!cpu_min_uV_consumers)
-		cpu_min_uV = cpu_uV;
+		cpu_min_uV = max(cpu_uV, cpu_min_uV);
 
 	/*
 	 * Bootloader shall set up voltages correctly, but if it
-- 
2.27.0


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

* [PATCH v1 10/30] regulator: Allow skipping disabled regulators in regulator_check_consumers()
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (8 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 09/30] soc/tegra: regulators: Fix lockup when voltage-spread is out of range Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling Dmitry Osipenko
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add option which allows regulator_check_consumers() to skip accounting of
a disabled consumer regulators.

This new option is needed for the NVIDIA Tegra voltage couplers in order
to properly calculate a lowest possible voltage for the CORE regulator.
The requirements of a disabled consumer regulators should not be accounted
by the Tegra voltage balancers because disabled state means that hardware
is inactive. In particular disabled state shouldn't be accounted for the
consumers which belong to the CORE voltage domain, meanwhile CPU domain
should continue to account the disabled state.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/regulator/core.c                       | 12 ++++++++----
 drivers/soc/samsung/exynos-regulator-coupler.c |  2 +-
 drivers/soc/tegra/regulators-tegra20.c         |  6 +++---
 drivers/soc/tegra/regulators-tegra30.c         |  6 +++---
 include/linux/regulator/coupler.h              |  6 ++++--
 5 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index f258ded39ce0..015dcd8408d9 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -462,7 +462,8 @@ static int regulator_check_states(suspend_state_t state)
  */
 int regulator_check_consumers(struct regulator_dev *rdev,
 			      int *min_uV, int *max_uV,
-			      suspend_state_t state)
+			      suspend_state_t state,
+			      bool skip_disabled_regulators)
 {
 	struct regulator *regulator;
 	struct regulator_voltage *voltage;
@@ -476,6 +477,9 @@ int regulator_check_consumers(struct regulator_dev *rdev,
 		if (!voltage->min_uV && !voltage->max_uV)
 			continue;
 
+		if (skip_disabled_regulators && !regulator->enable_count)
+			continue;
+
 		if (*max_uV > voltage->max_uV)
 			*max_uV = voltage->max_uV;
 		if (*min_uV < voltage->min_uV)
@@ -3662,7 +3666,7 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
 
 		ret = regulator_check_consumers(rdev,
 						&desired_min_uV,
-						&desired_max_uV, state);
+						&desired_max_uV, state, false);
 		if (ret < 0)
 			return ret;
 
@@ -3681,7 +3685,7 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
 
 		ret = regulator_check_consumers(c_rdevs[i],
 						&tmp_min,
-						&tmp_max, state);
+						&tmp_max, state, false);
 		if (ret < 0)
 			return ret;
 
@@ -4119,7 +4123,7 @@ int regulator_sync_voltage(struct regulator *regulator)
 	if (ret < 0)
 		goto out;
 
-	ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0);
+	ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0, false);
 	if (ret < 0)
 		goto out;
 
diff --git a/drivers/soc/samsung/exynos-regulator-coupler.c b/drivers/soc/samsung/exynos-regulator-coupler.c
index 61a156b44a48..9bd99a93e3e0 100644
--- a/drivers/soc/samsung/exynos-regulator-coupler.c
+++ b/drivers/soc/samsung/exynos-regulator-coupler.c
@@ -41,7 +41,7 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
 
 		ret = regulator_check_consumers(c_rdevs[i],
 						&tmp_min,
-						&tmp_max, state);
+						&tmp_max, state, false);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/soc/tegra/regulators-tegra20.c b/drivers/soc/tegra/regulators-tegra20.c
index 8782e399a58c..8c31acb5fdc6 100644
--- a/drivers/soc/tegra/regulators-tegra20.c
+++ b/drivers/soc/tegra/regulators-tegra20.c
@@ -136,7 +136,7 @@ static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra,
 		return err;
 
 	err = regulator_check_consumers(core_rdev, &core_min_uV, &core_max_uV,
-					PM_SUSPEND_ON);
+					PM_SUSPEND_ON, true);
 	if (err)
 		return err;
 
@@ -246,12 +246,12 @@ static int tegra20_cpu_voltage_update(struct tegra_regulator_coupler *tegra,
 		return err;
 
 	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV, &cpu_max_uV,
-					PM_SUSPEND_ON);
+					PM_SUSPEND_ON, false);
 	if (err)
 		return err;
 
 	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV_consumers,
-					&cpu_max_uV, PM_SUSPEND_ON);
+					&cpu_max_uV, PM_SUSPEND_ON, false);
 	if (err)
 		return err;
 
diff --git a/drivers/soc/tegra/regulators-tegra30.c b/drivers/soc/tegra/regulators-tegra30.c
index fcf824f73131..d92aafa736bc 100644
--- a/drivers/soc/tegra/regulators-tegra30.c
+++ b/drivers/soc/tegra/regulators-tegra30.c
@@ -164,7 +164,7 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,
 		return err;
 
 	err = regulator_check_consumers(core_rdev, &core_min_uV, &core_max_uV,
-					PM_SUSPEND_ON);
+					PM_SUSPEND_ON, true);
 	if (err)
 		return err;
 
@@ -175,12 +175,12 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra,
 	cpu_min_uV = core_min_uV - max_spread;
 
 	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV, &cpu_max_uV,
-					PM_SUSPEND_ON);
+					PM_SUSPEND_ON, false);
 	if (err)
 		return err;
 
 	err = regulator_check_consumers(cpu_rdev, &cpu_min_uV_consumers,
-					&cpu_max_uV, PM_SUSPEND_ON);
+					&cpu_max_uV, PM_SUSPEND_ON, false);
 	if (err)
 		return err;
 
diff --git a/include/linux/regulator/coupler.h b/include/linux/regulator/coupler.h
index 5f86824bd117..4e076567b823 100644
--- a/include/linux/regulator/coupler.h
+++ b/include/linux/regulator/coupler.h
@@ -55,7 +55,8 @@ int regulator_coupler_register(struct regulator_coupler *coupler);
 const char *rdev_get_name(struct regulator_dev *rdev);
 int regulator_check_consumers(struct regulator_dev *rdev,
 			      int *min_uV, int *max_uV,
-			      suspend_state_t state);
+			      suspend_state_t state,
+			      bool skip_disabled_regulators);
 int regulator_check_voltage(struct regulator_dev *rdev,
 			    int *min_uV, int *max_uV);
 int regulator_get_voltage_rdev(struct regulator_dev *rdev);
@@ -75,7 +76,8 @@ static inline const char *rdev_get_name(struct regulator_dev *rdev)
 }
 static inline int regulator_check_consumers(struct regulator_dev *rdev,
 					    int *min_uV, int *max_uV,
-					    suspend_state_t state)
+					    suspend_state_t state,
+					    bool skip_disabled_regulators))
 {
 	return -EINVAL;
 }
-- 
2.27.0


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

* [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (9 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 10/30] regulator: Allow skipping disabled regulators in regulator_check_consumers() Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-10 20:29   ` Thierry Reding
  2020-11-04 23:44 ` [PATCH v1 12/30] drm/tegra: gr2d: Correct swapped device-tree compatibles Dmitry Osipenko
                   ` (21 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add OPP and SoC core voltage scaling support to the display controller
driver. This is required for enabling system-wide DVFS on older Tegra
SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/Kconfig |   1 +
 drivers/gpu/drm/tegra/dc.c    | 138 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/tegra/dc.h    |   5 ++
 3 files changed, 143 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index 1650a448eabd..9eec4c3fbd3b 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -12,6 +12,7 @@ config DRM_TEGRA
 	select INTERCONNECT
 	select IOMMU_IOVA
 	select CEC_CORE if CEC_NOTIFIER
+	select PM_OPP
 	help
 	  Choose this option if you have an NVIDIA Tegra SoC.
 
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index fd7c8828652d..babcb66a335b 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -11,9 +11,13 @@
 #include <linux/interconnect.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pm_opp.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 
+#include <soc/tegra/common.h>
+#include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
 #include <drm/drm_atomic.h>
@@ -1699,6 +1703,55 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
 	return 0;
 }
 
+static void tegra_dc_update_voltage_state(struct tegra_dc *dc,
+					  struct tegra_dc_state *state)
+{
+	struct dev_pm_opp *opp;
+	unsigned long rate;
+	int err, min_uV;
+
+	/* OPP usage is optional */
+	if (!dc->opp_table)
+		return;
+
+	/* calculate actual pixel clock rate which depends on internal divider */
+	rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);
+
+	/* find suitable OPP for the rate */
+	opp = dev_pm_opp_find_freq_ceil(dc->dev, &rate);
+
+	if (opp == ERR_PTR(-ERANGE))
+		opp = dev_pm_opp_find_freq_floor(dc->dev, &rate);
+
+	if (IS_ERR(opp)) {
+		dev_err(dc->dev, "failed to find OPP for %lu Hz: %ld\n",
+			rate, PTR_ERR(opp));
+		return;
+	}
+
+	min_uV = dev_pm_opp_get_voltage(opp);
+	dev_pm_opp_put(opp);
+
+	/*
+	 * Voltage scaling is optional and trying to set voltage for a dummy
+	 * regulator will error out.
+	 */
+	if (!device_property_present(dc->dev, "core-supply"))
+		return;
+
+	/*
+	 * Note that the minimum core voltage depends on the pixel clock
+	 * rate (which depends on internal clock divider of CRTC) and not on
+	 * the rate of the display controller clock. This is why we're not
+	 * using dev_pm_opp_set_rate() API and instead are managing the
+	 * voltage by ourselves.
+	 */
+	err = regulator_set_voltage(dc->core_reg, min_uV, INT_MAX);
+	if (err)
+		dev_err(dc->dev, "failed to set CORE voltage to %duV: %d\n",
+			min_uV, err);
+}
+
 static void tegra_dc_commit_state(struct tegra_dc *dc,
 				  struct tegra_dc_state *state)
 {
@@ -1738,6 +1791,8 @@ static void tegra_dc_commit_state(struct tegra_dc *dc,
 	if (err < 0)
 		dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
 			dc->clk, state->pclk, err);
+
+	tegra_dc_update_voltage_state(dc, state);
 }
 
 static void tegra_dc_stop(struct tegra_dc *dc)
@@ -2521,6 +2576,7 @@ static int tegra_dc_runtime_suspend(struct host1x_client *client)
 
 	clk_disable_unprepare(dc->clk);
 	pm_runtime_put_sync(dev);
+	regulator_disable(dc->core_reg);
 
 	return 0;
 }
@@ -2531,10 +2587,16 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
 	struct device *dev = client->dev;
 	int err;
 
+	err = regulator_enable(dc->core_reg);
+	if (err < 0) {
+		dev_err(dev, "failed to enable CORE regulator: %d\n", err);
+		return err;
+	}
+
 	err = pm_runtime_get_sync(dev);
 	if (err < 0) {
 		dev_err(dev, "failed to get runtime PM: %d\n", err);
-		return err;
+		goto disable_regulator;
 	}
 
 	if (dc->soc->has_powergate) {
@@ -2564,6 +2626,9 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
 	clk_disable_unprepare(dc->clk);
 put_rpm:
 	pm_runtime_put_sync(dev);
+disable_regulator:
+	regulator_disable(dc->core_reg);
+
 	return err;
 }
 
@@ -2879,6 +2944,72 @@ static int tegra_dc_couple(struct tegra_dc *dc)
 	return 0;
 }
 
+static void tegra_dc_deinit_opp_table(void *data)
+{
+	struct tegra_dc *dc = data;
+
+	dev_pm_opp_of_remove_table(dc->dev);
+	dev_pm_opp_put_supported_hw(dc->opp_table);
+	dev_pm_opp_put_regulators(dc->opp_table);
+}
+
+static int devm_tegra_dc_opp_table_init(struct tegra_dc *dc)
+{
+	struct opp_table *hw_opp_table;
+	u32 hw_version;
+	int err;
+
+	/* voltage scaling is optional */
+	dc->core_reg = devm_regulator_get(dc->dev, "core");
+	if (IS_ERR(dc->core_reg))
+		return dev_err_probe(dc->dev, PTR_ERR(dc->core_reg),
+				     "failed to get CORE regulator\n");
+
+	/* legacy device-trees don't have OPP table */
+	if (!device_property_present(dc->dev, "operating-points-v2"))
+		return 0;
+
+	dc->opp_table = dev_pm_opp_get_opp_table(dc->dev);
+	if (IS_ERR(dc->opp_table))
+		return dev_err_probe(dc->dev, PTR_ERR(dc->opp_table),
+				     "failed to prepare OPP table\n");
+
+	if (of_machine_is_compatible("nvidia,tegra20"))
+		hw_version = BIT(tegra_sku_info.soc_process_id);
+	else
+		hw_version = BIT(tegra_sku_info.soc_speedo_id);
+
+	hw_opp_table = dev_pm_opp_set_supported_hw(dc->dev, &hw_version, 1);
+	err = PTR_ERR_OR_ZERO(hw_opp_table);
+	if (err) {
+		dev_err(dc->dev, "failed to set supported HW: %d\n", err);
+		goto put_table;
+	}
+
+	err = dev_pm_opp_of_add_table(dc->dev);
+	if (err) {
+		dev_err(dc->dev, "failed to add OPP table: %d\n", err);
+		goto put_hw;
+	}
+
+	err = devm_add_action(dc->dev, tegra_dc_deinit_opp_table, dc);
+	if (err)
+		goto remove_table;
+
+	dev_info(dc->dev, "OPP HW ver. 0x%x\n", hw_version);
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dc->dev);
+put_hw:
+	dev_pm_opp_put_supported_hw(dc->opp_table);
+put_table:
+	dev_pm_opp_put_opp_table(dc->opp_table);
+
+	return err;
+}
+
 static int tegra_dc_probe(struct platform_device *pdev)
 {
 	struct tegra_dc *dc;
@@ -2937,6 +3068,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		tegra_powergate_power_off(dc->powergate);
 	}
 
+	err = devm_tegra_dc_opp_table_init(dc);
+	if (err < 0)
+		return err;
+
 	dc->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(dc->regs))
 		return PTR_ERR(dc->regs);
@@ -3007,6 +3142,7 @@ struct platform_driver tegra_dc_driver = {
 	.driver = {
 		.name = "tegra-dc",
 		.of_match_table = tegra_dc_of_match,
+		.sync_state = tegra_soc_device_sync_state,
 	},
 	.probe = tegra_dc_probe,
 	.remove = tegra_dc_remove,
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index ba4ed35139fb..fd774fc5c2e4 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -13,6 +13,8 @@
 
 #include "drm.h"
 
+struct opp_table;
+struct regulator;
 struct tegra_output;
 
 #define TEGRA_DC_LEGACY_PLANES_NUM	6
@@ -107,6 +109,9 @@ struct tegra_dc {
 	struct drm_info_list *debugfs_files;
 
 	const struct tegra_dc_soc_info *soc;
+
+	struct opp_table *opp_table;
+	struct regulator *core_reg;
 };
 
 static inline struct tegra_dc *
-- 
2.27.0


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

* [PATCH v1 12/30] drm/tegra: gr2d: Correct swapped device-tree compatibles
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (10 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 13/30] drm/tegra: gr2d: Support OPP and SoC core voltage scaling Dmitry Osipenko
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

The device-tree compatibles are swapped in the code, correct them.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/gr2d.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 1a0d3ba6e525..f30aa86e4c9f 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -162,8 +162,8 @@ static const struct gr2d_soc tegra30_gr2d_soc = {
 };
 
 static const struct of_device_id gr2d_match[] = {
-	{ .compatible = "nvidia,tegra30-gr2d", .data = &tegra20_gr2d_soc },
-	{ .compatible = "nvidia,tegra20-gr2d", .data = &tegra30_gr2d_soc },
+	{ .compatible = "nvidia,tegra30-gr2d", .data = &tegra30_gr2d_soc },
+	{ .compatible = "nvidia,tegra20-gr2d", .data = &tegra20_gr2d_soc },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, gr2d_match);
-- 
2.27.0


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

* [PATCH v1 13/30] drm/tegra: gr2d: Support OPP and SoC core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (11 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 12/30] drm/tegra: gr2d: Correct swapped device-tree compatibles Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 14/30] drm/tegra: gr3d: " Dmitry Osipenko
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add OPP and SoC core voltage scaling support to the GR2D driver.
This is required for enabling system-wide DVFS on Tegra SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/gr2d.c | 136 +++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index f30aa86e4c9f..6d8f9419d908 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -7,6 +7,9 @@
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pm_opp.h>
+
+#include <soc/tegra/fuse.h>
 
 #include "drm.h"
 #include "gem.h"
@@ -185,6 +188,135 @@ static const u32 gr2d_addr_regs[] = {
 	GR2D_VA_BASE_ADDR_SB,
 };
 
+static int gr2d_init_opp_state(struct device *dev, struct gr2d *gr2d)
+{
+	struct dev_pm_opp *opp;
+	unsigned long rate;
+	int err;
+
+	/*
+	 * If voltage regulator presents, then we could select the fastest
+	 * clock rate, but driver doesn't support power management and
+	 * frequency scaling yet, hence the top freq OPP will vote for a
+	 * very high voltage that will produce lot's of heat.  Let's select
+	 * OPP for the current/default rate for now.
+	 *
+	 * Clock rate should be pre-initialized (i.e. it's non-zero) either
+	 * by clock driver or by assigned clocks in a device-tree.
+	 */
+	rate = clk_get_rate(gr2d->clk);
+
+	/* find suitable OPP for the clock rate supportable by SoC speedo ID */
+	opp = dev_pm_opp_find_freq_ceil(dev, &rate);
+
+	/*
+	 * dev_pm_opp_set_rate() doesn't search for a floor clock rate and it
+	 * will error out if default clock rate is too high, i.e. unsupported
+	 * by a SoC hardware version.  Hence will find floor rate by ourselves.
+	 */
+	if (opp == ERR_PTR(-ERANGE))
+		opp = dev_pm_opp_find_freq_floor(dev, &rate);
+
+	err = PTR_ERR_OR_ZERO(opp);
+	if (err) {
+		dev_err(dev, "failed to get OPP for %ld Hz: %d\n",
+			rate, err);
+		return err;
+	}
+
+	dev_pm_opp_put(opp);
+
+	/*
+	 * First dummy rate-set initializes voltage vote by setting voltage
+	 * in accordance to the clock rate.  We need to do this because GR2D
+	 * currently doesn't support power management and clock is permanently
+	 * enabled.
+	 */
+	err = dev_pm_opp_set_rate(dev, rate);
+	if (err) {
+		dev_err(dev, "failed to initialize OPP clock: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void gr2d_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_supported_hw(opp_table);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_gr2d_init_opp_table(struct device *dev, struct gr2d *gr2d)
+{
+	struct opp_table *opp_table, *hw_opp_table;
+	const char *rname = "core";
+	u32 hw_version;
+	int err;
+
+	/* voltage scaling is optional */
+	if (device_property_present(dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(dev, PTR_ERR(opp_table),
+				     "failed to prepare OPP table\n");
+
+	if (gr2d->soc->version == 0x20)
+		hw_version = BIT(tegra_sku_info.soc_process_id);
+	else
+		hw_version = BIT(tegra_sku_info.soc_speedo_id);
+
+	hw_opp_table = dev_pm_opp_set_supported_hw(dev, &hw_version, 1);
+	err = PTR_ERR_OR_ZERO(hw_opp_table);
+	if (err) {
+		dev_err(dev, "failed to set supported HW: %d\n", err);
+		goto put_table;
+	}
+
+	/*
+	 * OPP table presence is optional and we want the set_rate() of OPP
+	 * API to work similarly to clk_set_rate() if table is missing in a
+	 * device-tree.  The add_table() errors out if OPP is missing in DT.
+	 */
+	if (device_property_present(dev, "operating-points-v2")) {
+		err = dev_pm_opp_of_add_table(dev);
+		if (err) {
+			dev_err(dev, "failed to add OPP table: %d\n", err);
+			goto put_hw;
+		}
+
+		err = gr2d_init_opp_state(dev, gr2d);
+		if (err)
+			goto remove_table;
+	}
+
+	err = devm_add_action(dev, gr2d_deinit_opp_table, dev);
+	if (err)
+		goto remove_table;
+
+	dev_info(dev, "OPP HW ver. 0x%x\n", hw_version);
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dev);
+put_hw:
+	dev_pm_opp_put_supported_hw(opp_table);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static int gr2d_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -209,6 +341,10 @@ static int gr2d_probe(struct platform_device *pdev)
 		return PTR_ERR(gr2d->clk);
 	}
 
+	err = devm_gr2d_init_opp_table(dev, gr2d);
+	if (err)
+		return dev_err_probe(dev, err, "failed to initialize OPP\n");
+
 	err = clk_prepare_enable(gr2d->clk);
 	if (err) {
 		dev_err(dev, "cannot turn on clock\n");
-- 
2.27.0


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

* [PATCH v1 14/30] drm/tegra: gr3d: Support OPP and SoC core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (12 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 13/30] drm/tegra: gr2d: Support OPP and SoC core voltage scaling Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 15/30] drm/tegra: hdmi: " Dmitry Osipenko
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add OPP and SoC core voltage scaling support to the GR3D driver.
This is required for enabling system-wide DVFS on Tegra SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/gr3d.c | 136 +++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index b0b8154e8104..0c6efc55f9bc 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -11,7 +11,9 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
+#include <linux/pm_opp.h>
 
+#include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
 #include "drm.h"
@@ -278,6 +280,135 @@ static const u32 gr3d_addr_regs[] = {
 	GR3D_GLOBAL_SAMP23SURFADDR(15),
 };
 
+static int gr3d_init_opp_state(struct device *dev, struct gr3d *gr3d)
+{
+	struct dev_pm_opp *opp;
+	unsigned long rate;
+	int err;
+
+	/*
+	 * If voltage regulator presents, then we could select the fastest
+	 * clock rate, but driver doesn't support power management and
+	 * frequency scaling yet, hence the top freq OPP will vote for a
+	 * very high voltage that will produce lot's of heat.  Let's select
+	 * OPP for the current/default rate for now.
+	 *
+	 * Clock rate should be pre-initialized (i.e. it's non-zero) either
+	 * by clock driver or by assigned clocks in a device-tree.
+	 */
+	rate = clk_get_rate(gr3d->clk);
+
+	/* find suitable OPP for the clock rate supportable by SoC speedo ID */
+	opp = dev_pm_opp_find_freq_ceil(dev, &rate);
+
+	/*
+	 * dev_pm_opp_set_rate() doesn't search for a floor clock rate and it
+	 * will error out if default clock rate is too high, i.e. unsupported
+	 * by a SoC hardware version.  Hence will find floor rate by ourselves.
+	 */
+	if (opp == ERR_PTR(-ERANGE))
+		opp = dev_pm_opp_find_freq_floor(dev, &rate);
+
+	err = PTR_ERR_OR_ZERO(opp);
+	if (err) {
+		dev_err(dev, "failed to get OPP for %ld Hz: %d\n",
+			rate, err);
+		return err;
+	}
+
+	dev_pm_opp_put(opp);
+
+	/*
+	 * First dummy rate-set initializes voltage vote by setting voltage
+	 * in accordance to the clock rate.  We need to do this because GR2D
+	 * currently doesn't support power management and clock is permanently
+	 * enabled.
+	 */
+	err = dev_pm_opp_set_rate(dev, rate);
+	if (err) {
+		dev_err(dev, "failed to initialize OPP clock: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void gr3d_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_supported_hw(opp_table);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_gr3d_init_opp_table(struct device *dev, struct gr3d *gr3d)
+{
+	struct opp_table *opp_table, *hw_opp_table;
+	const char *rname = "core";
+	u32 hw_version;
+	int err;
+
+	/* voltage scaling is optional */
+	if (device_property_present(dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(dev, PTR_ERR(opp_table),
+				     "failed to prepare OPP table\n");
+
+	if (gr3d->soc->version == 0x20)
+		hw_version = BIT(tegra_sku_info.soc_process_id);
+	else
+		hw_version = BIT(tegra_sku_info.soc_speedo_id);
+
+	hw_opp_table = dev_pm_opp_set_supported_hw(dev, &hw_version, 1);
+	err = PTR_ERR_OR_ZERO(hw_opp_table);
+	if (err) {
+		dev_err(dev, "failed to set supported HW: %d\n", err);
+		goto put_table;
+	}
+
+	/*
+	 * OPP table presence is optional and we want the set_rate() of OPP
+	 * API to work similarly to clk_set_rate() if table is missing in a
+	 * device-tree.  The add_table() errors out if OPP is missing in DT.
+	 */
+	if (device_property_present(dev, "operating-points-v2")) {
+		err = dev_pm_opp_of_add_table(dev);
+		if (err) {
+			dev_err(dev, "failed to add OPP table: %d\n", err);
+			goto put_hw;
+		}
+
+		err = gr3d_init_opp_state(dev, gr3d);
+		if (err)
+			goto remove_table;
+	}
+
+	err = devm_add_action(dev, gr3d_deinit_opp_table, dev);
+	if (err)
+		goto remove_table;
+
+	dev_info(dev, "OPP HW ver. 0x%x\n", hw_version);
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dev);
+put_hw:
+	dev_pm_opp_put_supported_hw(opp_table);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static int gr3d_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -302,6 +433,11 @@ static int gr3d_probe(struct platform_device *pdev)
 		return PTR_ERR(gr3d->clk);
 	}
 
+	err = devm_gr3d_init_opp_table(&pdev->dev, gr3d);
+	if (err)
+		return dev_err_probe(&pdev->dev, err,
+				     "failed to initialize OPP\n");
+
 	gr3d->rst = devm_reset_control_get(&pdev->dev, "3d");
 	if (IS_ERR(gr3d->rst)) {
 		dev_err(&pdev->dev, "cannot get reset\n");
-- 
2.27.0


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

* [PATCH v1 15/30] drm/tegra: hdmi: Support OPP and SoC core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (13 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 14/30] drm/tegra: gr3d: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 16/30] gpu: host1x: " Dmitry Osipenko
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add OPP and SoC core voltage scaling support to the HDMI driver.
This is required for enabling system-wide DVFS on older Tegra SoCs.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/hdmi.c | 63 +++++++++++++++++++++++++++++++++++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index d09a24931c87..92e96990854b 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -11,6 +11,7 @@
 #include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pm_opp.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
@@ -1195,7 +1196,7 @@ static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder)
 	h_back_porch = mode->htotal - mode->hsync_end;
 	h_front_porch = mode->hsync_start - mode->hdisplay;
 
-	err = clk_set_rate(hdmi->clk, hdmi->pixel_clock);
+	err = dev_pm_opp_set_rate(hdmi->dev, hdmi->pixel_clock);
 	if (err < 0) {
 		dev_err(hdmi->dev, "failed to set HDMI clock frequency: %d\n",
 			err);
@@ -1499,6 +1500,7 @@ static int tegra_hdmi_runtime_suspend(struct host1x_client *client)
 	usleep_range(1000, 2000);
 
 	clk_disable_unprepare(hdmi->clk);
+	dev_pm_opp_set_rate(hdmi->dev, 0);
 	pm_runtime_put_sync(dev);
 
 	return 0;
@@ -1633,6 +1635,60 @@ static irqreturn_t tegra_hdmi_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static void tegra_hdmi_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_tegra_hdmi_init_opp_table(struct device *dev)
+{
+	struct opp_table *opp_table;
+	const char *rname = "core";
+	int err;
+
+	/* voltage scaling is optional */
+	if (device_property_present(dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(dev, PTR_ERR(opp_table),
+				    "failed to prepare OPP table\n");
+
+	/*
+	 * OPP table presence is optional and we want the set_rate() of OPP
+	 * API to work similarly to clk_set_rate() if table is missing in a
+	 * device-tree.  The add_table() errors out if OPP is missing in DT.
+	 */
+	if (device_property_present(dev, "operating-points-v2")) {
+		err = dev_pm_opp_of_add_table(dev);
+		if (err) {
+			dev_err(dev, "failed to add OPP table: %d\n", err);
+			goto put_table;
+		}
+	}
+
+	err = devm_add_action(dev, tegra_hdmi_deinit_opp_table, dev);
+	if (err)
+		goto remove_table;
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dev);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static int tegra_hdmi_probe(struct platform_device *pdev)
 {
 	const char *level = KERN_ERR;
@@ -1667,6 +1723,11 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 	if (IS_ERR(hdmi->clk_parent))
 		return PTR_ERR(hdmi->clk_parent);
 
+	err = devm_tegra_hdmi_init_opp_table(&pdev->dev);
+	if (err)
+		return dev_err_probe(&pdev->dev, err,
+				     "failed to initialize OPP\n");
+
 	err = clk_set_parent(hdmi->clk, hdmi->clk_parent);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to setup clocks: %d\n", err);
-- 
2.27.0


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

* [PATCH v1 16/30] gpu: host1x: Support OPP and SoC core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (14 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 15/30] drm/tegra: hdmi: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and " Dmitry Osipenko
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add initial OPP and SoC core voltage scaling support to the Host1x driver.
This is required for enabling system-wide DVFS on older Tegra SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/host1x/Kconfig |  1 +
 drivers/gpu/host1x/dev.c   | 87 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+)

diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
index 6dab94adf25e..fba4207c35a4 100644
--- a/drivers/gpu/host1x/Kconfig
+++ b/drivers/gpu/host1x/Kconfig
@@ -3,6 +3,7 @@ config TEGRA_HOST1X
 	tristate "NVIDIA Tegra host1x driver"
 	depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
 	select IOMMU_IOVA
+	select PM_OPP
 	help
 	  Driver for the NVIDIA Tegra host1x hardware.
 
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index d0ebb70e2fdd..06e65dc1ab19 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -13,6 +13,9 @@
 #include <linux/of_device.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/pm_opp.h>
+
+#include <soc/tegra/fuse.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/host1x.h>
@@ -341,6 +344,85 @@ static void host1x_iommu_exit(struct host1x *host)
 	}
 }
 
+static void host1x_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_supported_hw(opp_table);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_host1x_init_opp_table(struct host1x *host)
+{
+	struct opp_table *opp_table, *hw_opp_table;
+	const char *rname = "core";
+	u32 hw_version;
+	int err;
+
+	/* voltage scaling is optional */
+	if (device_property_present(host->dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(host->dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(host->dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(host->dev, PTR_ERR(opp_table),
+				     "failed to prepare OPP table\n");
+
+	if (of_machine_is_compatible("nvidia,tegra20"))
+		hw_version = BIT(tegra_sku_info.soc_process_id);
+	else
+		hw_version = BIT(tegra_sku_info.soc_speedo_id);
+
+	hw_opp_table = dev_pm_opp_set_supported_hw(host->dev, &hw_version, 1);
+	err = PTR_ERR_OR_ZERO(hw_opp_table);
+	if (err) {
+		dev_err(host->dev, "failed to set supported HW: %d\n", err);
+		goto put_table;
+	}
+
+	/*
+	 * OPP table presence is optional and we want the set_rate() of OPP
+	 * API to work similarly to clk_set_rate() if table is missing in a
+	 * device-tree.  The add_table() errors out if OPP is missing in DT.
+	 */
+	if (device_property_present(host->dev, "operating-points-v2")) {
+		err = dev_pm_opp_of_add_table(host->dev);
+		if (err) {
+			dev_err(host->dev, "failed to add OPP table: %d\n", err);
+			goto put_hw;
+		}
+	}
+
+	/* first dummy rate-set initializes voltage vote */
+	err = dev_pm_opp_set_rate(host->dev, clk_get_rate(host->clk));
+	if (err) {
+		dev_err(host->dev, "failed to initialize OPP clock: %d\n", err);
+		goto remove_table;
+	}
+
+	err = devm_add_action(host->dev, host1x_deinit_opp_table, host->dev);
+	if (err)
+		goto remove_table;
+
+	dev_info(host->dev, "OPP HW ver. 0x%x\n", hw_version);
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(host->dev);
+put_hw:
+	dev_pm_opp_put_supported_hw(opp_table);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static int host1x_probe(struct platform_device *pdev)
 {
 	struct host1x *host;
@@ -424,6 +506,11 @@ static int host1x_probe(struct platform_device *pdev)
 		return err;
 	}
 
+	err = devm_host1x_init_opp_table(host);
+	if (err < 0)
+		return dev_err_probe(&pdev->dev, err,
+				     "failed to initialize OPP\n");
+
 	err = host1x_iommu_init(host);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to setup IOMMU: %d\n", err);
-- 
2.27.0


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

* [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (15 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 16/30] gpu: host1x: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-05  9:58   ` Viresh Kumar
  2020-11-04 23:44 ` [PATCH v1 18/30] pwm: tegra: " Dmitry Osipenko
                   ` (15 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add OPP and SoC core voltage scaling support to the Tegra SDHCI driver.
This is required for enabling system-wide DVFS on older Tegra SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/mmc/host/Kconfig       |  1 +
 drivers/mmc/host/sdhci-tegra.c | 70 ++++++++++++++++++++++++++++++++--
 2 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 310e546e5898..7d719c81b917 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -293,6 +293,7 @@ config MMC_SDHCI_TEGRA
 	depends on MMC_SDHCI_PLTFM
 	select MMC_SDHCI_IO_ACCESSORS
 	select MMC_CQHCI
+	select PM_OPP
 	help
 	  This selects the Tegra SD/MMC controller. If you have a Tegra
 	  platform with SD or MMC devices, say Y or M here.
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index ed12aacb1c73..964709a3ccd6 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/pm_opp.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
@@ -754,10 +755,15 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
+	struct device *dev = mmc_dev(host->mmc);
 	unsigned long host_clk;
 
-	if (!clock)
-		return sdhci_set_clock(host, clock);
+	/* disable clock and then remove OPP performance/voltage vote */
+	if (!clock) {
+		sdhci_set_clock(host, clock);
+		dev_pm_opp_set_rate(dev, clock);
+		return;
+	}
 
 	/*
 	 * In DDR50/52 modes the Tegra SDHCI controllers require the SDHCI
@@ -772,7 +778,7 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 	 * from clk_get_rate() is used.
 	 */
 	host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
-	clk_set_rate(pltfm_host->clk, host_clk);
+	dev_pm_opp_set_rate(dev, host_clk);
 	tegra_host->curr_clk_rate = host_clk;
 	if (tegra_host->ddr_signaling)
 		host->max_clk = host_clk;
@@ -1558,6 +1564,60 @@ static int sdhci_tegra_add_host(struct sdhci_host *host)
 	return ret;
 }
 
+static void sdhci_tegra_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_sdhci_tegra_init_opp_table(struct device *dev)
+{
+	struct opp_table *opp_table;
+	const char *rname = "core";
+	int err;
+
+	/* voltage scaling is optional */
+	if (device_property_present(dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(dev, PTR_ERR(opp_table),
+				    "failed to prepare OPP table\n");
+
+	/*
+	 * OPP table presence is optional and we want the set_rate() of OPP
+	 * API to work similarly to clk_set_rate() if table is missing in a
+	 * device-tree.  The add_table() errors out if OPP is missing in DT.
+	 */
+	if (device_property_present(dev, "operating-points-v2")) {
+		err = dev_pm_opp_of_add_table(dev);
+		if (err) {
+			dev_err(dev, "failed to add OPP table: %d\n", err);
+			goto put_table;
+		}
+	}
+
+	err = devm_add_action(dev, sdhci_tegra_deinit_opp_table, dev);
+	if (err)
+		goto remove_table;
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dev);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static int sdhci_tegra_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
@@ -1621,6 +1681,10 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 		goto err_power_req;
 	}
 
+	rc = devm_sdhci_tegra_init_opp_table(&pdev->dev);
+	if (rc)
+		goto err_parse_dt;
+
 	/*
 	 * Tegra210 has a separate SDMMC_LEGACY_TM clock used for host
 	 * timeout clock and SW can choose TMCLK or SDCLK for hardware
-- 
2.27.0


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

* [PATCH v1 18/30] pwm: tegra: Support OPP and core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (16 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-10 20:50   ` Thierry Reding
  2020-11-04 23:44 ` [PATCH v1 19/30] media: staging: tegra-vde: Support OPP and SoC " Dmitry Osipenko
                   ` (14 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add OPP and SoC core voltage scaling support to the Tegra PWM driver.
This is required for enabling system-wide DVFS on older Tegra SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/pwm/Kconfig     |  1 +
 drivers/pwm/pwm-tegra.c | 84 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 82 insertions(+), 3 deletions(-)

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 63be5362fd3a..61d35ef759f2 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -509,6 +509,7 @@ config PWM_SUN4I
 config PWM_TEGRA
 	tristate "NVIDIA Tegra PWM support"
 	depends on ARCH_TEGRA || COMPILE_TEST
+	select PM_OPP
 	help
 	  Generic PWM framework driver for the PWFM controller found on NVIDIA
 	  Tegra SoCs.
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 1daf591025c0..96c253127ff3 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -42,12 +42,15 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/pm_opp.h>
 #include <linux/pwm.h>
 #include <linux/platform_device.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/slab.h>
 #include <linux/reset.h>
 
+#include <soc/tegra/common.h>
+
 #define PWM_ENABLE	(1 << 31)
 #define PWM_DUTY_WIDTH	8
 #define PWM_DUTY_SHIFT	16
@@ -145,7 +148,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 		required_clk_rate =
 			(NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH;
 
-		err = clk_set_rate(pc->clk, required_clk_rate);
+		err = dev_pm_opp_set_rate(pc->dev, required_clk_rate);
 		if (err < 0)
 			return -EINVAL;
 
@@ -181,6 +184,10 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	 * before writing the register. Otherwise, keep it enabled.
 	 */
 	if (!pwm_is_enabled(pwm)) {
+		err = dev_pm_opp_set_rate(pc->dev, pc->clk_rate);
+		if (err < 0)
+			return err;
+
 		err = clk_prepare_enable(pc->clk);
 		if (err < 0)
 			return err;
@@ -191,9 +198,12 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 
 	/*
 	 * If the PWM is not enabled, turn the clock off again to save power.
+	 * Remove OPP performance/voltage vote after disabling the clock.
 	 */
-	if (!pwm_is_enabled(pwm))
+	if (!pwm_is_enabled(pwm)) {
 		clk_disable_unprepare(pc->clk);
+		dev_pm_opp_set_rate(pc->dev, 0);
+	}
 
 	return 0;
 }
@@ -204,6 +214,10 @@ static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 	int rc = 0;
 	u32 val;
 
+	rc = dev_pm_opp_set_rate(pc->dev, pc->clk_rate);
+	if (rc < 0)
+		return rc;
+
 	rc = clk_prepare_enable(pc->clk);
 	if (rc < 0)
 		return rc;
@@ -225,6 +239,7 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 	pwm_writel(pc, pwm->hwpwm, val);
 
 	clk_disable_unprepare(pc->clk);
+	dev_pm_opp_set_rate(pc->dev, 0);
 }
 
 static const struct pwm_ops tegra_pwm_ops = {
@@ -234,6 +249,60 @@ static const struct pwm_ops tegra_pwm_ops = {
 	.owner = THIS_MODULE,
 };
 
+static void tegra_pwm_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_tegra_pwm_init_opp_table(struct device *dev)
+{
+	struct opp_table *opp_table;
+	const char *rname = "core";
+	int err;
+
+	/* voltage scaling is optional */
+	if (device_property_present(dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(dev, PTR_ERR(opp_table),
+				     "failed to prepare OPP table\n");
+
+	/*
+	 * OPP table presence is optional and we want the set_rate() of OPP
+	 * API to work similarly to clk_set_rate() if table is missing in a
+	 * device-tree.  The add_table() errors out if OPP is missing in DT.
+	 */
+	if (device_property_present(dev, "operating-points-v2")) {
+		err = dev_pm_opp_of_add_table(dev);
+		if (err) {
+			dev_err(dev, "failed to add OPP table: %d\n", err);
+			goto put_table;
+		}
+	}
+
+	err = devm_add_action(dev, tegra_pwm_deinit_opp_table, dev);
+	if (err)
+		goto remove_table;
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dev);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static int tegra_pwm_probe(struct platform_device *pdev)
 {
 	struct tegra_pwm_chip *pwm;
@@ -258,8 +327,12 @@ static int tegra_pwm_probe(struct platform_device *pdev)
 	if (IS_ERR(pwm->clk))
 		return PTR_ERR(pwm->clk);
 
+	ret = devm_tegra_pwm_init_opp_table(&pdev->dev);
+	if (ret)
+		return ret;
+
 	/* Set maximum frequency of the IP */
-	ret = clk_set_rate(pwm->clk, pwm->soc->max_frequency);
+	ret = dev_pm_opp_set_rate(pwm->dev, pwm->soc->max_frequency);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret);
 		return ret;
@@ -309,6 +382,10 @@ static int tegra_pwm_remove(struct platform_device *pdev)
 	if (WARN_ON(!pc))
 		return -ENODEV;
 
+	err = dev_pm_opp_set_rate(pc->dev, pc->clk_rate);
+	if (err < 0)
+		return err;
+
 	err = clk_prepare_enable(pc->clk);
 	if (err < 0)
 		return err;
@@ -375,6 +452,7 @@ static struct platform_driver tegra_pwm_driver = {
 		.name = "tegra-pwm",
 		.of_match_table = tegra_pwm_of_match,
 		.pm = &tegra_pwm_pm_ops,
+		.sync_state = tegra_soc_device_sync_state,
 	},
 	.probe = tegra_pwm_probe,
 	.remove = tegra_pwm_remove,
-- 
2.27.0


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

* [PATCH v1 19/30] media: staging: tegra-vde: Support OPP and SoC core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (17 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 18/30] pwm: tegra: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 20/30] usb: chipidea: tegra: " Dmitry Osipenko
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add initial OPP and SoC core voltage scaling support to the video
decoder driver. This is required for enabling system-wide DVFS on
older Tegra SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/staging/media/tegra-vde/Kconfig |   1 +
 drivers/staging/media/tegra-vde/vde.c   | 127 ++++++++++++++++++++++++
 drivers/staging/media/tegra-vde/vde.h   |   1 +
 3 files changed, 129 insertions(+)

diff --git a/drivers/staging/media/tegra-vde/Kconfig b/drivers/staging/media/tegra-vde/Kconfig
index 0dc78afd09e0..0ebfe5b07a30 100644
--- a/drivers/staging/media/tegra-vde/Kconfig
+++ b/drivers/staging/media/tegra-vde/Kconfig
@@ -4,6 +4,7 @@ config TEGRA_VDE
 	depends on ARCH_TEGRA || COMPILE_TEST
 	select DMA_SHARED_BUFFER
 	select IOMMU_IOVA
+	select PM_OPP
 	select SRAM
 	help
 	    Say Y here to enable support for the NVIDIA Tegra video decoder
diff --git a/drivers/staging/media/tegra-vde/vde.c b/drivers/staging/media/tegra-vde/vde.c
index 28845b5bafaf..9ad43a862eef 100644
--- a/drivers/staging/media/tegra-vde/vde.c
+++ b/drivers/staging/media/tegra-vde/vde.c
@@ -15,11 +15,13 @@
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pm_opp.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
+#include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
 #include "uapi.h"
@@ -926,6 +928,9 @@ static __maybe_unused int tegra_vde_runtime_suspend(struct device *dev)
 
 	clk_disable_unprepare(vde->clk);
 
+	/* remove performance/voltage vote */
+	dev_pm_opp_set_rate(dev, 0);
+
 	return 0;
 }
 
@@ -934,6 +939,12 @@ static __maybe_unused int tegra_vde_runtime_resume(struct device *dev)
 	struct tegra_vde *vde = dev_get_drvdata(dev);
 	int err;
 
+	err = dev_pm_opp_set_rate(dev, vde->default_clk_rate);
+	if (err) {
+		dev_err(dev, "Failed to set clock rate: %d\n", err);
+		return err;
+	}
+
 	err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
 						vde->clk, vde->rst);
 	if (err) {
@@ -944,6 +955,118 @@ static __maybe_unused int tegra_vde_runtime_resume(struct device *dev)
 	return 0;
 }
 
+static void tegra_vde_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_supported_hw(opp_table);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_tegra_vde_init_opp_table(struct device *dev,
+					 struct tegra_vde *vde)
+{
+	struct opp_table *opp_table, *hw_opp_table;
+	const char *rname = "core";
+	struct dev_pm_opp *opp;
+	unsigned long rate;
+	u32 hw_version;
+	int err;
+
+	/* voltage scaling is optional */
+	if (device_property_present(dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(dev, PTR_ERR(opp_table),
+				     "Failed to prepare OPP table\n");
+
+	if (of_machine_is_compatible("nvidia,tegra20"))
+		hw_version = BIT(tegra_sku_info.soc_process_id);
+	else
+		hw_version = BIT(tegra_sku_info.soc_speedo_id);
+
+	hw_opp_table = dev_pm_opp_set_supported_hw(dev, &hw_version, 1);
+	err = PTR_ERR_OR_ZERO(hw_opp_table);
+	if (err) {
+		dev_err(dev, "Failed to set supported HW: %d\n", err);
+		goto put_table;
+	}
+
+	/*
+	 * OPP table presence is optional and we want the set_rate() of OPP
+	 * API to work similarly to clk_set_rate() if table is missing in a
+	 * device-tree.  The add_table() errors out if OPP is missing in DT.
+	 *
+	 * Clock rate should be pre-initialized (i.e. it's non-zero) either
+	 * by clock driver or by assigned clocks in a device-tree.
+	 */
+	if (!device_property_present(dev, "operating-points-v2")) {
+		vde->default_clk_rate = clk_get_rate(vde->clk);
+		goto add_action;
+	}
+
+	err = dev_pm_opp_of_add_table(dev);
+	if (err) {
+		dev_err(dev, "Failed to add OPP table: %d\n", err);
+		goto put_hw;
+	}
+
+	/*
+	 * If voltage regulator presents, then we could select the fastest
+	 * clock rate, but driver doesn't support frequency scaling yet,
+	 * hence the top freq OPP may vote for a very high voltage that will
+	 * produce lot's of heat.  Let's select OPP for the current/default
+	 * rate for now.
+	 *
+	 * Clock rate should be pre-initialized (i.e. it's non-zero) either
+	 * by clock driver or by assigned clocks in a device-tree.
+	 */
+	rate = clk_get_rate(vde->clk);
+
+	/* find suitable OPP for the clock rate supportable by SoC */
+	opp = dev_pm_opp_find_freq_ceil(dev, &rate);
+
+	if (opp == ERR_PTR(-ERANGE))
+		opp = dev_pm_opp_find_freq_floor(dev, &rate);
+
+	err = PTR_ERR_OR_ZERO(opp);
+	if (err) {
+		dev_err(dev, "failed to get OPP for %ld Hz: %d\n",
+			rate, err);
+		goto remove_table;
+	}
+
+	dev_pm_opp_put(opp);
+
+	vde->default_clk_rate = clk_round_rate(vde->clk, rate);
+
+add_action:
+	err = devm_add_action(dev, tegra_vde_deinit_opp_table, dev);
+	if (err)
+		goto remove_table;
+
+	dev_info(dev, "OPP HW ver. 0x%x, clock rate %lu MHz\n",
+		 hw_version, vde->default_clk_rate / 1000000);
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dev);
+put_hw:
+	dev_pm_opp_put_supported_hw(opp_table);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static int tegra_vde_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1024,6 +1147,10 @@ static int tegra_vde_probe(struct platform_device *pdev)
 		return err;
 	}
 
+	err = devm_tegra_vde_init_opp_table(dev, vde);
+	if (err)
+		return dev_err_probe(dev, err, "Failed to initialize OPP\n");
+
 	vde->iram_pool = of_gen_pool_get(dev->of_node, "iram", 0);
 	if (!vde->iram_pool) {
 		dev_err(dev, "Could not get IRAM pool\n");
diff --git a/drivers/staging/media/tegra-vde/vde.h b/drivers/staging/media/tegra-vde/vde.h
index 5561291b0c88..da83c2d6af8b 100644
--- a/drivers/staging/media/tegra-vde/vde.h
+++ b/drivers/staging/media/tegra-vde/vde.h
@@ -48,6 +48,7 @@ struct tegra_vde {
 	struct iova_domain iova;
 	struct iova *iova_resv_static_addresses;
 	struct iova *iova_resv_last_page;
+	unsigned long default_clk_rate;
 	dma_addr_t iram_lists_addr;
 	u32 *iram;
 };
-- 
2.27.0


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

* [PATCH v1 20/30] usb: chipidea: tegra: Support OPP and SoC core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (18 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 19/30] media: staging: tegra-vde: Support OPP and SoC " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 21/30] usb: host: ehci-tegra: " Dmitry Osipenko
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add initial OPP and SoC CORE voltage scaling support to the Tegra UDC
driver. This is required for enabling system-wide DVFS on older Tegra
SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/usb/chipidea/Kconfig         |  1 +
 drivers/usb/chipidea/ci_hdrc_tegra.c | 79 ++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+)

diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index 8bafcfc6080d..6a5bc08711d6 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -56,6 +56,7 @@ config USB_CHIPIDEA_TEGRA
 	tristate "Enable Tegra UDC glue driver" if EMBEDDED
 	depends on OF
 	depends on USB_CHIPIDEA_UDC
+	select PM_OPP
 	default USB_CHIPIDEA
 
 endif
diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 7455df0ede49..7f0403e810fe 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -6,6 +6,7 @@
 #include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pm_opp.h>
 #include <linux/reset.h>
 
 #include <linux/usb/chipidea.h>
@@ -47,6 +48,79 @@ static const struct of_device_id tegra_udc_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_udc_of_match);
 
+static void tegra_udc_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_tegra_udc_init_opp_table(struct device *dev)
+{
+	unsigned long rate = ULONG_MAX;
+	struct opp_table *opp_table;
+	const char *rname = "core";
+	struct dev_pm_opp *opp;
+	int err;
+
+	/* legacy device-trees don't have OPP table */
+	if (!device_property_present(dev, "operating-points-v2"))
+		return 0;
+
+	/* voltage scaling is optional */
+	if (device_property_present(dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(dev, PTR_ERR(opp_table),
+				     "failed to prepare OPP table\n");
+
+	err = dev_pm_opp_of_add_table(dev);
+	if (err) {
+		dev_err(dev, "failed to add OPP table: %d\n", err);
+		goto put_table;
+	}
+
+	/* find suitable OPP for the maximum clock rate */
+	opp = dev_pm_opp_find_freq_floor(dev, &rate);
+	err = PTR_ERR_OR_ZERO(opp);
+	if (err) {
+		dev_err(dev, "failed to get OPP: %d\n", err);
+		goto remove_table;
+	}
+
+	dev_pm_opp_put(opp);
+
+	/*
+	 * First dummy rate-set initializes voltage vote by setting voltage
+	 * in accordance to the clock rate.
+	 */
+	err = dev_pm_opp_set_rate(dev, rate);
+	if (err) {
+		dev_err(dev, "failed to initialize OPP clock: %d\n", err);
+		goto remove_table;
+	}
+
+	err = devm_add_action(dev, tegra_udc_deinit_opp_table, dev);
+	if (err)
+		goto remove_table;
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dev);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static int tegra_udc_probe(struct platform_device *pdev)
 {
 	const struct tegra_udc_soc_info *soc;
@@ -77,6 +151,11 @@ static int tegra_udc_probe(struct platform_device *pdev)
 		return err;
 	}
 
+	err = devm_tegra_udc_init_opp_table(&pdev->dev);
+	if (err)
+		return dev_err_probe(&pdev->dev, err,
+				     "failed to initialize OPP\n");
+
 	err = clk_prepare_enable(udc->clk);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to enable clock: %d\n", err);
-- 
2.27.0


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

* [PATCH v1 21/30] usb: host: ehci-tegra: Support OPP and SoC core voltage scaling
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (19 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 20/30] usb: chipidea: tegra: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-05 16:07   ` Alan Stern
  2020-11-04 23:44 ` [PATCH v1 22/30] memory: tegra20-emc: Support Tegra SoC device state syncing Dmitry Osipenko
                   ` (11 subsequent siblings)
  32 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add initial OPP and SoC core voltage scaling support to the Tegra EHCI
driver. This is required for enabling system-wide DVFS on older Tegra
SoCs.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/usb/host/Kconfig      |  1 +
 drivers/usb/host/ehci-tegra.c | 79 +++++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index ab12c4bf0ef1..35c42bc05c5a 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -278,6 +278,7 @@ config USB_EHCI_TEGRA
 	depends on ARCH_TEGRA
 	select USB_EHCI_ROOT_HUB_TT
 	select USB_TEGRA_PHY
+	select PM_OPP
 	help
 	  This driver enables support for the internal USB Host Controllers
 	  found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 869d9c4de5fc..0976577f54b4 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -17,6 +17,7 @@
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
+#include <linux/pm_opp.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
@@ -364,6 +365,79 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 	free_dma_aligned_buffer(urb);
 }
 
+static void tegra_ehci_deinit_opp_table(void *data)
+{
+	struct device *dev = data;
+	struct opp_table *opp_table;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	dev_pm_opp_of_remove_table(dev);
+	dev_pm_opp_put_regulators(opp_table);
+	dev_pm_opp_put_opp_table(opp_table);
+}
+
+static int devm_tegra_ehci_init_opp_table(struct device *dev)
+{
+	unsigned long rate = ULONG_MAX;
+	struct opp_table *opp_table;
+	const char *rname = "core";
+	struct dev_pm_opp *opp;
+	int err;
+
+	/* legacy device-trees don't have OPP table */
+	if (!device_property_present(dev, "operating-points-v2"))
+		return 0;
+
+	/* voltage scaling is optional */
+	if (device_property_present(dev, "core-supply"))
+		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
+	else
+		opp_table = dev_pm_opp_get_opp_table(dev);
+
+	if (IS_ERR(opp_table))
+		return dev_err_probe(dev, PTR_ERR(opp_table),
+				     "failed to prepare OPP table\n");
+
+	err = dev_pm_opp_of_add_table(dev);
+	if (err) {
+		dev_err(dev, "failed to add OPP table: %d\n", err);
+		goto put_table;
+	}
+
+	/* find suitable OPP for the maximum clock rate */
+	opp = dev_pm_opp_find_freq_floor(dev, &rate);
+	err = PTR_ERR_OR_ZERO(opp);
+	if (err) {
+		dev_err(dev, "failed to get OPP: %d\n", err);
+		goto remove_table;
+	}
+
+	dev_pm_opp_put(opp);
+
+	/*
+	 * First dummy rate-set initializes voltage vote by setting voltage
+	 * in accordance to the clock rate.
+	 */
+	err = dev_pm_opp_set_rate(dev, rate);
+	if (err) {
+		dev_err(dev, "failed to initialize OPP clock: %d\n", err);
+		goto remove_table;
+	}
+
+	err = devm_add_action(dev, tegra_ehci_deinit_opp_table, dev);
+	if (err)
+		goto remove_table;
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(dev);
+put_table:
+	dev_pm_opp_put_regulators(opp_table);
+
+	return err;
+}
+
 static const struct tegra_ehci_soc_config tegra30_soc_config = {
 	.has_hostpc = true,
 };
@@ -431,6 +505,11 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 		goto cleanup_hcd_create;
 	}
 
+	err = devm_tegra_ehci_init_opp_table(&pdev->dev);
+	if (err)
+		return dev_err_probe(&pdev->dev, err,
+				     "Failed to initialize OPP\n");
+
 	err = clk_prepare_enable(tegra->clk);
 	if (err)
 		goto cleanup_hcd_create;
-- 
2.27.0


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

* [PATCH v1 22/30] memory: tegra20-emc: Support Tegra SoC device state syncing
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (20 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 21/30] usb: host: ehci-tegra: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 23/30] memory: tegra30-emc: " Dmitry Osipenko
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Sync driver state using the Tegra SoC device state syncing API, telling
to regulators voltage coupler that EMC state is ready for DVFS. This is
required for enabling system-wide DVFS on Tegra20.

Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra20-emc.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
index 9946b957bb01..b1b0a2439689 100644
--- a/drivers/memory/tegra/tegra20-emc.c
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -1129,6 +1129,12 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	return err;
 }
 
+static void tegra_emc_sync_state(struct device *dev)
+{
+	tegra_soc_device_sync_state(dev);
+	icc_sync_state(dev);
+}
+
 static const struct of_device_id tegra_emc_of_match[] = {
 	{ .compatible = "nvidia,tegra20-emc", },
 	{},
@@ -1141,7 +1147,7 @@ static struct platform_driver tegra_emc_driver = {
 		.name = "tegra20-emc",
 		.of_match_table = tegra_emc_of_match,
 		.suppress_bind_attrs = true,
-		.sync_state = icc_sync_state,
+		.sync_state = tegra_emc_sync_state,
 	},
 };
 module_platform_driver(tegra_emc_driver);
-- 
2.27.0


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

* [PATCH v1 23/30] memory: tegra30-emc: Support Tegra SoC device state syncing
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (21 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 22/30] memory: tegra20-emc: Support Tegra SoC device state syncing Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 24/30] ARM: tegra: Add OPP tables for Tegra20 peripheral devices Dmitry Osipenko
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Sync driver state using the Tegra SoC device state syncing API, telling
to regulators voltage coupler that EMC state is ready for DVFS. This is
required for enabling system-wide DVFS on Tegra30.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra30-emc.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c
index 6b20ce9f16af..dd7474065346 100644
--- a/drivers/memory/tegra/tegra30-emc.c
+++ b/drivers/memory/tegra/tegra30-emc.c
@@ -1666,6 +1666,12 @@ static int tegra_emc_resume(struct device *dev)
 	return 0;
 }
 
+static void tegra_emc_sync_state(struct device *dev)
+{
+	tegra_soc_device_sync_state(dev);
+	icc_sync_state(dev);
+}
+
 static const struct dev_pm_ops tegra_emc_pm_ops = {
 	.suspend = tegra_emc_suspend,
 	.resume = tegra_emc_resume,
@@ -1684,7 +1690,7 @@ static struct platform_driver tegra_emc_driver = {
 		.of_match_table = tegra_emc_of_match,
 		.pm = &tegra_emc_pm_ops,
 		.suppress_bind_attrs = true,
-		.sync_state = icc_sync_state,
+		.sync_state = tegra_emc_sync_state,
 	},
 };
 module_platform_driver(tegra_emc_driver);
-- 
2.27.0


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

* [PATCH v1 24/30] ARM: tegra: Add OPP tables for Tegra20 peripheral devices
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (22 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 23/30] memory: tegra30-emc: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 25/30] ARM: tegra: Add OPP tables for Tegra30 " Dmitry Osipenko
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add OPP tables for Tegra20 SoC devices.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../arm/boot/dts/tegra20-peripherals-opp.dtsi | 386 ++++++++++++++++++
 arch/arm/boot/dts/tegra20.dtsi                |  14 +
 2 files changed, 400 insertions(+)

diff --git a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi b/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
index 25b1ba73951e..792dc79d32c5 100644
--- a/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra20-peripherals-opp.dtsi
@@ -89,4 +89,390 @@ opp@760000000 {
 			opp-hz = /bits/ 64 <760000000>;
 		};
 	};
+
+	vde_dvfs_opp_table: vde-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@95000000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <95000000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@123500000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <123500000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@123500000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <123500000>;
+			opp-supported-hw = <0x0002>;
+		};
+
+		opp@152000000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <152000000>;
+			opp-supported-hw = <0x0002>;
+		};
+
+		opp@152000000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <152000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@171000000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <171000000>;
+			opp-supported-hw = <0x0008>;
+		};
+
+		opp@209000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <209000000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@209000000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <209000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@218500000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <218500000>;
+			opp-supported-hw = <0x0008>;
+		};
+
+		opp@237500000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <237500000>;
+			opp-supported-hw = <0x0002>;
+		};
+
+		opp@275500000,1200 {
+			opp-microvolt = <1200000 1200000 1300000>;
+			opp-hz = /bits/ 64 <275500000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@285000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <285000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@300000000,1275 {
+			opp-microvolt = <1275000 1275000 1300000>;
+			opp-hz = /bits/ 64 <300000000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@300000000,1200 {
+			opp-microvolt = <1200000 1200000 1300000>;
+			opp-hz = /bits/ 64 <300000000>;
+			opp-supported-hw = <0x0006>;
+		};
+
+		opp@300000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <300000000>;
+			opp-supported-hw = <0x0008>;
+		};
+	};
+
+	gr2d_dvfs_opp_table: gr2d-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@133000000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <133000000>;
+			opp-supported-hw = <0x000F>;
+		};
+
+		opp@171000000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <171000000>;
+			opp-supported-hw = <0x000F>;
+		};
+
+		opp@247000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <247000000>;
+			opp-supported-hw = <0x000F>;
+		};
+
+		opp@300000000,1200 {
+			opp-microvolt = <1200000 1200000 1300000>;
+			opp-hz = /bits/ 64 <300000000>;
+			opp-supported-hw = <0x000F>;
+		};
+	};
+
+	gr3d_dvfs_opp_table: gr3d-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@114000000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <114000000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@161500000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <161500000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@161500000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <161500000>;
+			opp-supported-hw = <0x0002>;
+		};
+
+		opp@209000000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <209000000>;
+			opp-supported-hw = <0x0002>;
+		};
+
+		opp@218500000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <218500000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@247000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <247000000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@247000000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <247000000>;
+			opp-supported-hw = <0x0008>;
+		};
+
+		opp@256500000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <256500000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@285000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <285000000>;
+			opp-supported-hw = <0x0002>;
+		};
+
+		opp@285000000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <285000000>;
+			opp-supported-hw = <0x0008>;
+		};
+
+		opp@304000000,1200 {
+			opp-microvolt = <1200000 1200000 1300000>;
+			opp-hz = /bits/ 64 <304000000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@323000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <323000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@333500000,1275 {
+			opp-microvolt = <1275000 1275000 1300000>;
+			opp-hz = /bits/ 64 <333500000>;
+			opp-supported-hw = <0x0001>;
+		};
+
+		opp@333500000,1200 {
+			opp-microvolt = <1200000 1200000 1300000>;
+			opp-hz = /bits/ 64 <333500000>;
+			opp-supported-hw = <0x0002>;
+		};
+
+		opp@351500000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <351500000>;
+			opp-supported-hw = <0x0008>;
+		};
+
+		opp@361000000,1275 {
+			opp-microvolt = <1275000 1275000 1300000>;
+			opp-hz = /bits/ 64 <361000000>;
+			opp-supported-hw = <0x0002>;
+		};
+
+		opp@380000000,1200 {
+			opp-microvolt = <1200000 1200000 1300000>;
+			opp-hz = /bits/ 64 <380000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@400000000,1275 {
+			opp-microvolt = <1275000 1275000 1300000>;
+			opp-hz = /bits/ 64 <400000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@400000000,1200 {
+			opp-microvolt = <1200000 1200000 1300000>;
+			opp-hz = /bits/ 64 <400000000>;
+			opp-supported-hw = <0x0008>;
+		};
+	};
+
+	host1x_dvfs_opp_table: host1x-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@104500000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <104500000>;
+			opp-supported-hw = <0x000F>;
+		};
+
+		opp@133000000,1000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <133000000>;
+			opp-supported-hw = <0x000F>;
+		};
+
+		opp@166000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <166000000>;
+			opp-supported-hw = <0x000F>;
+		};
+	};
+
+	usbd_dvfs_opp_table: usbd-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@480000000 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <480000000>;
+		};
+	};
+
+	usb2_dvfs_opp_table: usb2-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@480000000 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <480000000>;
+		};
+	};
+
+	usb3_dvfs_opp_table: usb3-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@480000000 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <480000000>;
+		};
+	};
+
+	sdmmc1_dvfs_opp_table: sdmmc1-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@44000000 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <44000000>;
+		};
+
+		opp@52000000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <52000000>;
+		};
+	};
+
+	sdmmc2_dvfs_opp_table: sdmmc2-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@44000000 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <44000000>;
+		};
+
+		opp@52000000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <52000000>;
+		};
+	};
+
+	sdmmc3_dvfs_opp_table: sdmmc3-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@44000000 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <44000000>;
+		};
+
+		opp@52000000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <52000000>;
+		};
+	};
+
+	sdmmc4_dvfs_opp_table: sdmmc4-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@44000000 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <44000000>;
+		};
+
+		opp@52000000 {
+			opp-microvolt = <1000000 1000000 1300000>;
+			opp-hz = /bits/ 64 <52000000>;
+		};
+	};
+
+	hdmi_dvfs_opp_table: hdmi-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@148500000 {
+			opp-microvolt = <1200000 1200000 1300000>;
+			opp-hz = /bits/ 64 <148500000>;
+		};
+	};
+
+	dc0_dvfs_opp_table: dc0-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@158000000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <158000000>;
+			opp-supported-hw = <0x000F>;
+		};
+
+		opp@190000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <190000000>;
+			opp-supported-hw = <0x000F>;
+		};
+	};
+
+	dc1_dvfs_opp_table: dc1-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@158000000,950 {
+			opp-microvolt = <950000 950000 1300000>;
+			opp-hz = /bits/ 64 <158000000>;
+			opp-supported-hw = <0x000F>;
+		};
+
+		opp@190000000,1100 {
+			opp-microvolt = <1100000 1100000 1300000>;
+			opp-hz = /bits/ 64 <190000000>;
+			opp-supported-hw = <0x000F>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 6ce498178105..317bdf75ff6c 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -42,6 +42,7 @@ host1x@50000000 {
 		clock-names = "host1x";
 		resets = <&tegra_car 28>;
 		reset-names = "host1x";
+		operating-points-v2 = <&host1x_dvfs_opp_table>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -91,6 +92,7 @@ gr2d@54140000 {
 			clocks = <&tegra_car TEGRA20_CLK_GR2D>;
 			resets = <&tegra_car 21>;
 			reset-names = "2d";
+			operating-points-v2 = <&gr2d_dvfs_opp_table>;
 		};
 
 		gr3d@54180000 {
@@ -99,6 +101,7 @@ gr3d@54180000 {
 			clocks = <&tegra_car TEGRA20_CLK_GR3D>;
 			resets = <&tegra_car 24>;
 			reset-names = "3d";
+			operating-points-v2 = <&gr3d_dvfs_opp_table>;
 		};
 
 		dc@54200000 {
@@ -110,6 +113,7 @@ dc@54200000 {
 			clock-names = "dc", "parent";
 			resets = <&tegra_car 27>;
 			reset-names = "dc";
+			operating-points-v2 = <&dc0_dvfs_opp_table>;
 
 			nvidia,head = <0>;
 
@@ -138,6 +142,7 @@ dc@54240000 {
 			clock-names = "dc", "parent";
 			resets = <&tegra_car 26>;
 			reset-names = "dc";
+			operating-points-v2 = <&dc1_dvfs_opp_table>;
 
 			nvidia,head = <1>;
 
@@ -167,6 +172,7 @@ hdmi@54280000 {
 			resets = <&tegra_car 51>;
 			reset-names = "hdmi";
 			status = "disabled";
+			operating-points-v2 = <&hdmi_dvfs_opp_table>;
 		};
 
 		tvo@542c0000 {
@@ -319,6 +325,7 @@ vde@6001a000 {
 		clocks = <&tegra_car TEGRA20_CLK_VDE>;
 		reset-names = "vde", "mc";
 		resets = <&tegra_car 61>, <&mc TEGRA20_MC_RESET_VDE>;
+		operating-points-v2 = <&vde_dvfs_opp_table>;
 	};
 
 	apbmisc@70000800 {
@@ -755,6 +762,7 @@ usb@c5000000 {
 		nvidia,needs-double-reset;
 		nvidia,phy = <&phy1>;
 		status = "disabled";
+		operating-points-v2 = <&usbd_dvfs_opp_table>;
 	};
 
 	phy1: usb-phy@c5000000 {
@@ -792,6 +800,7 @@ usb@c5004000 {
 		reset-names = "usb";
 		nvidia,phy = <&phy2>;
 		status = "disabled";
+		operating-points-v2 = <&usb2_dvfs_opp_table>;
 	};
 
 	phy2: usb-phy@c5004000 {
@@ -818,6 +827,7 @@ usb@c5008000 {
 		reset-names = "usb";
 		nvidia,phy = <&phy3>;
 		status = "disabled";
+		operating-points-v2 = <&usb3_dvfs_opp_table>;
 	};
 
 	phy3: usb-phy@c5008000 {
@@ -852,6 +862,7 @@ mmc@c8000000 {
 		resets = <&tegra_car 14>;
 		reset-names = "sdhci";
 		status = "disabled";
+		operating-points-v2 = <&sdmmc1_dvfs_opp_table>;
 	};
 
 	mmc@c8000200 {
@@ -863,6 +874,7 @@ mmc@c8000200 {
 		resets = <&tegra_car 9>;
 		reset-names = "sdhci";
 		status = "disabled";
+		operating-points-v2 = <&sdmmc2_dvfs_opp_table>;
 	};
 
 	mmc@c8000400 {
@@ -874,6 +886,7 @@ mmc@c8000400 {
 		resets = <&tegra_car 69>;
 		reset-names = "sdhci";
 		status = "disabled";
+		operating-points-v2 = <&sdmmc3_dvfs_opp_table>;
 	};
 
 	mmc@c8000600 {
@@ -885,6 +898,7 @@ mmc@c8000600 {
 		resets = <&tegra_car 15>;
 		reset-names = "sdhci";
 		status = "disabled";
+		operating-points-v2 = <&sdmmc4_dvfs_opp_table>;
 	};
 
 	cpus {
-- 
2.27.0


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

* [PATCH v1 25/30] ARM: tegra: Add OPP tables for Tegra30 peripheral devices
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (23 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 24/30] ARM: tegra: Add OPP tables for Tegra20 peripheral devices Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 26/30] ARM: tegra: ventana: Add voltage supplies to DVFS-capable devices Dmitry Osipenko
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add OPP tables for Tegra30 SoC devices.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../arm/boot/dts/tegra30-peripherals-opp.dtsi | 415 ++++++++++++++++++
 arch/arm/boot/dts/tegra30.dtsi                |  13 +
 2 files changed, 428 insertions(+)

diff --git a/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi b/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
index cbe84d25e726..f8c522099dfe 100644
--- a/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
+++ b/arch/arm/boot/dts/tegra30-peripherals-opp.dtsi
@@ -380,4 +380,419 @@ opp@900000000 {
 			opp-peak-kBps = <7200000>;
 		};
 	};
+
+	vde_dvfs_opp_table: vde-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@228000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <228000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@247000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <247000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@275000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <275000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@304000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <304000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@332000000,1100 {
+			opp-microvolt = <1100000 1100000 1350000>;
+			opp-hz = /bits/ 64 <332000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@352000000,1100 {
+			opp-microvolt = <1100000 1100000 1350000>;
+			opp-hz = /bits/ 64 <352000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@380000000,1150 {
+			opp-microvolt = <1150000 1150000 1350000>;
+			opp-hz = /bits/ 64 <380000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@400000000,1150 {
+			opp-microvolt = <1150000 1150000 1350000>;
+			opp-hz = /bits/ 64 <400000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@416000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <416000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@437000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <437000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@484000000,1250 {
+			opp-microvolt = <1250000 1250000 1350000>;
+			opp-hz = /bits/ 64 <484000000>;
+			opp-supported-hw = <0x000C>;
+		};
+
+		opp@520000000,1300 {
+			opp-microvolt = <1300000 1300000 1350000>;
+			opp-hz = /bits/ 64 <520000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@600000000,1350 {
+			opp-microvolt = <1350000 1350000 1350000>;
+			opp-hz = /bits/ 64 <600000000>;
+			opp-supported-hw = <0x0004>;
+		};
+	};
+
+	gr2d_dvfs_opp_table: gr2d-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@267000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <267000000>;
+			opp-supported-hw = <0x0007>;
+		};
+
+		opp@285000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <285000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@304000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <304000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@332000000,1100 {
+			opp-microvolt = <1100000 1100000 1350000>;
+			opp-hz = /bits/ 64 <332000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@361000000,1100 {
+			opp-microvolt = <1100000 1100000 1350000>;
+			opp-hz = /bits/ 64 <361000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@380000000,1150 {
+			opp-microvolt = <1150000 1150000 1350000>;
+			opp-hz = /bits/ 64 <380000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@408000000,1150 {
+			opp-microvolt = <1150000 1150000 1350000>;
+			opp-hz = /bits/ 64 <408000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@416000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <416000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@446000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <446000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@484000000,1250 {
+			opp-microvolt = <1250000 1250000 1350000>;
+			opp-hz = /bits/ 64 <484000000>;
+			opp-supported-hw = <0x000C>;
+		};
+
+		opp@520000000,1300 {
+			opp-microvolt = <1300000 1300000 1350000>;
+			opp-hz = /bits/ 64 <520000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@600000000,1350 {
+			opp-microvolt = <1350000 1350000 1350000>;
+			opp-hz = /bits/ 64 <600000000>;
+			opp-supported-hw = <0x0004>;
+		};
+	};
+
+	gr3d_dvfs_opp_table: gr3d-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@234000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <234000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@247000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <247000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@285000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <285000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@304000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <304000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@332000000,1100 {
+			opp-microvolt = <1100000 1100000 1350000>;
+			opp-hz = /bits/ 64 <332000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@361000000,1100 {
+			opp-microvolt = <1100000 1100000 1350000>;
+			opp-hz = /bits/ 64 <361000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@380000000,1150 {
+			opp-microvolt = <1150000 1150000 1350000>;
+			opp-hz = /bits/ 64 <380000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@408000000,1150 {
+			opp-microvolt = <1150000 1150000 1350000>;
+			opp-hz = /bits/ 64 <408000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@416000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <416000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp@446000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <446000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@484000000,1250 {
+			opp-microvolt = <1250000 1250000 1350000>;
+			opp-hz = /bits/ 64 <484000000>;
+			opp-supported-hw = <0x000C>;
+		};
+
+		opp@520000000,1300 {
+			opp-microvolt = <1300000 1300000 1350000>;
+			opp-hz = /bits/ 64 <520000000>;
+			opp-supported-hw = <0x0004>;
+		};
+
+		opp@600000000,1350 {
+			opp-microvolt = <1350000 1350000 1350000>;
+			opp-hz = /bits/ 64 <600000000>;
+			opp-supported-hw = <0x0004>;
+		};
+	};
+
+	host1x_dvfs_opp_table: host1x-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@152000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <152000000>;
+			opp-supported-hw = <0x0007>;
+		};
+
+		opp@188000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <188000000>;
+			opp-supported-hw = <0x0007>;
+		};
+
+		opp@222000000,1100 {
+			opp-microvolt = <1100000 1100000 1350000>;
+			opp-hz = /bits/ 64 <222000000>;
+			opp-supported-hw = <0x0007>;
+		};
+
+		opp@242000000,1250 {
+			opp-microvolt = <1250000 1250000 1350000>;
+			opp-hz = /bits/ 64 <242000000>;
+			opp-supported-hw = <0x0008>;
+		};
+
+		opp@254000000,1150 {
+			opp-microvolt = <1150000 1150000 1350000>;
+			opp-hz = /bits/ 64 <254000000>;
+			opp-supported-hw = <0x0007>;
+		};
+
+		opp@267000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <267000000>;
+			opp-supported-hw = <0x0007>;
+		};
+
+		opp@300000000,1350 {
+			opp-microvolt = <1350000 1350000 1350000>;
+			opp-hz = /bits/ 64 <300000000>;
+			opp-supported-hw = <0x0004>;
+		};
+	};
+
+	usbd_dvfs_opp_table: usbd-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@480000000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <480000000>;
+		};
+	};
+
+	usb2_dvfs_opp_table: usb2-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@480000000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <480000000>;
+		};
+	};
+
+	usb3_dvfs_opp_table: usb3-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@480000000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <480000000>;
+		};
+	};
+
+	sdmmc1_dvfs_opp_table: sdmmc1-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@104000000 {
+			opp-microvolt = <950000 950000 1350000>;
+			opp-hz = /bits/ 64 <104000000>;
+		};
+
+		opp@208000000 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <208000000>;
+		};
+	};
+
+	sdmmc3_dvfs_opp_table: sdmmc3-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@104000000 {
+			opp-microvolt = <950000 950000 1350000>;
+			opp-hz = /bits/ 64 <104000000>;
+		};
+
+		opp@208000000 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <208000000>;
+		};
+	};
+
+	hdmi_dvfs_opp_table: hdmi-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@148500000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <148500000>;
+		};
+	};
+
+	pwm_dvfs_opp_table: pwm-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@408000000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <408000000>;
+		};
+	};
+
+	dc0_dvfs_opp_table: dc0-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@120000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <120000000>;
+			opp-supported-hw = <0x0009>;
+		};
+
+		opp@155000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <155000000>;
+			opp-supported-hw = <0x0006>;
+		};
+
+		opp@190000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <190000000>;
+			opp-supported-hw = <0x0009>;
+		};
+
+		opp@268000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <268000000>;
+			opp-supported-hw = <0x0006>;
+		};
+	};
+
+	dc1_dvfs_opp_table: dc1-opp-table {
+		compatible = "operating-points-v2";
+
+		opp@120000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <120000000>;
+			opp-supported-hw = <0x0009>;
+		};
+
+		opp@155000000,1000 {
+			opp-microvolt = <1000000 1000000 1350000>;
+			opp-hz = /bits/ 64 <155000000>;
+			opp-supported-hw = <0x0006>;
+		};
+
+		opp@190000000,1200 {
+			opp-microvolt = <1200000 1200000 1350000>;
+			opp-hz = /bits/ 64 <190000000>;
+			opp-supported-hw = <0x0009>;
+		};
+
+		opp@268000000,1050 {
+			opp-microvolt = <1050000 1050000 1350000>;
+			opp-hz = /bits/ 64 <268000000>;
+			opp-supported-hw = <0x0006>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 44a6dbba7081..c387d46f737c 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -123,6 +123,7 @@ host1x@50000000 {
 		resets = <&tegra_car 28>;
 		reset-names = "host1x";
 		iommus = <&mc TEGRA_SWGROUP_HC>;
+		operating-points-v2 = <&host1x_dvfs_opp_table>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -180,6 +181,7 @@ gr2d@54140000 {
 			clocks = <&tegra_car TEGRA30_CLK_GR2D>;
 			resets = <&tegra_car 21>;
 			reset-names = "2d";
+			operating-points-v2 = <&gr2d_dvfs_opp_table>;
 
 			iommus = <&mc TEGRA_SWGROUP_G2>;
 		};
@@ -193,6 +195,7 @@ gr3d@54180000 {
 			resets = <&tegra_car 24>,
 				 <&tegra_car 98>;
 			reset-names = "3d", "3d2";
+			operating-points-v2 = <&gr3d_dvfs_opp_table>;
 
 			iommus = <&mc TEGRA_SWGROUP_NV>,
 				 <&mc TEGRA_SWGROUP_NV2>;
@@ -207,6 +210,7 @@ dc@54200000 {
 			clock-names = "dc", "parent";
 			resets = <&tegra_car 27>;
 			reset-names = "dc";
+			operating-points-v2 = <&dc0_dvfs_opp_table>;
 
 			iommus = <&mc TEGRA_SWGROUP_DC>;
 
@@ -237,6 +241,7 @@ dc@54240000 {
 			clock-names = "dc", "parent";
 			resets = <&tegra_car 26>;
 			reset-names = "dc";
+			operating-points-v2 = <&dc1_dvfs_opp_table>;
 
 			iommus = <&mc TEGRA_SWGROUP_DCB>;
 
@@ -268,6 +273,7 @@ hdmi@54280000 {
 			resets = <&tegra_car 51>;
 			reset-names = "hdmi";
 			status = "disabled";
+			operating-points-v2 = <&hdmi_dvfs_opp_table>;
 		};
 
 		tvo@542c0000 {
@@ -466,6 +472,7 @@ vde@6001a000 {
 		reset-names = "vde", "mc";
 		resets = <&tegra_car 61>, <&mc TEGRA30_MC_RESET_VDE>;
 		iommus = <&mc TEGRA_SWGROUP_VDE>;
+		operating-points-v2 = <&vde_dvfs_opp_table>;
 	};
 
 	apbmisc@70000800 {
@@ -574,6 +581,7 @@ pwm: pwm@7000a000 {
 		resets = <&tegra_car 17>;
 		reset-names = "pwm";
 		status = "disabled";
+		operating-points-v2 = <&pwm_dvfs_opp_table>;
 	};
 
 	rtc@7000e000 {
@@ -906,6 +914,7 @@ mmc@78000000 {
 		resets = <&tegra_car 14>;
 		reset-names = "sdhci";
 		status = "disabled";
+		operating-points-v2 = <&sdmmc1_dvfs_opp_table>;
 	};
 
 	mmc@78000200 {
@@ -928,6 +937,7 @@ mmc@78000400 {
 		resets = <&tegra_car 69>;
 		reset-names = "sdhci";
 		status = "disabled";
+		operating-points-v2 = <&sdmmc3_dvfs_opp_table>;
 	};
 
 	mmc@78000600 {
@@ -952,6 +962,7 @@ usb@7d000000 {
 		nvidia,needs-double-reset;
 		nvidia,phy = <&phy1>;
 		status = "disabled";
+		operating-points-v2 = <&usbd_dvfs_opp_table>;
 	};
 
 	phy1: usb-phy@7d000000 {
@@ -991,6 +1002,7 @@ usb@7d004000 {
 		reset-names = "usb";
 		nvidia,phy = <&phy2>;
 		status = "disabled";
+		operating-points-v2 = <&usb2_dvfs_opp_table>;
 	};
 
 	phy2: usb-phy@7d004000 {
@@ -1029,6 +1041,7 @@ usb@7d008000 {
 		reset-names = "usb";
 		nvidia,phy = <&phy3>;
 		status = "disabled";
+		operating-points-v2 = <&usb3_dvfs_opp_table>;
 	};
 
 	phy3: usb-phy@7d008000 {
-- 
2.27.0


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

* [PATCH v1 26/30] ARM: tegra: ventana: Add voltage supplies to DVFS-capable devices
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (24 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 25/30] ARM: tegra: Add OPP tables for Tegra30 " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 27/30] ARM: tegra: paz00: " Dmitry Osipenko
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add voltage supplies to DVFS-capable devices in order to enable
system-wide voltage scaling and allow CORE/RTC regulators to go lower.

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

diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index b158771ac0b7..d5d90605e649 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -23,7 +23,19 @@ memory@0 {
 	};
 
 	host1x@50000000 {
+		core-supply = <&vdd_core>;
+
+		gr2d@54140000 {
+			core-supply = <&vdd_core>;
+		};
+
+		gr3d@54180000 {
+			core-supply = <&vdd_core>;
+		};
+
 		dc@54200000 {
+			core-supply = <&vdd_core>;
+
 			rgb {
 				status = "okay";
 
@@ -31,11 +43,16 @@ rgb {
 			};
 		};
 
+		dc@54240000 {
+			core-supply = <&vdd_core>;
+		};
+
 		hdmi@54280000 {
 			status = "okay";
 
 			vdd-supply = <&hdmi_vdd_reg>;
 			pll-supply = <&hdmi_pll_reg>;
+			core-supply = <&vdd_core>;
 
 			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
 			nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7)
@@ -43,6 +60,10 @@ hdmi@54280000 {
 		};
 	};
 
+	vde@6001a000 {
+		core-supply = <&vdd_core>;
+	};
+
 	pinmux@70000014 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -419,18 +440,28 @@ sys_reg: sys {
 					regulator-always-on;
 				};
 
-				sm0 {
+				vdd_core: sm0 {
 					regulator-name = "vdd_sm0,vdd_core";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-coupled-with = <&rtc_vdd &vdd_cpu>;
+					regulator-coupled-max-spread = <170000 550000>;
 					regulator-always-on;
+					regulator-boot-on;
+
+					nvidia,tegra-core-regulator;
 				};
 
-				sm1 {
+				vdd_cpu: sm1 {
 					regulator-name = "vdd_sm1,vdd_cpu";
-					regulator-min-microvolt = <1000000>;
-					regulator-max-microvolt = <1000000>;
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <1125000>;
+					regulator-coupled-with = <&vdd_core &rtc_vdd>;
+					regulator-coupled-max-spread = <550000 550000>;
 					regulator-always-on;
+					regulator-boot-on;
+
+					nvidia,tegra-cpu-regulator;
 				};
 
 				sm2_reg: sm2 {
@@ -449,10 +480,16 @@ ldo1 {
 					regulator-always-on;
 				};
 
-				ldo2 {
+				rtc_vdd: 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 = <&vdd_core &vdd_cpu>;
+					regulator-coupled-max-spread = <170000 550000>;
+					regulator-always-on;
+					regulator-boot-on;
+
+					nvidia,tegra-rtc-regulator;
 				};
 
 				ldo3 {
@@ -526,8 +563,13 @@ pmc@7000e400 {
 		nvidia,sys-clock-req-active-high;
 	};
 
+	memory-controller@7000f400 {
+		core-supply = <&vdd_core>;
+	};
+
 	usb@c5000000 {
 		status = "okay";
+		core-supply = <&vdd_core>;
 	};
 
 	usb-phy@c5000000 {
@@ -538,6 +580,7 @@ usb@c5004000 {
 		status = "okay";
 		nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 1)
 			GPIO_ACTIVE_LOW>;
+		core-supply = <&vdd_core>;
 	};
 
 	usb-phy@c5004000 {
@@ -548,6 +591,7 @@ usb-phy@c5004000 {
 
 	usb@c5008000 {
 		status = "okay";
+		core-supply = <&vdd_core>;
 	};
 
 	usb-phy@c5008000 {
@@ -559,6 +603,7 @@ mmc@c8000000 {
 		power-gpios = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
 		keep-power-in-suspend;
+		core-supply = <&vdd_core>;
 	};
 
 	mmc@c8000400 {
@@ -567,12 +612,14 @@ mmc@c8000400 {
 		wp-gpios = <&gpio TEGRA_GPIO(H, 1) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(I, 6) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
+		core-supply = <&vdd_core>;
 	};
 
 	mmc@c8000600 {
 		status = "okay";
 		bus-width = <8>;
 		non-removable;
+		core-supply = <&vdd_core>;
 	};
 
 	backlight: backlight {
-- 
2.27.0


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

* [PATCH v1 27/30] ARM: tegra: paz00: Add voltage supplies to DVFS-capable devices
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (25 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 26/30] ARM: tegra: ventana: Add voltage supplies to DVFS-capable devices Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 28/30] ARM: tegra: acer-a500: " Dmitry Osipenko
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add voltage supplies to DVFS-capable devices in order to enable
system-wide voltage scaling and allow CORE/RTC regulators to go lower.

Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20-paz00.dts | 40 ++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index 52a81d888424..d497eb149fba 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -26,7 +26,19 @@ memory@0 {
 	};
 
 	host1x@50000000 {
+		core-supply = <&core_vdd_reg>;
+
+		gr2d@54140000 {
+			core-supply = <&core_vdd_reg>;
+		};
+
+		gr3d@54180000 {
+			core-supply = <&core_vdd_reg>;
+		};
+
 		dc@54200000 {
+			core-supply = <&core_vdd_reg>;
+
 			rgb {
 				status = "okay";
 
@@ -34,11 +46,16 @@ rgb {
 			};
 		};
 
+		dc@54240000 {
+			core-supply = <&core_vdd_reg>;
+		};
+
 		hdmi@54280000 {
 			status = "okay";
 
 			vdd-supply = <&hdmi_vdd_reg>;
 			pll-supply = <&hdmi_pll_reg>;
+			core-supply = <&core_vdd_reg>;
 
 			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
 			nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7)
@@ -46,6 +63,10 @@ hdmi@54280000 {
 		};
 	};
 
+	vde@6001a000 {
+		core-supply = <&core_vdd_reg>;
+	};
+
 	pinmux@70000014 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -389,10 +410,10 @@ sys_reg: sys {
 
 				core_vdd_reg: sm0 {
 					regulator-name = "+1.2vs_sm0,vdd_core";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1225000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
 					regulator-coupled-with = <&rtc_vdd_reg &cpu_vdd_reg>;
-					regulator-coupled-max-spread = <170000 450000>;
+					regulator-coupled-max-spread = <170000 550000>;
 					regulator-always-on;
 
 					nvidia,tegra-core-regulator;
@@ -403,7 +424,7 @@ cpu_vdd_reg: sm1 {
 					regulator-min-microvolt = <750000>;
 					regulator-max-microvolt = <1100000>;
 					regulator-coupled-with = <&core_vdd_reg &rtc_vdd_reg>;
-					regulator-coupled-max-spread = <450000 450000>;
+					regulator-coupled-max-spread = <550000 550000>;
 					regulator-always-on;
 
 					nvidia,tegra-cpu-regulator;
@@ -427,10 +448,10 @@ ldo1 {
 
 				rtc_vdd_reg: ldo2 {
 					regulator-name = "+1.2vs_ldo2,vdd_rtc";
-					regulator-min-microvolt = <1200000>;
-					regulator-max-microvolt = <1225000>;
+					regulator-min-microvolt = <950000>;
+					regulator-max-microvolt = <1300000>;
 					regulator-coupled-with = <&core_vdd_reg &cpu_vdd_reg>;
-					regulator-coupled-max-spread = <170000 450000>;
+					regulator-coupled-max-spread = <170000 550000>;
 					regulator-always-on;
 
 					nvidia,tegra-rtc-regulator;
@@ -519,6 +540,7 @@ usb@c5000000 {
 		compatible = "nvidia,tegra20-udc";
 		status = "okay";
 		dr_mode = "peripheral";
+		core-supply = <&core_vdd_reg>;
 	};
 
 	usb-phy@c5000000 {
@@ -529,6 +551,7 @@ usb@c5004000 {
 		status = "okay";
 		nvidia,phy-reset-gpio = <&gpio TEGRA_GPIO(V, 0)
 			GPIO_ACTIVE_LOW>;
+		core-supply = <&core_vdd_reg>;
 	};
 
 	usb-phy@c5004000 {
@@ -539,6 +562,7 @@ usb-phy@c5004000 {
 
 	usb@c5008000 {
 		status = "okay";
+		core-supply = <&core_vdd_reg>;
 	};
 
 	usb-phy@c5008000 {
@@ -551,12 +575,14 @@ mmc@c8000000 {
 		wp-gpios = <&gpio TEGRA_GPIO(H, 1) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
 		bus-width = <4>;
+		core-supply = <&core_vdd_reg>;
 	};
 
 	mmc@c8000600 {
 		status = "okay";
 		bus-width = <8>;
 		non-removable;
+		core-supply = <&core_vdd_reg>;
 	};
 
 	backlight: backlight {
-- 
2.27.0


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

* [PATCH v1 28/30] ARM: tegra: acer-a500: Add voltage supplies to DVFS-capable devices
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (26 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 27/30] ARM: tegra: paz00: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 29/30] ARM: tegra: cardhu-a04: " Dmitry Osipenko
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add voltage supplies to DVFS-capable devices in order to enable
system-wide voltage scaling and allow CORE/RTC regulators to go lower.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../boot/dts/tegra20-acer-a500-picasso.dts    | 30 +++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
index b4ed88802387..5ab6872cd84c 100644
--- a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
+++ b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
@@ -60,7 +60,19 @@ linux,cma@30000000 {
 	};
 
 	host1x@50000000 {
+		core-supply = <&vdd_core>;
+
+		gr2d@54140000 {
+			core-supply = <&vdd_core>;
+		};
+
+		gr3d@54180000 {
+			core-supply = <&vdd_core>;
+		};
+
 		dc@54200000 {
+			core-supply = <&vdd_core>;
+
 			rgb {
 				status = "okay";
 
@@ -73,12 +85,17 @@ lcd_output: endpoint {
 			};
 		};
 
+		dc@54240000 {
+			core-supply = <&vdd_core>;
+		};
+
 		hdmi@54280000 {
 			status = "okay";
 
 			vdd-supply = <&hdmi_vdd_reg>;
 			pll-supply = <&hdmi_pll_reg>;
 			hdmi-supply = <&vdd_5v0_sys>;
+			core-supply = <&vdd_core>;
 
 			nvidia,ddc-i2c-bus = <&hdmi_ddc>;
 			nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7)
@@ -86,6 +103,10 @@ hdmi@54280000 {
 		};
 	};
 
+	vde@6001a000 {
+		core-supply = <&vdd_core>;
+	};
+
 	pinmux@70000014 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -565,7 +586,7 @@ sys_reg: sys {
 
 				vdd_core: sm0 {
 					regulator-name = "vdd_sm0,vdd_core";
-					regulator-min-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
 					regulator-max-microvolt = <1300000>;
 					regulator-coupled-with = <&rtc_vdd &vdd_cpu>;
 					regulator-coupled-max-spread = <170000 550000>;
@@ -606,7 +627,7 @@ ldo1 {
 
 				rtc_vdd: ldo2 {
 					regulator-name = "vdd_ldo2,vdd_rtc";
-					regulator-min-microvolt = <1200000>;
+					regulator-min-microvolt = <950000>;
 					regulator-max-microvolt = <1300000>;
 					regulator-coupled-with = <&vdd_core &vdd_cpu>;
 					regulator-coupled-max-spread = <170000 550000>;
@@ -696,6 +717,7 @@ usb@c5000000 {
 		compatible = "nvidia,tegra20-udc";
 		status = "okay";
 		dr_mode = "peripheral";
+		core-supply = <&vdd_core>;
 	};
 
 	usb-phy@c5000000 {
@@ -709,6 +731,7 @@ usb-phy@c5000000 {
 
 	usb@c5008000 {
 		status = "okay";
+		core-supply = <&vdd_core>;
 	};
 
 	usb-phy@c5008000 {
@@ -746,6 +769,7 @@ sdmmc1: mmc@c8000000 {
 		non-removable;
 
 		mmc-pwrseq = <&brcm_wifi_pwrseq>;
+		core-supply = <&vdd_core>;
 		vmmc-supply = <&vdd_3v3_sys>;
 		vqmmc-supply = <&vdd_3v3_sys>;
 
@@ -764,6 +788,7 @@ sdmmc3: mmc@c8000400 {
 		bus-width = <4>;
 		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
 		power-gpios = <&gpio TEGRA_GPIO(I, 6) GPIO_ACTIVE_HIGH>;
+		core-supply = <&vdd_core>;
 		vmmc-supply = <&vdd_3v3_sys>;
 		vqmmc-supply = <&vdd_3v3_sys>;
 	};
@@ -771,6 +796,7 @@ sdmmc3: mmc@c8000400 {
 	sdmmc4: mmc@c8000600 {
 		status = "okay";
 		bus-width = <8>;
+		core-supply = <&vdd_core>;
 		vmmc-supply = <&vcore_emmc>;
 		vqmmc-supply = <&vdd_3v3_sys>;
 		non-removable;
-- 
2.27.0


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

* [PATCH v1 29/30] ARM: tegra: cardhu-a04: Add voltage supplies to DVFS-capable devices
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (27 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 28/30] ARM: tegra: acer-a500: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-04 23:44 ` [PATCH v1 30/30] ARM: tegra: nexus7: " Dmitry Osipenko
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add voltage supplies to DVFS-capable devices in order to enable
system-wide voltage scaling.

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

diff --git a/arch/arm/boot/dts/tegra30-cardhu-a04.dts b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
index c1c0ca628af1..7149e5594537 100644
--- a/arch/arm/boot/dts/tegra30-cardhu-a04.dts
+++ b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
@@ -93,6 +93,34 @@ vdd_bl2_reg: regulator@106 {
 		gpio = <&gpio TEGRA_GPIO(DD, 0) GPIO_ACTIVE_HIGH>;
 	};
 
+	host1x@50000000 {
+		core-supply = <&vddcore_reg>;
+
+		gr2d@54140000 {
+			core-supply = <&vddcore_reg>;
+		};
+
+		gr3d@54180000 {
+			core-supply = <&vddcore_reg>;
+		};
+
+		dc@54200000 {
+			core-supply = <&vddcore_reg>;
+		};
+
+		dc@54240000 {
+			core-supply = <&vddcore_reg>;
+		};
+	};
+
+	vde@6001a000 {
+		core-supply = <&vddcore_reg>;
+	};
+
+	pwm: pwm@7000a000 {
+		core-supply = <&vddcore_reg>;
+	};
+
 	i2c@7000d000 {
 		pmic: tps65911@2d {
 			regulators {
@@ -117,6 +145,22 @@ vddcore_reg: tps62361@60 {
 		};
 	};
 
+	memory-controller@7000f400 {
+		core-supply = <&vddcore_reg>;
+	};
+
+	mmc@78000000 {
+		core-supply = <&vddcore_reg>;
+	};
+
+	mmc@78000600 {
+		core-supply = <&vddcore_reg>;
+	};
+
+	usb@7d008000 {
+		core-supply = <&vddcore_reg>;
+	};
+
 	cpus {
 		cpu0: cpu@0 {
 			cpu-supply = <&vddctrl_reg>;
-- 
2.27.0


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

* [PATCH v1 30/30] ARM: tegra: nexus7: Add voltage supplies to DVFS-capable devices
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (28 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 29/30] ARM: tegra: cardhu-a04: " Dmitry Osipenko
@ 2020-11-04 23:44 ` Dmitry Osipenko
  2020-11-05  1:45 ` [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Michał Mirosław
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-04 23:44 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet
  Cc: linux-samsung-soc, devel, linux-usb, linux-pwm, linux-mmc,
	linux-kernel, devicetree, dri-devel, linux-media, linux-tegra

Add voltage supplies to DVFS-capable devices in order to enable
system-wide voltage scaling.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../tegra30-asus-nexus7-grouper-common.dtsi   | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
index 261e266c61d8..2b405872ad2d 100644
--- a/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
+++ b/arch/arm/boot/dts/tegra30-asus-nexus7-grouper-common.dtsi
@@ -60,7 +60,19 @@ trustzone@bfe00000 {
 	};
 
 	host1x@50000000 {
+		core-supply = <&vdd_core>;
+
+		gr2d@54140000 {
+			core-supply = <&vdd_core>;
+		};
+
+		gr3d@54180000 {
+			core-supply = <&vdd_core>;
+		};
+
 		dc@54200000 {
+			core-supply = <&vdd_core>;
+
 			rgb {
 				status = "okay";
 
@@ -72,6 +84,10 @@ lcd_output: endpoint {
 				};
 			};
 		};
+
+		dc@54240000 {
+			core-supply = <&vdd_core>;
+		};
 	};
 
 	gpio@6000d000 {
@@ -90,6 +106,10 @@ init-low-power-mode {
 		};
 	};
 
+	vde@6001a000 {
+		core-supply = <&vdd_core>;
+	};
+
 	pinmux@70000868 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&state_default>;
@@ -835,6 +855,7 @@ bluetooth {
 
 	pwm: pwm@7000a000 {
 		status = "okay";
+		core-supply = <&vdd_core>;
 	};
 
 	i2c@7000c400 {
@@ -994,6 +1015,7 @@ sdmmc3: mmc@78000400 {
 
 		mmc-pwrseq = <&brcm_wifi_pwrseq>;
 		vmmc-supply = <&vdd_3v3_sys>;
+		core-supply = <&vdd_core>;
 		vqmmc-supply = <&vdd_1v8>;
 
 		/* Azurewave AW-NH665 BCM4330 */
@@ -1018,6 +1040,7 @@ usb@7d000000 {
 		compatible = "nvidia,tegra30-udc";
 		status = "okay";
 		dr_mode = "peripheral";
+		core-supply = <&vdd_core>;
 	};
 
 	usb-phy@7d000000 {
-- 
2.27.0


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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (29 preceding siblings ...)
  2020-11-04 23:44 ` [PATCH v1 30/30] ARM: tegra: nexus7: " Dmitry Osipenko
@ 2020-11-05  1:45 ` Michał Mirosław
  2020-11-05 13:57   ` Dmitry Osipenko
  2020-11-05  9:45 ` Ulf Hansson
       [not found] ` <160683107675.35139.13466076210885462180.b4-ty@kernel.org>
  32 siblings, 1 reply; 108+ messages in thread
From: Michał Mirosław @ 2020-11-05  1:45 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

On Thu, Nov 05, 2020 at 02:43:57AM +0300, Dmitry Osipenko wrote:
> Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs, which reduces
> power consumption and heating of the Tegra chips. Tegra SoC has multiple
> hardware units which belong to a core power domain of the SoC and share
> the core voltage. The voltage must be selected in accordance to a minimum
> requirement of every core hardware unit.
[...]

Just looked briefly through the series - it looks like there is a lot of
code duplication in *_init_opp_table() functions. Could this be made
more generic / data-driven?

Best Regards
Michał Mirosław

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
                   ` (30 preceding siblings ...)
  2020-11-05  1:45 ` [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Michał Mirosław
@ 2020-11-05  9:45 ` Ulf Hansson
  2020-11-05 10:06   ` Viresh Kumar
  2020-11-05 15:22   ` Dmitry Osipenko
       [not found] ` <160683107675.35139.13466076210885462180.b4-ty@kernel.org>
  32 siblings, 2 replies; 108+ messages in thread
From: Ulf Hansson @ 2020-11-05  9:45 UTC (permalink / raw)
  To: Dmitry Osipenko, Viresh Kumar
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Mauro Carvalho Chehab, Rob Herring, Marek Szyprowski, Peter Geis,
	Nicolas Chauvet, linux-samsung-soc, driverdevel, Linux USB List,
	linux-pwm, linux-mmc, Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

+ Viresh

On Thu, 5 Nov 2020 at 00:44, Dmitry Osipenko <digetx@gmail.com> wrote:
>
> Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs, which reduces
> power consumption and heating of the Tegra chips. Tegra SoC has multiple
> hardware units which belong to a core power domain of the SoC and share
> the core voltage. The voltage must be selected in accordance to a minimum
> requirement of every core hardware unit.
>
> The minimum core voltage requirement depends on:
>
>   1. Clock enable state of a hardware unit.
>   2. Clock frequency.
>   3. Unit's internal idling/active state.
>
> This series is tested on Acer A500 (T20), AC100 (T20), Nexus 7 (T30) and
> Ouya (T30) devices. I also added voltage scaling to the Ventana (T20) and
> Cardhu (T30) boards which are tested by NVIDIA's CI farm. Tegra30 is now up
> to 5C cooler on Nexus 7 and stays cool on Ouya (instead of becoming burning
> hot) while system is idling. It should be possible to improve this further
> by implementing a more advanced power management features for the kernel
> drivers.
>
> The DVFS support is opt-in for all boards, meaning that older DTBs will
> continue to work like they did it before this series. It should be possible
> to easily add the core voltage scaling support for Tegra114+ SoCs based on
> this grounding work later on, if anyone will want to implement it.
>
> WARNING(!) This series is made on top of the memory interconnect patches
>            which are currently under review [1]. The Tegra EMC driver
>            and devicetree-related patches need to be applied on top of
>            the ICC series.
>
> [1] https://patchwork.ozlabs.org/project/linux-tegra/list/?series=212196
>
> Dmitry Osipenko (30):
>   dt-bindings: host1x: Document OPP and voltage regulator properties
>   dt-bindings: mmc: tegra: Document OPP and voltage regulator properties
>   dt-bindings: pwm: tegra: Document OPP and voltage regulator properties
>   media: dt: bindings: tegra-vde: Document OPP and voltage regulator
>     properties
>   dt-binding: usb: ci-hdrc-usb2:  Document OPP and voltage regulator
>     properties
>   dt-bindings: usb: tegra-ehci: Document OPP and voltage regulator
>     properties
>   soc/tegra: Add sync state API
>   soc/tegra: regulators: Support Tegra SoC device sync state API
>   soc/tegra: regulators: Fix lockup when voltage-spread is out of range
>   regulator: Allow skipping disabled regulators in
>     regulator_check_consumers()
>   drm/tegra: dc: Support OPP and SoC core voltage scaling
>   drm/tegra: gr2d: Correct swapped device-tree compatibles
>   drm/tegra: gr2d: Support OPP and SoC core voltage scaling
>   drm/tegra: gr3d: Support OPP and SoC core voltage scaling
>   drm/tegra: hdmi: Support OPP and SoC core voltage scaling
>   gpu: host1x: Support OPP and SoC core voltage scaling
>   mmc: sdhci-tegra: Support OPP and core voltage scaling
>   pwm: tegra: Support OPP and core voltage scaling
>   media: staging: tegra-vde: Support OPP and SoC core voltage scaling
>   usb: chipidea: tegra: Support OPP and SoC core voltage scaling
>   usb: host: ehci-tegra: Support OPP and SoC core voltage scaling
>   memory: tegra20-emc: Support Tegra SoC device state syncing
>   memory: tegra30-emc: Support Tegra SoC device state syncing
>   ARM: tegra: Add OPP tables for Tegra20 peripheral devices
>   ARM: tegra: Add OPP tables for Tegra30 peripheral devices
>   ARM: tegra: ventana: Add voltage supplies to DVFS-capable devices
>   ARM: tegra: paz00: Add voltage supplies to DVFS-capable devices
>   ARM: tegra: acer-a500: Add voltage supplies to DVFS-capable devices
>   ARM: tegra: cardhu-a04: Add voltage supplies to DVFS-capable devices
>   ARM: tegra: nexus7: Add voltage supplies to DVFS-capable devices
>
>  .../display/tegra/nvidia,tegra20-host1x.txt   |  56 +++
>  .../bindings/media/nvidia,tegra-vde.txt       |  12 +
>  .../bindings/mmc/nvidia,tegra20-sdhci.txt     |  12 +
>  .../bindings/pwm/nvidia,tegra20-pwm.txt       |  13 +
>  .../devicetree/bindings/usb/ci-hdrc-usb2.txt  |   4 +
>  .../bindings/usb/nvidia,tegra20-ehci.txt      |   2 +
>  .../boot/dts/tegra20-acer-a500-picasso.dts    |  30 +-
>  arch/arm/boot/dts/tegra20-paz00.dts           |  40 +-
>  .../arm/boot/dts/tegra20-peripherals-opp.dtsi | 386 ++++++++++++++++
>  arch/arm/boot/dts/tegra20-ventana.dts         |  65 ++-
>  arch/arm/boot/dts/tegra20.dtsi                |  14 +
>  .../tegra30-asus-nexus7-grouper-common.dtsi   |  23 +
>  arch/arm/boot/dts/tegra30-cardhu-a04.dts      |  44 ++
>  .../arm/boot/dts/tegra30-peripherals-opp.dtsi | 415 ++++++++++++++++++
>  arch/arm/boot/dts/tegra30.dtsi                |  13 +
>  drivers/gpu/drm/tegra/Kconfig                 |   1 +
>  drivers/gpu/drm/tegra/dc.c                    | 138 +++++-
>  drivers/gpu/drm/tegra/dc.h                    |   5 +
>  drivers/gpu/drm/tegra/gr2d.c                  | 140 +++++-
>  drivers/gpu/drm/tegra/gr3d.c                  | 136 ++++++
>  drivers/gpu/drm/tegra/hdmi.c                  |  63 ++-
>  drivers/gpu/host1x/Kconfig                    |   1 +
>  drivers/gpu/host1x/dev.c                      |  87 ++++
>  drivers/memory/tegra/tegra20-emc.c            |   8 +-
>  drivers/memory/tegra/tegra30-emc.c            |   8 +-
>  drivers/mmc/host/Kconfig                      |   1 +
>  drivers/mmc/host/sdhci-tegra.c                |  70 ++-
>  drivers/pwm/Kconfig                           |   1 +
>  drivers/pwm/pwm-tegra.c                       |  84 +++-
>  drivers/regulator/core.c                      |  12 +-
>  .../soc/samsung/exynos-regulator-coupler.c    |   2 +-
>  drivers/soc/tegra/common.c                    | 152 ++++++-
>  drivers/soc/tegra/regulators-tegra20.c        |  25 +-
>  drivers/soc/tegra/regulators-tegra30.c        |  30 +-
>  drivers/staging/media/tegra-vde/Kconfig       |   1 +
>  drivers/staging/media/tegra-vde/vde.c         | 127 ++++++
>  drivers/staging/media/tegra-vde/vde.h         |   1 +
>  drivers/usb/chipidea/Kconfig                  |   1 +
>  drivers/usb/chipidea/ci_hdrc_tegra.c          |  79 ++++
>  drivers/usb/host/Kconfig                      |   1 +
>  drivers/usb/host/ehci-tegra.c                 |  79 ++++
>  include/linux/regulator/coupler.h             |   6 +-
>  include/soc/tegra/common.h                    |  22 +
>  43 files changed, 2360 insertions(+), 50 deletions(-)
>
> --
> 2.27.0
>

I need some more time to review this, but just a quick check found a
few potential issues...

The "core-supply", that you specify as a regulator for each
controller's device node, is not the way we describe power domains.
Instead, it seems like you should register a power-domain provider
(with the help of genpd) and implement the ->set_performance_state()
callback for it. Each device node should then be hooked up to this
power-domain, rather than to a "core-supply". For DT bindings, please
have a look at Documentation/devicetree/bindings/power/power-domain.yaml
and Documentation/devicetree/bindings/power/power_domain.txt.

In regards to the "sync state" problem (preventing to change
performance states until all consumers have been attached), this can
then be managed by the genpd provider driver instead.

Kind regards
Uffe

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-04 23:44 ` [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and " Dmitry Osipenko
@ 2020-11-05  9:58   ` Viresh Kumar
  2020-11-05 14:18     ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-05  9:58 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, driver-dev,
	linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On Thu, Nov 5, 2020 at 5:15 AM Dmitry Osipenko <digetx@gmail.com> wrote:

> diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c

> +static void sdhci_tegra_deinit_opp_table(void *data)
> +{
> +       struct device *dev = data;
> +       struct opp_table *opp_table;
> +
> +       opp_table = dev_pm_opp_get_opp_table(dev);

So you need to get an OPP table to put one :)
You need to save the pointer returned by dev_pm_opp_set_regulators() instead.

> +       dev_pm_opp_of_remove_table(dev);
> +       dev_pm_opp_put_regulators(opp_table);
> +       dev_pm_opp_put_opp_table(opp_table);
> +}
> +
> +static int devm_sdhci_tegra_init_opp_table(struct device *dev)
> +{
> +       struct opp_table *opp_table;
> +       const char *rname = "core";
> +       int err;
> +
> +       /* voltage scaling is optional */
> +       if (device_property_present(dev, "core-supply"))
> +               opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
> +       else


> +               opp_table = dev_pm_opp_get_opp_table(dev);

Nice. I didn't think that someone will end up abusing this API and so made it
available for all, but someone just did that. I will fix that in the OPP core.

Any idea why you are doing what you are doing here ?

> +
> +       if (IS_ERR(opp_table))
> +               return dev_err_probe(dev, PTR_ERR(opp_table),
> +                                   "failed to prepare OPP table\n");
> +
> +       /*
> +        * OPP table presence is optional and we want the set_rate() of OPP
> +        * API to work similarly to clk_set_rate() if table is missing in a
> +        * device-tree.  The add_table() errors out if OPP is missing in DT.
> +        */
> +       if (device_property_present(dev, "operating-points-v2")) {
> +               err = dev_pm_opp_of_add_table(dev);
> +               if (err) {
> +                       dev_err(dev, "failed to add OPP table: %d\n", err);
> +                       goto put_table;
> +               }
> +       }
> +
> +       err = devm_add_action(dev, sdhci_tegra_deinit_opp_table, dev);
> +       if (err)
> +               goto remove_table;
> +
> +       return 0;
> +
> +remove_table:
> +       dev_pm_opp_of_remove_table(dev);
> +put_table:
> +       dev_pm_opp_put_regulators(opp_table);
> +
> +       return err;
> +}
> +
>  static int sdhci_tegra_probe(struct platform_device *pdev)
>  {
>         const struct of_device_id *match;
> @@ -1621,6 +1681,10 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
>                 goto err_power_req;
>         }
>
> +       rc = devm_sdhci_tegra_init_opp_table(&pdev->dev);
> +       if (rc)
> +               goto err_parse_dt;
> +
>         /*
>          * Tegra210 has a separate SDMMC_LEGACY_TM clock used for host
>          * timeout clock and SW can choose TMCLK or SDCLK for hardware
> --
> 2.27.0
>
> _______________________________________________
> devel mailing list
> devel@linuxdriverproject.org
> http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05  9:45 ` Ulf Hansson
@ 2020-11-05 10:06   ` Viresh Kumar
  2020-11-05 10:34     ` Ulf Hansson
  2020-11-05 15:22   ` Dmitry Osipenko
  1 sibling, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-05 10:06 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On 05-11-20, 10:45, Ulf Hansson wrote:
> + Viresh

Thanks Ulf. I found a bug in OPP core because you cc'd me here :)

> On Thu, 5 Nov 2020 at 00:44, Dmitry Osipenko <digetx@gmail.com> wrote:
> I need some more time to review this, but just a quick check found a
> few potential issues...
> 
> The "core-supply", that you specify as a regulator for each
> controller's device node, is not the way we describe power domains.

Maybe I misunderstood your comment here, but there are two ways of
scaling the voltage of a device depending on if it is a regulator (and
can be modeled as one in the kernel) or a power domain.

In case of Qcom earlier (when we added the performance-state stuff),
the eventual hardware was out of kernel's control and we didn't wanted
(allowed) to model it as a virtual regulator just to pass the votes to
the RPM. And so we did what we did.

But if the hardware (where the voltage is required to be changed) is
indeed a regulator and is modeled as one, then what Dmitry has done
looks okay. i.e. add a supply in the device's node and microvolt
property in the DT entries.

-- 
viresh

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05 10:06   ` Viresh Kumar
@ 2020-11-05 10:34     ` Ulf Hansson
  2020-11-05 10:40       ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Ulf Hansson @ 2020-11-05 10:34 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On Thu, 5 Nov 2020 at 11:06, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> On 05-11-20, 10:45, Ulf Hansson wrote:
> > + Viresh
>
> Thanks Ulf. I found a bug in OPP core because you cc'd me here :)

Happy to help. :-)

>
> > On Thu, 5 Nov 2020 at 00:44, Dmitry Osipenko <digetx@gmail.com> wrote:
> > I need some more time to review this, but just a quick check found a
> > few potential issues...
> >
> > The "core-supply", that you specify as a regulator for each
> > controller's device node, is not the way we describe power domains.
>
> Maybe I misunderstood your comment here, but there are two ways of
> scaling the voltage of a device depending on if it is a regulator (and
> can be modeled as one in the kernel) or a power domain.

I am not objecting about scaling the voltage through a regulator,
that's fine to me. However, encoding a power domain as a regulator
(even if it may seem like a regulator) isn't. Well, unless Mark Brown
has changed his mind about this.

In this case, it seems like the regulator supply belongs in the
description of the power domain provider.

>
> In case of Qcom earlier (when we added the performance-state stuff),
> the eventual hardware was out of kernel's control and we didn't wanted
> (allowed) to model it as a virtual regulator just to pass the votes to
> the RPM. And so we did what we did.
>
> But if the hardware (where the voltage is required to be changed) is
> indeed a regulator and is modeled as one, then what Dmitry has done
> looks okay. i.e. add a supply in the device's node and microvolt
> property in the DT entries.

I guess I haven't paid enough attention how power domain regulators
are being described then. I was under the impression that the CPUfreq
case was a bit specific - and we had legacy bindings to stick with.

Can you point me to some other existing examples of where power domain
regulators are specified as a regulator in each device's node?

Kind regards
Uffe

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05 10:34     ` Ulf Hansson
@ 2020-11-05 10:40       ` Viresh Kumar
  2020-11-05 10:56         ` Ulf Hansson
  0 siblings, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-05 10:40 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On 05-11-20, 11:34, Ulf Hansson wrote:
> I am not objecting about scaling the voltage through a regulator,
> that's fine to me. However, encoding a power domain as a regulator
> (even if it may seem like a regulator) isn't. Well, unless Mark Brown
> has changed his mind about this.
>
> In this case, it seems like the regulator supply belongs in the
> description of the power domain provider.

Okay, I wasn't sure if it is a power domain or a regulator here. Btw,
how do we identify if it is a power domain or a regulator ?

> > In case of Qcom earlier (when we added the performance-state stuff),
> > the eventual hardware was out of kernel's control and we didn't wanted
> > (allowed) to model it as a virtual regulator just to pass the votes to
> > the RPM. And so we did what we did.
> >
> > But if the hardware (where the voltage is required to be changed) is
> > indeed a regulator and is modeled as one, then what Dmitry has done
> > looks okay. i.e. add a supply in the device's node and microvolt
> > property in the DT entries.
> 
> I guess I haven't paid enough attention how power domain regulators
> are being described then. I was under the impression that the CPUfreq
> case was a bit specific - and we had legacy bindings to stick with.
> 
> Can you point me to some other existing examples of where power domain
> regulators are specified as a regulator in each device's node?

No, I thought it is a regulator here and not a power domain.

-- 
viresh

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05 10:40       ` Viresh Kumar
@ 2020-11-05 10:56         ` Ulf Hansson
  2020-11-05 11:13           ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Ulf Hansson @ 2020-11-05 10:56 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On Thu, 5 Nov 2020 at 11:40, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> On 05-11-20, 11:34, Ulf Hansson wrote:
> > I am not objecting about scaling the voltage through a regulator,
> > that's fine to me. However, encoding a power domain as a regulator
> > (even if it may seem like a regulator) isn't. Well, unless Mark Brown
> > has changed his mind about this.
> >
> > In this case, it seems like the regulator supply belongs in the
> > description of the power domain provider.
>
> Okay, I wasn't sure if it is a power domain or a regulator here. Btw,
> how do we identify if it is a power domain or a regulator ?

Good question. It's not a crystal clear line in between them, I think.

A power domain to me, means that some part of a silicon (a group of
controllers or just a single piece, for example) needs some kind of
resource (typically a power rail) to be enabled to be functional, to
start with. If there are operating points involved, that's also a
clear indication to me, that it's not a regular regulator.

Maybe we should try to specify this more exactly in some
documentation, somewhere.

>
> > > In case of Qcom earlier (when we added the performance-state stuff),
> > > the eventual hardware was out of kernel's control and we didn't wanted
> > > (allowed) to model it as a virtual regulator just to pass the votes to
> > > the RPM. And so we did what we did.
> > >
> > > But if the hardware (where the voltage is required to be changed) is
> > > indeed a regulator and is modeled as one, then what Dmitry has done
> > > looks okay. i.e. add a supply in the device's node and microvolt
> > > property in the DT entries.
> >
> > I guess I haven't paid enough attention how power domain regulators
> > are being described then. I was under the impression that the CPUfreq
> > case was a bit specific - and we had legacy bindings to stick with.
> >
> > Can you point me to some other existing examples of where power domain
> > regulators are specified as a regulator in each device's node?
>
> No, I thought it is a regulator here and not a power domain.

Okay, thanks!

Kind regards
Uffe

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05 10:56         ` Ulf Hansson
@ 2020-11-05 11:13           ` Viresh Kumar
  2020-11-05 12:52             ` Ulf Hansson
  0 siblings, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-05 11:13 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On 05-11-20, 11:56, Ulf Hansson wrote:
> On Thu, 5 Nov 2020 at 11:40, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> > Btw, how do we identify if it is a power domain or a regulator ?

To be honest, I was a bit afraid and embarrassed to ask this question,
and was hoping people to make fun of me in return :)

> Good question. It's not a crystal clear line in between them, I think.

And I was relieved after reading this :)

> A power domain to me, means that some part of a silicon (a group of
> controllers or just a single piece, for example) needs some kind of
> resource (typically a power rail) to be enabled to be functional, to
> start with.

Isn't this what a part of regulator does as well ? i.e.
enabling/disabling of the regulator or power to a group of
controllers.

Over that the regulator does voltage/current scaling as well, which
normally the power domains don't do (though we did that in
performance-state case).

> If there are operating points involved, that's also a
> clear indication to me, that it's not a regular regulator.

Is there any example of that? I hope by OPP you meant both freq and
voltage here. I am not sure if I know of a case where a power domain
handles both of them.

> Maybe we should try to specify this more exactly in some
> documentation, somewhere.

I think yes, it is very much required. And in absence of that I think,
many (or most) of the platforms that also need to scale the voltage
would have modeled their hardware as a regulator and not a PM domain.

What I always thought was:

- Module that can just enable/disable power to a block of SoC is a
  power domain.

- Module that can enable/disable as well as scale voltage is a
  regulator.

And so I thought that this patchset has done the right thing. This
changed a bit with the qcom stuff where the IP to be configured was in
control of RPM and not Linux and so we couldn't add it as a regulator.
If it was controlled by Linux, it would have been a regulator in
kernel for sure :)

-- 
viresh

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05 11:13           ` Viresh Kumar
@ 2020-11-05 12:52             ` Ulf Hansson
  0 siblings, 0 replies; 108+ messages in thread
From: Ulf Hansson @ 2020-11-05 12:52 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On Thu, 5 Nov 2020 at 12:13, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> On 05-11-20, 11:56, Ulf Hansson wrote:
> > On Thu, 5 Nov 2020 at 11:40, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> > > Btw, how do we identify if it is a power domain or a regulator ?
>
> To be honest, I was a bit afraid and embarrassed to ask this question,
> and was hoping people to make fun of me in return :)
>
> > Good question. It's not a crystal clear line in between them, I think.
>
> And I was relieved after reading this :)
>
> > A power domain to me, means that some part of a silicon (a group of
> > controllers or just a single piece, for example) needs some kind of
> > resource (typically a power rail) to be enabled to be functional, to
> > start with.
>
> Isn't this what a part of regulator does as well ? i.e.
> enabling/disabling of the regulator or power to a group of
> controllers.

It could, but it shouldn't.

>
> Over that the regulator does voltage/current scaling as well, which
> normally the power domains don't do (though we did that in
> performance-state case).
>
> > If there are operating points involved, that's also a
> > clear indication to me, that it's not a regular regulator.
>
> Is there any example of that? I hope by OPP you meant both freq and
> voltage here. I am not sure if I know of a case where a power domain
> handles both of them.

It may be both voltage and frequency - but in some cases only voltage.
From HW point of view, many ARM legacy platforms have power domains
that work like this.

As you know, the DVFS case has in many years not been solved in a
generic way, but mostly via platform specific hacks.

The worst ones are probably those hacking clock drivers (which myself
also have contributed to). Have a look at clk_prcmu_opp_prepare(), for
example, which is used by the UX500 platform. Another option has been
to use the devfreq framework, but it has limitations in regards to
this too.

That said, I am hoping that people start moving towards the
deploying/implementing DVFS through the power-domain approach,
together with the OPPs. Maybe there are still some pieces missing from
an infrastructure point of view, but that should become more evident
as more starts using it.

>
> > Maybe we should try to specify this more exactly in some
> > documentation, somewhere.
>
> I think yes, it is very much required. And in absence of that I think,
> many (or most) of the platforms that also need to scale the voltage
> would have modeled their hardware as a regulator and not a PM domain.
>
> What I always thought was:
>
> - Module that can just enable/disable power to a block of SoC is a
>   power domain.
>
> - Module that can enable/disable as well as scale voltage is a
>   regulator.
>
> And so I thought that this patchset has done the right thing. This
> changed a bit with the qcom stuff where the IP to be configured was in
> control of RPM and not Linux and so we couldn't add it as a regulator.
> If it was controlled by Linux, it would have been a regulator in
> kernel for sure :)

In my view, DT bindings have consistently been pushed back during the
year, if they have tried to model power domains as regulator supplies
from consumer device nodes. Hence, people have tried other things, as
I mentioned above.

I definitely agree that we need to update some documentations,
explaining things more exactly. Additionally, it seems like a talk at
some conferences should make sense, as a way to spread the word.

Kind regards
Uffe

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05  1:45 ` [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Michał Mirosław
@ 2020-11-05 13:57   ` Dmitry Osipenko
  0 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-05 13:57 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

05.11.2020 04:45, Michał Mirosław пишет:
> On Thu, Nov 05, 2020 at 02:43:57AM +0300, Dmitry Osipenko wrote:
>> Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs, which reduces
>> power consumption and heating of the Tegra chips. Tegra SoC has multiple
>> hardware units which belong to a core power domain of the SoC and share
>> the core voltage. The voltage must be selected in accordance to a minimum
>> requirement of every core hardware unit.
> [...]
> 
> Just looked briefly through the series - it looks like there is a lot of
> code duplication in *_init_opp_table() functions. Could this be made
> more generic / data-driven?

Indeed, it should be possible to add a common helper. I had a quick
thought about doing it too, but then decided to defer for the starter
since there were some differences among the needs of the drivers. I'll
take a closer look for the v2, thanks!

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-05  9:58   ` Viresh Kumar
@ 2020-11-05 14:18     ` Dmitry Osipenko
  2020-11-06  6:15       ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-05 14:18 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, driver-dev,
	linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

05.11.2020 12:58, Viresh Kumar пишет:
>> +static void sdhci_tegra_deinit_opp_table(void *data)
>> +{
>> +       struct device *dev = data;
>> +       struct opp_table *opp_table;
>> +
>> +       opp_table = dev_pm_opp_get_opp_table(dev);
> So you need to get an OPP table to put one :)
> You need to save the pointer returned by dev_pm_opp_set_regulators() instead.

This is intentional because why do we need to save the pointer if we're
not using it and we know that we could get this pointer using OPP API?
This is exactly the same what I did for the CPUFreq driver [1] :)

[1]
https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/cpufreq/tegra20-cpufreq.c#L97

>> +       dev_pm_opp_of_remove_table(dev);
>> +       dev_pm_opp_put_regulators(opp_table);
>> +       dev_pm_opp_put_opp_table(opp_table);
>> +}
>> +
>> +static int devm_sdhci_tegra_init_opp_table(struct device *dev)
>> +{
>> +       struct opp_table *opp_table;
>> +       const char *rname = "core";
>> +       int err;
>> +
>> +       /* voltage scaling is optional */
>> +       if (device_property_present(dev, "core-supply"))
>> +               opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
>> +       else
> 
>> +               opp_table = dev_pm_opp_get_opp_table(dev);
> Nice. I didn't think that someone will end up abusing this API and so made it
> available for all, but someone just did that. I will fix that in the OPP core.

The dev_pm_opp_put_regulators() handles the case where regulator is
missing by acting as dev_pm_opp_get_opp_table(), but the
dev_pm_opp_set_regulators() doesn't do it. Hence I don't think this is
an abuse, but the OPP API drawback.

> Any idea why you are doing what you are doing here ?

Two reasons:

1. Voltage regulator is optional, but dev_pm_opp_set_regulators()
doesn't support optional regulators.

2. We need to balance the opp_table refcount in order to use OPP API
without polluting code with if(have_regulator), hence the
dev_pm_opp_get_opp_table() is needed for taking the opp_table reference
to have the same refcount as in the case of the dev_pm_opp_set_regulators().

I guess we could make dev_pm_opp_set_regulators(dev, count) to accept
regulators count=0 and then act as dev_pm_opp_get_opp_table(dev), will
it be acceptable?

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05  9:45 ` Ulf Hansson
  2020-11-05 10:06   ` Viresh Kumar
@ 2020-11-05 15:22   ` Dmitry Osipenko
  2020-11-08 12:19     ` Dmitry Osipenko
  1 sibling, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-05 15:22 UTC (permalink / raw)
  To: Ulf Hansson, Viresh Kumar
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Mauro Carvalho Chehab, Rob Herring, Marek Szyprowski, Peter Geis,
	Nicolas Chauvet, linux-samsung-soc, driverdevel, Linux USB List,
	linux-pwm, linux-mmc, Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

05.11.2020 12:45, Ulf Hansson пишет:
...
> I need some more time to review this, but just a quick check found a
> few potential issues...

Thank you for starting the review! I'm pretty sure it will take a couple
revisions until all the questions will be resolved :)

> The "core-supply", that you specify as a regulator for each
> controller's device node, is not the way we describe power domains.
> Instead, it seems like you should register a power-domain provider
> (with the help of genpd) and implement the ->set_performance_state()
> callback for it. Each device node should then be hooked up to this
> power-domain, rather than to a "core-supply". For DT bindings, please
> have a look at Documentation/devicetree/bindings/power/power-domain.yaml
> and Documentation/devicetree/bindings/power/power_domain.txt.
> 
> In regards to the "sync state" problem (preventing to change
> performance states until all consumers have been attached), this can
> then be managed by the genpd provider driver instead.

I'll need to take a closer look at GENPD, thank you for the suggestion.

Sounds like a software GENPD driver which manages clocks and voltages
could be a good idea, but it also could be an unnecessary
over-engineering. Let's see..

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

* Re: [PATCH v1 21/30] usb: host: ehci-tegra: Support OPP and SoC core voltage scaling
  2020-11-04 23:44 ` [PATCH v1 21/30] usb: host: ehci-tegra: " Dmitry Osipenko
@ 2020-11-05 16:07   ` Alan Stern
  2020-11-05 17:54     ` Dmitry Osipenko
  2020-11-05 18:02     ` Dmitry Osipenko
  0 siblings, 2 replies; 108+ messages in thread
From: Alan Stern @ 2020-11-05 16:07 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

On Thu, Nov 05, 2020 at 02:44:18AM +0300, Dmitry Osipenko wrote:
> Add initial OPP and SoC core voltage scaling support to the Tegra EHCI
> driver. This is required for enabling system-wide DVFS on older Tegra
> SoCs.
> 
> Tested-by: Peter Geis <pgwipeout@gmail.com>
> Tested-by: Nicolas Chauvet <kwizart@gmail.com>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---

I'm no expert on OPP stuff, but some of what you have done here looks 
peculiar.

> diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
> index 869d9c4de5fc..0976577f54b4 100644
> --- a/drivers/usb/host/ehci-tegra.c
> +++ b/drivers/usb/host/ehci-tegra.c
> @@ -17,6 +17,7 @@
>  #include <linux/of_device.h>
>  #include <linux/of_gpio.h>
>  #include <linux/platform_device.h>
> +#include <linux/pm_opp.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/reset.h>
>  #include <linux/slab.h>
> @@ -364,6 +365,79 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
>  	free_dma_aligned_buffer(urb);
>  }
>  
> +static void tegra_ehci_deinit_opp_table(void *data)
> +{
> +	struct device *dev = data;
> +	struct opp_table *opp_table;
> +
> +	opp_table = dev_pm_opp_get_opp_table(dev);
> +	dev_pm_opp_of_remove_table(dev);
> +	dev_pm_opp_put_regulators(opp_table);
> +	dev_pm_opp_put_opp_table(opp_table);
> +}
> +
> +static int devm_tegra_ehci_init_opp_table(struct device *dev)
> +{
> +	unsigned long rate = ULONG_MAX;
> +	struct opp_table *opp_table;
> +	const char *rname = "core";
> +	struct dev_pm_opp *opp;
> +	int err;
> +
> +	/* legacy device-trees don't have OPP table */
> +	if (!device_property_present(dev, "operating-points-v2"))
> +		return 0;
> +
> +	/* voltage scaling is optional */
> +	if (device_property_present(dev, "core-supply"))
> +		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
> +	else
> +		opp_table = dev_pm_opp_get_opp_table(dev);
> +
> +	if (IS_ERR(opp_table))
> +		return dev_err_probe(dev, PTR_ERR(opp_table),
> +				     "failed to prepare OPP table\n");
> +
> +	err = dev_pm_opp_of_add_table(dev);
> +	if (err) {
> +		dev_err(dev, "failed to add OPP table: %d\n", err);
> +		goto put_table;
> +	}
> +
> +	/* find suitable OPP for the maximum clock rate */
> +	opp = dev_pm_opp_find_freq_floor(dev, &rate);
> +	err = PTR_ERR_OR_ZERO(opp);
> +	if (err) {
> +		dev_err(dev, "failed to get OPP: %d\n", err);
> +		goto remove_table;
> +	}
> +
> +	dev_pm_opp_put(opp);
> +
> +	/*
> +	 * First dummy rate-set initializes voltage vote by setting voltage
> +	 * in accordance to the clock rate.
> +	 */
> +	err = dev_pm_opp_set_rate(dev, rate);
> +	if (err) {
> +		dev_err(dev, "failed to initialize OPP clock: %d\n", err);
> +		goto remove_table;
> +	}
> +
> +	err = devm_add_action(dev, tegra_ehci_deinit_opp_table, dev);
> +	if (err)
> +		goto remove_table;
> +
> +	return 0;
> +
> +remove_table:
> +	dev_pm_opp_of_remove_table(dev);
> +put_table:
> +	dev_pm_opp_put_regulators(opp_table);

Do you really want to use the same error unwinding for opp_table values 
obtained from dev_pm_opp_set_regulators() as from 
dev_pm_opp_get_opp_table()?

> +
> +	return err;
> +}
> +
>  static const struct tegra_ehci_soc_config tegra30_soc_config = {
>  	.has_hostpc = true,
>  };
> @@ -431,6 +505,11 @@ static int tegra_ehci_probe(struct platform_device *pdev)
>  		goto cleanup_hcd_create;
>  	}
>  
> +	err = devm_tegra_ehci_init_opp_table(&pdev->dev);
> +	if (err)
> +		return dev_err_probe(&pdev->dev, err,
> +				     "Failed to initialize OPP\n");

Why log a second error message?  Just return err.

Alan Stern

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

* Re: [PATCH v1 21/30] usb: host: ehci-tegra: Support OPP and SoC core voltage scaling
  2020-11-05 16:07   ` Alan Stern
@ 2020-11-05 17:54     ` Dmitry Osipenko
  2020-11-05 18:02     ` Dmitry Osipenko
  1 sibling, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-05 17:54 UTC (permalink / raw)
  To: Alan Stern
  Cc: Thierry Reding, Jonathan Hunter, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

05.11.2020 19:07, Alan Stern пишет:
> Do you really want to use the same error unwinding for opp_table values 
> obtained from dev_pm_opp_set_regulators() as from 
> dev_pm_opp_get_opp_table()?

They both are pointing at the same opp_table, which is refcounted.

The dev_pm_opp_set_regulators() is dev_pm_opp_get_opp_table() + it sets
regulator for the table.

https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/opp/core.c#L1756

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

* Re: [PATCH v1 21/30] usb: host: ehci-tegra: Support OPP and SoC core voltage scaling
  2020-11-05 16:07   ` Alan Stern
  2020-11-05 17:54     ` Dmitry Osipenko
@ 2020-11-05 18:02     ` Dmitry Osipenko
  1 sibling, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-05 18:02 UTC (permalink / raw)
  To: Alan Stern
  Cc: Thierry Reding, Jonathan Hunter, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

05.11.2020 19:07, Alan Stern пишет:
>> +	err = devm_tegra_ehci_init_opp_table(&pdev->dev);
>> +	if (err)
>> +		return dev_err_probe(&pdev->dev, err,
>> +				     "Failed to initialize OPP\n");
> Why log a second error message?  Just return err.

Indeed, thanks.

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-05 14:18     ` Dmitry Osipenko
@ 2020-11-06  6:15       ` Viresh Kumar
  2020-11-06 13:17         ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-06  6:15 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, driver-dev,
	linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On 05-11-20, 17:18, Dmitry Osipenko wrote:
> 05.11.2020 12:58, Viresh Kumar пишет:
> >> +static void sdhci_tegra_deinit_opp_table(void *data)
> >> +{
> >> +       struct device *dev = data;
> >> +       struct opp_table *opp_table;
> >> +
> >> +       opp_table = dev_pm_opp_get_opp_table(dev);
> > So you need to get an OPP table to put one :)
> > You need to save the pointer returned by dev_pm_opp_set_regulators() instead.
> 
> This is intentional because why do we need to save the pointer if we're
> not using it and we know that we could get this pointer using OPP API?

Because it is highly inefficient and it doesn't follow the rules set
by the OPP core. Hypothetically speaking, the OPP core is free to
allocate the OPP table structure as much as it wants, and if you don't
use the value returned back to you earlier (think of it as a cookie
assigned to your driver), then it will eventually lead to memory leak.

> This is exactly the same what I did for the CPUFreq driver [1] :)

I will strongly suggest you to save the pointer here and do the same
in the cpufreq driver as well.

> >> +static int devm_sdhci_tegra_init_opp_table(struct device *dev)
> >> +{
> >> +       struct opp_table *opp_table;
> >> +       const char *rname = "core";
> >> +       int err;
> >> +
> >> +       /* voltage scaling is optional */
> >> +       if (device_property_present(dev, "core-supply"))
> >> +               opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
> >> +       else
> > 
> >> +               opp_table = dev_pm_opp_get_opp_table(dev);

To make it further clear, this will end up allocating an OPP table for
you, which it shouldn't have.

> > Nice. I didn't think that someone will end up abusing this API and so made it
> > available for all, but someone just did that. I will fix that in the OPP core.

To be fair, I allowed the cpufreq-dt driver to abuse it too, which I
am going to fix shortly.

> The dev_pm_opp_put_regulators() handles the case where regulator is
> missing by acting as dev_pm_opp_get_opp_table(), but the
> dev_pm_opp_set_regulators() doesn't do it. Hence I don't think this is
> an abuse, but the OPP API drawback.

I am not sure what you meant here. Normally you are required to call
dev_pm_opp_put_regulators() only if you have called
dev_pm_opp_set_regulators() earlier. And the refcount stays in
balance.

> > Any idea why you are doing what you are doing here ?
> 
> Two reasons:
> 
> 1. Voltage regulator is optional, but dev_pm_opp_set_regulators()
> doesn't support optional regulators.
> 
> 2. We need to balance the opp_table refcount in order to use OPP API
> without polluting code with if(have_regulator), hence the
> dev_pm_opp_get_opp_table() is needed for taking the opp_table reference
> to have the same refcount as in the case of the dev_pm_opp_set_regulators().

I am going to send a patchset shortly after which this call to
dev_pm_opp_get_opp_table() will fail, if it is called before adding
the OPP table.

> I guess we could make dev_pm_opp_set_regulators(dev, count) to accept
> regulators count=0 and then act as dev_pm_opp_get_opp_table(dev), will
> it be acceptable?

Setting regulators for count as 0 doesn't sound good to me.

But, I understand that you don't want to have that if (have_regulator)
check, and it is a fair request. What I will instead do is, allow all
dev_pm_opp_put*() API to start accepting a NULL pointer for the OPP
table and fail silently. And so you won't be required to have this
unwanted check. But you will be required to save the pointer returned
back by dev_pm_opp_set_regulators(), which is the right thing to do
anyways.

-- 
viresh

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-06  6:15       ` Viresh Kumar
@ 2020-11-06 13:17         ` Dmitry Osipenko
  2020-11-06 13:41           ` Frank Lee
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-06 13:17 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, driver-dev,
	linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

06.11.2020 09:15, Viresh Kumar пишет:
> Setting regulators for count as 0 doesn't sound good to me.
> 
> But, I understand that you don't want to have that if (have_regulator)
> check, and it is a fair request. What I will instead do is, allow all
> dev_pm_opp_put*() API to start accepting a NULL pointer for the OPP
> table and fail silently. And so you won't be required to have this
> unwanted check. But you will be required to save the pointer returned
> back by dev_pm_opp_set_regulators(), which is the right thing to do
> anyways.

Perhaps even a better variant could be to add a devm versions of the OPP
API functions, then drivers won't need to care about storing the
opp_table pointer if it's unused by drivers.

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-06 13:17         ` Dmitry Osipenko
@ 2020-11-06 13:41           ` Frank Lee
  2020-11-09  5:00             ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Frank Lee @ 2020-11-06 13:41 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Viresh Kumar, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On Fri, Nov 6, 2020 at 9:18 PM Dmitry Osipenko <digetx@gmail.com> wrote:
>
> 06.11.2020 09:15, Viresh Kumar пишет:
> > Setting regulators for count as 0 doesn't sound good to me.
> >
> > But, I understand that you don't want to have that if (have_regulator)
> > check, and it is a fair request. What I will instead do is, allow all
> > dev_pm_opp_put*() API to start accepting a NULL pointer for the OPP
> > table and fail silently. And so you won't be required to have this
> > unwanted check. But you will be required to save the pointer returned
> > back by dev_pm_opp_set_regulators(), which is the right thing to do
> > anyways.
>
> Perhaps even a better variant could be to add a devm versions of the OPP
> API functions, then drivers won't need to care about storing the
> opp_table pointer if it's unused by drivers.

I think so. The consumer may not be so concerned about the status of
these OPP tables.
If the driver needs to manage the release, it needs to add a pointer
to their driver global structure.

Maybe it's worth having these devm interfaces for opp.

Yangtao

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-05 15:22   ` Dmitry Osipenko
@ 2020-11-08 12:19     ` Dmitry Osipenko
  2020-11-09  4:43       ` Viresh Kumar
  2020-11-11 11:38       ` Ulf Hansson
  0 siblings, 2 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-08 12:19 UTC (permalink / raw)
  To: Ulf Hansson, Viresh Kumar
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Mauro Carvalho Chehab, Rob Herring, Marek Szyprowski, Peter Geis,
	Nicolas Chauvet, linux-samsung-soc, driverdevel, Linux USB List,
	linux-pwm, linux-mmc, Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

05.11.2020 18:22, Dmitry Osipenko пишет:
> 05.11.2020 12:45, Ulf Hansson пишет:
> ...
>> I need some more time to review this, but just a quick check found a
>> few potential issues...
> 
> Thank you for starting the review! I'm pretty sure it will take a couple
> revisions until all the questions will be resolved :)
> 
>> The "core-supply", that you specify as a regulator for each
>> controller's device node, is not the way we describe power domains.
>> Instead, it seems like you should register a power-domain provider
>> (with the help of genpd) and implement the ->set_performance_state()
>> callback for it. Each device node should then be hooked up to this
>> power-domain, rather than to a "core-supply". For DT bindings, please
>> have a look at Documentation/devicetree/bindings/power/power-domain.yaml
>> and Documentation/devicetree/bindings/power/power_domain.txt.
>>
>> In regards to the "sync state" problem (preventing to change
>> performance states until all consumers have been attached), this can
>> then be managed by the genpd provider driver instead.
> 
> I'll need to take a closer look at GENPD, thank you for the suggestion.
> 
> Sounds like a software GENPD driver which manages clocks and voltages
> could be a good idea, but it also could be an unnecessary
> over-engineering. Let's see..
> 

Hello Ulf and all,

I took a detailed look at the GENPD and tried to implement it. Here is
what was found:

1. GENPD framework doesn't aggregate performance requests from the
attached devices. This means that if deviceA requests performance state
10 and then deviceB requests state 3, then framework will set domain's
state to 3 instead of 10.

https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/base/power/domain.c#L376

2. GENPD framework has a sync() callback in the genpd.domain structure,
but this callback isn't allowed to be used by the GENPD implementation.
The GENPD framework always overrides that callback for its own needs.
Hence GENPD doesn't allow to solve the bootstrapping
state-synchronization problem in a nice way.

https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/base/power/domain.c#L2606

3. Tegra doesn't have a dedicated hardware power-controller for the core
domain, instead there is only an external voltage regulator. Hence we
will need to create a phony device-tree node for the virtual power
domain, which is probably a wrong thing to do.

===

Perhaps it should be possible to create some hacks to work around
bullets 2 and 3 in order to achieve what we need for DVFS on Tegra, but
bullet 1 isn't solvable without changing how the GENPD core works.

Altogether, the GENPD in its current form is a wrong abstraction for a
system-wide DVFS in a case where multiple devices share power domain and
this domain is a voltage regulator. The regulator framework is the
correct abstraction in this case for today.

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-08 12:19     ` Dmitry Osipenko
@ 2020-11-09  4:43       ` Viresh Kumar
  2020-11-09  4:47         ` Dmitry Osipenko
  2020-11-11 11:38       ` Ulf Hansson
  1 sibling, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-09  4:43 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Ulf Hansson, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On 08-11-20, 15:19, Dmitry Osipenko wrote:
> I took a detailed look at the GENPD and tried to implement it. Here is
> what was found:
> 
> 1. GENPD framework doesn't aggregate performance requests from the
> attached devices. This means that if deviceA requests performance state
> 10 and then deviceB requests state 3, then framework will set domain's
> state to 3 instead of 10.

It does. Look at _genpd_reeval_performance_state().

-- 
viresh

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-09  4:43       ` Viresh Kumar
@ 2020-11-09  4:47         ` Dmitry Osipenko
  2020-11-09  5:10           ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-09  4:47 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Ulf Hansson, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

09.11.2020 07:43, Viresh Kumar пишет:
> On 08-11-20, 15:19, Dmitry Osipenko wrote:
>> I took a detailed look at the GENPD and tried to implement it. Here is
>> what was found:
>>
>> 1. GENPD framework doesn't aggregate performance requests from the
>> attached devices. This means that if deviceA requests performance state
>> 10 and then deviceB requests state 3, then framework will set domain's
>> state to 3 instead of 10.
> 
> It does. Look at _genpd_reeval_performance_state().
> 

Thanks, I probably had a bug in the quick prototype and then overlooked
that function.

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-06 13:41           ` Frank Lee
@ 2020-11-09  5:00             ` Viresh Kumar
  2020-11-09  5:08               ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-09  5:00 UTC (permalink / raw)
  To: Frank Lee
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On 06-11-20, 21:41, Frank Lee wrote:
> On Fri, Nov 6, 2020 at 9:18 PM Dmitry Osipenko <digetx@gmail.com> wrote:
> >
> > 06.11.2020 09:15, Viresh Kumar пишет:
> > > Setting regulators for count as 0 doesn't sound good to me.
> > >
> > > But, I understand that you don't want to have that if (have_regulator)
> > > check, and it is a fair request. What I will instead do is, allow all
> > > dev_pm_opp_put*() API to start accepting a NULL pointer for the OPP
> > > table and fail silently. And so you won't be required to have this
> > > unwanted check. But you will be required to save the pointer returned
> > > back by dev_pm_opp_set_regulators(), which is the right thing to do
> > > anyways.
> >
> > Perhaps even a better variant could be to add a devm versions of the OPP
> > API functions, then drivers won't need to care about storing the
> > opp_table pointer if it's unused by drivers.
> 
> I think so. The consumer may not be so concerned about the status of
> these OPP tables.
> If the driver needs to manage the release, it needs to add a pointer
> to their driver global structure.
> 
> Maybe it's worth having these devm interfaces for opp.

Sure if there are enough users of this, I am all for it. I was fine
with the patches you sent, just that there were not a lot of users of
it and so I pushed them back. If we find that we have more users of it
now, we can surely get that back.

-- 
viresh

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-09  5:00             ` Viresh Kumar
@ 2020-11-09  5:08               ` Dmitry Osipenko
  2020-11-09  5:10                 ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-09  5:08 UTC (permalink / raw)
  To: Viresh Kumar, Frank Lee
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, driver-dev,
	linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

09.11.2020 08:00, Viresh Kumar пишет:
> On 06-11-20, 21:41, Frank Lee wrote:
>> On Fri, Nov 6, 2020 at 9:18 PM Dmitry Osipenko <digetx@gmail.com> wrote:
>>>
>>> 06.11.2020 09:15, Viresh Kumar пишет:
>>>> Setting regulators for count as 0 doesn't sound good to me.
>>>>
>>>> But, I understand that you don't want to have that if (have_regulator)
>>>> check, and it is a fair request. What I will instead do is, allow all
>>>> dev_pm_opp_put*() API to start accepting a NULL pointer for the OPP
>>>> table and fail silently. And so you won't be required to have this
>>>> unwanted check. But you will be required to save the pointer returned
>>>> back by dev_pm_opp_set_regulators(), which is the right thing to do
>>>> anyways.
>>>
>>> Perhaps even a better variant could be to add a devm versions of the OPP
>>> API functions, then drivers won't need to care about storing the
>>> opp_table pointer if it's unused by drivers.
>>
>> I think so. The consumer may not be so concerned about the status of
>> these OPP tables.
>> If the driver needs to manage the release, it needs to add a pointer
>> to their driver global structure.
>>
>> Maybe it's worth having these devm interfaces for opp.
> 
> Sure if there are enough users of this, I am all for it. I was fine
> with the patches you sent, just that there were not a lot of users of
> it and so I pushed them back. If we find that we have more users of it
> now, we can surely get that back.
> 

There was already attempt to add the devm? Could you please give me a
link to the patches?

I already prepared a patch which adds the devm helpers. It helps to keep
code cleaner and readable.

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-09  5:08               ` Dmitry Osipenko
@ 2020-11-09  5:10                 ` Viresh Kumar
  2020-11-09  5:19                   ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-09  5:10 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Frank Lee, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On 09-11-20, 08:08, Dmitry Osipenko wrote:
> 09.11.2020 08:00, Viresh Kumar пишет:
> > On 06-11-20, 21:41, Frank Lee wrote:
> >> On Fri, Nov 6, 2020 at 9:18 PM Dmitry Osipenko <digetx@gmail.com> wrote:
> >>>
> >>> 06.11.2020 09:15, Viresh Kumar пишет:
> >>>> Setting regulators for count as 0 doesn't sound good to me.
> >>>>
> >>>> But, I understand that you don't want to have that if (have_regulator)
> >>>> check, and it is a fair request. What I will instead do is, allow all
> >>>> dev_pm_opp_put*() API to start accepting a NULL pointer for the OPP
> >>>> table and fail silently. And so you won't be required to have this
> >>>> unwanted check. But you will be required to save the pointer returned
> >>>> back by dev_pm_opp_set_regulators(), which is the right thing to do
> >>>> anyways.
> >>>
> >>> Perhaps even a better variant could be to add a devm versions of the OPP
> >>> API functions, then drivers won't need to care about storing the
> >>> opp_table pointer if it's unused by drivers.
> >>
> >> I think so. The consumer may not be so concerned about the status of
> >> these OPP tables.
> >> If the driver needs to manage the release, it needs to add a pointer
> >> to their driver global structure.
> >>
> >> Maybe it's worth having these devm interfaces for opp.
> > 
> > Sure if there are enough users of this, I am all for it. I was fine
> > with the patches you sent, just that there were not a lot of users of
> > it and so I pushed them back. If we find that we have more users of it
> > now, we can surely get that back.
> > 
> 
> There was already attempt to add the devm? Could you please give me a
> link to the patches?
> 
> I already prepared a patch which adds the devm helpers. It helps to keep
> code cleaner and readable.

https://lore.kernel.org/lkml/20201012135517.19468-1-frank@allwinnertech.com/

-- 
viresh

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-09  4:47         ` Dmitry Osipenko
@ 2020-11-09  5:10           ` Dmitry Osipenko
  2020-11-09  5:12             ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-09  5:10 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Ulf Hansson, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

09.11.2020 07:47, Dmitry Osipenko пишет:
> 09.11.2020 07:43, Viresh Kumar пишет:
>> On 08-11-20, 15:19, Dmitry Osipenko wrote:
>>> I took a detailed look at the GENPD and tried to implement it. Here is
>>> what was found:
>>>
>>> 1. GENPD framework doesn't aggregate performance requests from the
>>> attached devices. This means that if deviceA requests performance state
>>> 10 and then deviceB requests state 3, then framework will set domain's
>>> state to 3 instead of 10.
>>
>> It does. Look at _genpd_reeval_performance_state().
>>
> 
> Thanks, I probably had a bug in the quick prototype and then overlooked
> that function.
> 

If a non-hardware device-tree node is okay to have for the domain, then
I can try again.

What I also haven't mentioned is that GENPD adds some extra complexity
to some drivers (3d, video decoder) because we will need to handle both
new GENPD and legacy Tegra specific pre-genpd era domains.

I'm also not exactly sure how the topology of domains should look like
because Tegra has a power-controller (PMC) which manages power rail of a
few hardware units. Perhaps it should be

  device -> PMC domain -> CORE domain

but not exactly sure for now.

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-09  5:10           ` Dmitry Osipenko
@ 2020-11-09  5:12             ` Viresh Kumar
  0 siblings, 0 replies; 108+ messages in thread
From: Viresh Kumar @ 2020-11-09  5:12 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Ulf Hansson, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On 09-11-20, 08:10, Dmitry Osipenko wrote:
> 09.11.2020 07:47, Dmitry Osipenko пишет:
> > 09.11.2020 07:43, Viresh Kumar пишет:
> >> On 08-11-20, 15:19, Dmitry Osipenko wrote:
> >>> I took a detailed look at the GENPD and tried to implement it. Here is
> >>> what was found:
> >>>
> >>> 1. GENPD framework doesn't aggregate performance requests from the
> >>> attached devices. This means that if deviceA requests performance state
> >>> 10 and then deviceB requests state 3, then framework will set domain's
> >>> state to 3 instead of 10.
> >>
> >> It does. Look at _genpd_reeval_performance_state().
> >>
> > 
> > Thanks, I probably had a bug in the quick prototype and then overlooked
> > that function.
> > 
> 
> If a non-hardware device-tree node is okay to have for the domain, then
> I can try again.
> 
> What I also haven't mentioned is that GENPD adds some extra complexity
> to some drivers (3d, video decoder) because we will need to handle both
> new GENPD and legacy Tegra specific pre-genpd era domains.
> 
> I'm also not exactly sure how the topology of domains should look like
> because Tegra has a power-controller (PMC) which manages power rail of a
> few hardware units. Perhaps it should be
> 
>   device -> PMC domain -> CORE domain
> 
> but not exactly sure for now.

I am also confused on if it should be a domain or regulator, but that
is for Ulf to tell :)

-- 
viresh

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-09  5:10                 ` Viresh Kumar
@ 2020-11-09  5:19                   ` Dmitry Osipenko
  2020-11-09  5:35                     ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-09  5:19 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Frank Lee, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

09.11.2020 08:10, Viresh Kumar пишет:
> On 09-11-20, 08:08, Dmitry Osipenko wrote:
>> 09.11.2020 08:00, Viresh Kumar пишет:
>>> On 06-11-20, 21:41, Frank Lee wrote:
>>>> On Fri, Nov 6, 2020 at 9:18 PM Dmitry Osipenko <digetx@gmail.com> wrote:
>>>>>
>>>>> 06.11.2020 09:15, Viresh Kumar пишет:
>>>>>> Setting regulators for count as 0 doesn't sound good to me.
>>>>>>
>>>>>> But, I understand that you don't want to have that if (have_regulator)
>>>>>> check, and it is a fair request. What I will instead do is, allow all
>>>>>> dev_pm_opp_put*() API to start accepting a NULL pointer for the OPP
>>>>>> table and fail silently. And so you won't be required to have this
>>>>>> unwanted check. But you will be required to save the pointer returned
>>>>>> back by dev_pm_opp_set_regulators(), which is the right thing to do
>>>>>> anyways.
>>>>>
>>>>> Perhaps even a better variant could be to add a devm versions of the OPP
>>>>> API functions, then drivers won't need to care about storing the
>>>>> opp_table pointer if it's unused by drivers.
>>>>
>>>> I think so. The consumer may not be so concerned about the status of
>>>> these OPP tables.
>>>> If the driver needs to manage the release, it needs to add a pointer
>>>> to their driver global structure.
>>>>
>>>> Maybe it's worth having these devm interfaces for opp.
>>>
>>> Sure if there are enough users of this, I am all for it. I was fine
>>> with the patches you sent, just that there were not a lot of users of
>>> it and so I pushed them back. If we find that we have more users of it
>>> now, we can surely get that back.
>>>
>>
>> There was already attempt to add the devm? Could you please give me a
>> link to the patches?
>>
>> I already prepared a patch which adds the devm helpers. It helps to keep
>> code cleaner and readable.
> 
> https://lore.kernel.org/lkml/20201012135517.19468-1-frank@allwinnertech.com/
> 

Thanks, I made it in a different way by simply adding helpers to the
pm_opp.h which use devm_add_action_or_reset(). This doesn't require to
add new kernel symbols.

static inline int devm_pm_opp_of_add_table(struct device *dev)
{
	int err;

	err = dev_pm_opp_of_add_table(dev);
	if (err)
		return err;

	err = devm_add_action_or_reset(dev, (void*)dev_pm_opp_remove_table,
				       dev);
	if (err)
		return err;

	return 0;
}

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-09  5:19                   ` Dmitry Osipenko
@ 2020-11-09  5:35                     ` Viresh Kumar
  2020-11-09  5:44                       ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-09  5:35 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Frank Lee, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On 09-11-20, 08:19, Dmitry Osipenko wrote:
> Thanks, I made it in a different way by simply adding helpers to the
> pm_opp.h which use devm_add_action_or_reset(). This doesn't require to
> add new kernel symbols.

I will prefer to add it in core.c itself, and yes
devm_add_action_or_reset() looks better. But I am still not sure for
which helpers do we need the devm_*() variants, as this is only useful
for non-CPU devices. But if we have users that we can add right now,
why not.

> static inline int devm_pm_opp_of_add_table(struct device *dev)
> {
> 	int err;
> 
> 	err = dev_pm_opp_of_add_table(dev);
> 	if (err)
> 		return err;
> 
> 	err = devm_add_action_or_reset(dev, (void*)dev_pm_opp_remove_table,
> 				       dev);
> 	if (err)
> 		return err;
> 
> 	return 0;
> }

-- 
viresh

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-09  5:35                     ` Viresh Kumar
@ 2020-11-09  5:44                       ` Dmitry Osipenko
  2020-11-09  5:53                         ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-09  5:44 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Frank Lee, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

09.11.2020 08:35, Viresh Kumar пишет:
> On 09-11-20, 08:19, Dmitry Osipenko wrote:
>> Thanks, I made it in a different way by simply adding helpers to the
>> pm_opp.h which use devm_add_action_or_reset(). This doesn't require to
>> add new kernel symbols.
> 
> I will prefer to add it in core.c itself, and yes
> devm_add_action_or_reset() looks better. But I am still not sure for
> which helpers do we need the devm_*() variants, as this is only useful
> for non-CPU devices. But if we have users that we can add right now,
> why not.

All current non-CPU drivers (devfreq, mmc, memory, etc) can benefit from it.

For Tegra drivers we need these variants:

devm_pm_opp_set_supported_hw()
devm_pm_opp_set_regulators() [if we won't use GENPD]
devm_pm_opp_set_clkname()
devm_pm_opp_of_add_table()

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-09  5:44                       ` Dmitry Osipenko
@ 2020-11-09  5:53                         ` Viresh Kumar
  2020-11-09 11:20                           ` Frank Lee
  0 siblings, 1 reply; 108+ messages in thread
From: Viresh Kumar @ 2020-11-09  5:53 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Frank Lee, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On 09-11-20, 08:44, Dmitry Osipenko wrote:
> 09.11.2020 08:35, Viresh Kumar пишет:
> > On 09-11-20, 08:19, Dmitry Osipenko wrote:
> >> Thanks, I made it in a different way by simply adding helpers to the
> >> pm_opp.h which use devm_add_action_or_reset(). This doesn't require to
> >> add new kernel symbols.
> > 
> > I will prefer to add it in core.c itself, and yes
> > devm_add_action_or_reset() looks better. But I am still not sure for
> > which helpers do we need the devm_*() variants, as this is only useful
> > for non-CPU devices. But if we have users that we can add right now,
> > why not.
> 
> All current non-CPU drivers (devfreq, mmc, memory, etc) can benefit from it.
> 
> For Tegra drivers we need these variants:
> 
> devm_pm_opp_set_supported_hw()
> devm_pm_opp_set_regulators() [if we won't use GENPD]
> devm_pm_opp_set_clkname()
> devm_pm_opp_of_add_table()

I tried to look earlier for the stuff already merged in and didn't
find a lot of stuff where the devm_* could be used, maybe I missed
some of it.

Frank, would you like to refresh your series based on suggestions from
Dmitry and make other drivers adapt to the new APIs ?

-- 
viresh

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-09  5:53                         ` Viresh Kumar
@ 2020-11-09 11:20                           ` Frank Lee
  2020-12-22  8:54                             ` Viresh Kumar
  0 siblings, 1 reply; 108+ messages in thread
From: Frank Lee @ 2020-11-09 11:20 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML, linux-usb,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On Mon, Nov 9, 2020 at 1:53 PM Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> On 09-11-20, 08:44, Dmitry Osipenko wrote:
> > 09.11.2020 08:35, Viresh Kumar пишет:
> > > On 09-11-20, 08:19, Dmitry Osipenko wrote:
> > >> Thanks, I made it in a different way by simply adding helpers to the
> > >> pm_opp.h which use devm_add_action_or_reset(). This doesn't require to
> > >> add new kernel symbols.
> > >
> > > I will prefer to add it in core.c itself, and yes
> > > devm_add_action_or_reset() looks better. But I am still not sure for
> > > which helpers do we need the devm_*() variants, as this is only useful
> > > for non-CPU devices. But if we have users that we can add right now,
> > > why not.
> >
> > All current non-CPU drivers (devfreq, mmc, memory, etc) can benefit from it.
> >
> > For Tegra drivers we need these variants:
> >
> > devm_pm_opp_set_supported_hw()
> > devm_pm_opp_set_regulators() [if we won't use GENPD]
> > devm_pm_opp_set_clkname()
> > devm_pm_opp_of_add_table()
>
> I tried to look earlier for the stuff already merged in and didn't
> find a lot of stuff where the devm_* could be used, maybe I missed
> some of it.
>
> Frank, would you like to refresh your series based on suggestions from
> Dmitry and make other drivers adapt to the new APIs ?

I am glad to do this.:)

Yangtao

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

* Re: [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties
  2020-11-04 23:43 ` [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties Dmitry Osipenko
@ 2020-11-09 18:57   ` Rob Herring
  2020-11-11 11:45   ` Ulf Hansson
  1 sibling, 0 replies; 108+ messages in thread
From: Rob Herring @ 2020-11-09 18:57 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: devel, Ulf Hansson, Greg Kroah-Hartman, Mark Brown,
	Krzysztof Kozlowski, Adrian Hunter, devicetree, linux-kernel,
	linux-usb, Alan Stern, linux-pwm, linux-samsung-soc, Peter Geis,
	linux-mmc, Mauro Carvalho Chehab, dri-devel, linux-tegra,
	linux-media, Jonathan Hunter, Marek Szyprowski, Peter Chen,
	Rob Herring, Nicolas Chauvet, Thierry Reding, Lee Jones,
	Liam Girdwood, Uwe Kleine-König

On Thu, 05 Nov 2020 02:43:58 +0300, Dmitry Osipenko wrote:
> Document new DVFS OPP table and voltage regulator properties of the
> Host1x bus and devices sitting on the bus.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../display/tegra/nvidia,tegra20-host1x.txt   | 56 +++++++++++++++++++
>  1 file changed, 56 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v1 02/30] dt-bindings: mmc: tegra: Document OPP and voltage regulator properties
  2020-11-04 23:43 ` [PATCH v1 02/30] dt-bindings: mmc: tegra: " Dmitry Osipenko
@ 2020-11-09 18:58   ` Rob Herring
  0 siblings, 0 replies; 108+ messages in thread
From: Rob Herring @ 2020-11-09 18:58 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: linux-usb, Mauro Carvalho Chehab, Rob Herring, linux-tegra,
	linux-mmc, Nicolas Chauvet, Mark Brown, Liam Girdwood,
	linux-kernel, Peter Chen, Adrian Hunter, Uwe Kleine-König,
	dri-devel, Krzysztof Kozlowski, Greg Kroah-Hartman,
	Marek Szyprowski, linux-pwm, linux-samsung-soc, Thierry Reding,
	devel, Lee Jones, devicetree, Ulf Hansson, Peter Geis,
	Jonathan Hunter, Alan Stern, linux-media

On Thu, 05 Nov 2020 02:43:59 +0300, Dmitry Osipenko wrote:
> Document new DVFS OPP table and voltage regulator properties of the
> SDHCI controller.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v1 03/30] dt-bindings: pwm: tegra: Document OPP and voltage regulator properties
  2020-11-04 23:44 ` [PATCH v1 03/30] dt-bindings: pwm: " Dmitry Osipenko
@ 2020-11-09 19:00   ` Rob Herring
  0 siblings, 0 replies; 108+ messages in thread
From: Rob Herring @ 2020-11-09 19:00 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Lee Jones, linux-tegra, Liam Girdwood, Nicolas Chauvet,
	linux-mmc, Mark Brown, devel, linux-pwm, linux-samsung-soc,
	Peter Chen, Adrian Hunter, Marek Szyprowski, Greg Kroah-Hartman,
	Jonathan Hunter, Rob Herring, Peter Geis, Krzysztof Kozlowski,
	Ulf Hansson, devicetree, Alan Stern, dri-devel,
	Mauro Carvalho Chehab, Uwe Kleine-König, linux-media,
	linux-kernel, Thierry Reding, linux-usb

On Thu, 05 Nov 2020 02:44:00 +0300, Dmitry Osipenko wrote:
> Document new DVFS OPP table and voltage regulator properties of the
> PWM controller.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../devicetree/bindings/pwm/nvidia,tegra20-pwm.txt  | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v1 04/30] media: dt: bindings: tegra-vde: Document OPP and voltage regulator properties
  2020-11-04 23:44 ` [PATCH v1 04/30] media: dt: bindings: tegra-vde: " Dmitry Osipenko
@ 2020-11-09 19:01   ` Rob Herring
  0 siblings, 0 replies; 108+ messages in thread
From: Rob Herring @ 2020-11-09 19:01 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Rob Herring, Alan Stern, Mauro Carvalho Chehab, Mark Brown,
	Krzysztof Kozlowski, dri-devel, Marek Szyprowski, linux-usb,
	devel, linux-media, linux-pwm, Peter Geis, linux-tegra,
	linux-kernel, linux-mmc, Liam Girdwood, Lee Jones,
	Greg Kroah-Hartman, Ulf Hansson, Nicolas Chauvet, Adrian Hunter,
	linux-samsung-soc, Jonathan Hunter, Thierry Reding, devicetree,
	Uwe Kleine-König, Peter Chen

On Thu, 05 Nov 2020 02:44:01 +0300, Dmitry Osipenko wrote:
> Document new DVFS OPP table and voltage regulator properties of the
> video decoder engine.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../devicetree/bindings/media/nvidia,tegra-vde.txt   | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v1 05/30] dt-binding: usb: ci-hdrc-usb2: Document OPP and voltage regulator properties
  2020-11-04 23:44 ` [PATCH v1 05/30] dt-binding: usb: ci-hdrc-usb2: " Dmitry Osipenko
@ 2020-11-09 19:01   ` Rob Herring
  0 siblings, 0 replies; 108+ messages in thread
From: Rob Herring @ 2020-11-09 19:01 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Mauro Carvalho Chehab, linux-tegra, Nicolas Chauvet, Peter Geis,
	Krzysztof Kozlowski, Rob Herring, linux-kernel, linux-media,
	Lee Jones, devicetree, Greg Kroah-Hartman, Adrian Hunter,
	Peter Chen, linux-usb, devel, linux-pwm, Thierry Reding,
	Ulf Hansson, Alan Stern, Liam Girdwood, Mark Brown, dri-devel,
	Jonathan Hunter, Marek Szyprowski, linux-samsung-soc,
	Uwe Kleine-König, linux-mmc

On Thu, 05 Nov 2020 02:44:02 +0300, Dmitry Osipenko wrote:
> Document new OPP table and NVIDIA Tegra-specific voltage regulator
> properties.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt | 4 ++++
>  1 file changed, 4 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v1 06/30] dt-bindings: usb: tegra-ehci: Document OPP and voltage regulator properties
  2020-11-04 23:44 ` [PATCH v1 06/30] dt-bindings: usb: tegra-ehci: " Dmitry Osipenko
@ 2020-11-09 19:01   ` Rob Herring
  0 siblings, 0 replies; 108+ messages in thread
From: Rob Herring @ 2020-11-09 19:01 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Mark Brown, Greg Kroah-Hartman, linux-usb, dri-devel, Peter Chen,
	linux-kernel, Uwe Kleine-König, devicetree, Ulf Hansson,
	linux-tegra, Peter Geis, Rob Herring, linux-pwm, linux-mmc,
	Marek Szyprowski, Liam Girdwood, Alan Stern, Adrian Hunter,
	Jonathan Hunter, linux-samsung-soc, Thierry Reding,
	Mauro Carvalho Chehab, Nicolas Chauvet, devel, Lee Jones,
	linux-media, Krzysztof Kozlowski

On Thu, 05 Nov 2020 02:44:03 +0300, Dmitry Osipenko wrote:
> Document new DVFS OPP table and voltage regulator properties of the
> Tegra EHCI controller.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-04 23:44 ` [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling Dmitry Osipenko
@ 2020-11-10 20:29   ` Thierry Reding
  2020-11-10 20:32     ` Mark Brown
                       ` (3 more replies)
  0 siblings, 4 replies; 108+ messages in thread
From: Thierry Reding @ 2020-11-10 20:29 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 9116 bytes --]

On Thu, Nov 05, 2020 at 02:44:08AM +0300, Dmitry Osipenko wrote:
> Add OPP and SoC core voltage scaling support to the display controller
> driver. This is required for enabling system-wide DVFS on older Tegra
> SoCs.
> 
> Tested-by: Peter Geis <pgwipeout@gmail.com>
> Tested-by: Nicolas Chauvet <kwizart@gmail.com>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/gpu/drm/tegra/Kconfig |   1 +
>  drivers/gpu/drm/tegra/dc.c    | 138 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/tegra/dc.h    |   5 ++
>  3 files changed, 143 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
> index 1650a448eabd..9eec4c3fbd3b 100644
> --- a/drivers/gpu/drm/tegra/Kconfig
> +++ b/drivers/gpu/drm/tegra/Kconfig
> @@ -12,6 +12,7 @@ config DRM_TEGRA
>  	select INTERCONNECT
>  	select IOMMU_IOVA
>  	select CEC_CORE if CEC_NOTIFIER
> +	select PM_OPP
>  	help
>  	  Choose this option if you have an NVIDIA Tegra SoC.
>  
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index fd7c8828652d..babcb66a335b 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -11,9 +11,13 @@
>  #include <linux/interconnect.h>
>  #include <linux/module.h>
>  #include <linux/of_device.h>
> +#include <linux/pm_opp.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/regulator/consumer.h>
>  #include <linux/reset.h>
>  
> +#include <soc/tegra/common.h>
> +#include <soc/tegra/fuse.h>
>  #include <soc/tegra/pmc.h>
>  
>  #include <drm/drm_atomic.h>
> @@ -1699,6 +1703,55 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
>  	return 0;
>  }
>  
> +static void tegra_dc_update_voltage_state(struct tegra_dc *dc,
> +					  struct tegra_dc_state *state)
> +{
> +	struct dev_pm_opp *opp;
> +	unsigned long rate;
> +	int err, min_uV;
> +
> +	/* OPP usage is optional */
> +	if (!dc->opp_table)
> +		return;
> +
> +	/* calculate actual pixel clock rate which depends on internal divider */
> +	rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);
> +
> +	/* find suitable OPP for the rate */
> +	opp = dev_pm_opp_find_freq_ceil(dc->dev, &rate);
> +
> +	if (opp == ERR_PTR(-ERANGE))
> +		opp = dev_pm_opp_find_freq_floor(dc->dev, &rate);
> +
> +	if (IS_ERR(opp)) {
> +		dev_err(dc->dev, "failed to find OPP for %lu Hz: %ld\n",
> +			rate, PTR_ERR(opp));
> +		return;
> +	}
> +
> +	min_uV = dev_pm_opp_get_voltage(opp);
> +	dev_pm_opp_put(opp);
> +
> +	/*
> +	 * Voltage scaling is optional and trying to set voltage for a dummy
> +	 * regulator will error out.
> +	 */
> +	if (!device_property_present(dc->dev, "core-supply"))
> +		return;

This is a potentially heavy operation, so I think we should avoid that
here. How about you use devm_regulator_get_optional() in ->probe()? That
returns -ENODEV if no regulator was specified, in which case you can set
dc->core_reg = NULL and use that as the condition here.

> +
> +	/*
> +	 * Note that the minimum core voltage depends on the pixel clock
> +	 * rate (which depends on internal clock divider of CRTC) and not on
> +	 * the rate of the display controller clock. This is why we're not
> +	 * using dev_pm_opp_set_rate() API and instead are managing the
> +	 * voltage by ourselves.
> +	 */
> +	err = regulator_set_voltage(dc->core_reg, min_uV, INT_MAX);
> +	if (err)
> +		dev_err(dc->dev, "failed to set CORE voltage to %duV: %d\n",
> +			min_uV, err);
> +}

Also, I'd prefer if the flow here was more linear, such as:

	if (dc->core_reg) {
		err = regulator_set_voltage(...);
		...
	}

> +
>  static void tegra_dc_commit_state(struct tegra_dc *dc,
>  				  struct tegra_dc_state *state)
>  {
> @@ -1738,6 +1791,8 @@ static void tegra_dc_commit_state(struct tegra_dc *dc,
>  	if (err < 0)
>  		dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
>  			dc->clk, state->pclk, err);
> +
> +	tegra_dc_update_voltage_state(dc, state);
>  }
>  
>  static void tegra_dc_stop(struct tegra_dc *dc)
> @@ -2521,6 +2576,7 @@ static int tegra_dc_runtime_suspend(struct host1x_client *client)
>  
>  	clk_disable_unprepare(dc->clk);
>  	pm_runtime_put_sync(dev);
> +	regulator_disable(dc->core_reg);
>  
>  	return 0;
>  }
> @@ -2531,10 +2587,16 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
>  	struct device *dev = client->dev;
>  	int err;
>  
> +	err = regulator_enable(dc->core_reg);
> +	if (err < 0) {
> +		dev_err(dev, "failed to enable CORE regulator: %d\n", err);
> +		return err;
> +	}
> +
>  	err = pm_runtime_get_sync(dev);
>  	if (err < 0) {
>  		dev_err(dev, "failed to get runtime PM: %d\n", err);
> -		return err;
> +		goto disable_regulator;
>  	}
>  
>  	if (dc->soc->has_powergate) {
> @@ -2564,6 +2626,9 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
>  	clk_disable_unprepare(dc->clk);
>  put_rpm:
>  	pm_runtime_put_sync(dev);
> +disable_regulator:
> +	regulator_disable(dc->core_reg);
> +
>  	return err;
>  }
>  
> @@ -2879,6 +2944,72 @@ static int tegra_dc_couple(struct tegra_dc *dc)
>  	return 0;
>  }
>  
> +static void tegra_dc_deinit_opp_table(void *data)
> +{
> +	struct tegra_dc *dc = data;
> +
> +	dev_pm_opp_of_remove_table(dc->dev);
> +	dev_pm_opp_put_supported_hw(dc->opp_table);
> +	dev_pm_opp_put_regulators(dc->opp_table);
> +}
> +
> +static int devm_tegra_dc_opp_table_init(struct tegra_dc *dc)
> +{
> +	struct opp_table *hw_opp_table;
> +	u32 hw_version;
> +	int err;
> +
> +	/* voltage scaling is optional */
> +	dc->core_reg = devm_regulator_get(dc->dev, "core");
> +	if (IS_ERR(dc->core_reg))
> +		return dev_err_probe(dc->dev, PTR_ERR(dc->core_reg),
> +				     "failed to get CORE regulator\n");
> +
> +	/* legacy device-trees don't have OPP table */
> +	if (!device_property_present(dc->dev, "operating-points-v2"))
> +		return 0;

"Legacy" is a bit confusing here. For one, no device trees currently
have these tables and secondly, for newer SoCs we may never need them.

> +
> +	dc->opp_table = dev_pm_opp_get_opp_table(dc->dev);
> +	if (IS_ERR(dc->opp_table))
> +		return dev_err_probe(dc->dev, PTR_ERR(dc->opp_table),
> +				     "failed to prepare OPP table\n");
> +
> +	if (of_machine_is_compatible("nvidia,tegra20"))
> +		hw_version = BIT(tegra_sku_info.soc_process_id);
> +	else
> +		hw_version = BIT(tegra_sku_info.soc_speedo_id);
> +
> +	hw_opp_table = dev_pm_opp_set_supported_hw(dc->dev, &hw_version, 1);
> +	err = PTR_ERR_OR_ZERO(hw_opp_table);

What's the point of this? A more canonical version would be:

	if (IS_ERR(hw_opp_table)) {
		err = PTR_ERR(hw_opp_table);
		dev_err(dc->dev, ...);
		goto put_table;
	}

That uses the same number of lines but is much easier to read, in my
opinion, because it is the canonical form.

> +	if (err) {
> +		dev_err(dc->dev, "failed to set supported HW: %d\n", err);
> +		goto put_table;
> +	}
> +
> +	err = dev_pm_opp_of_add_table(dc->dev);
> +	if (err) {
> +		dev_err(dc->dev, "failed to add OPP table: %d\n", err);
> +		goto put_hw;
> +	}
> +
> +	err = devm_add_action(dc->dev, tegra_dc_deinit_opp_table, dc);
> +	if (err)
> +		goto remove_table;

Do these functions return positive values? If not, I'd prefer if this
check was more explicit (i.e. err < 0) for consistency with the rest of
this code.

> +
> +	dev_info(dc->dev, "OPP HW ver. 0x%x\n", hw_version);
> +
> +	return 0;
> +
> +remove_table:
> +	dev_pm_opp_of_remove_table(dc->dev);
> +put_hw:
> +	dev_pm_opp_put_supported_hw(dc->opp_table);
> +put_table:
> +	dev_pm_opp_put_opp_table(dc->opp_table);
> +
> +	return err;
> +}
> +
>  static int tegra_dc_probe(struct platform_device *pdev)
>  {
>  	struct tegra_dc *dc;
> @@ -2937,6 +3068,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
>  		tegra_powergate_power_off(dc->powergate);
>  	}
>  
> +	err = devm_tegra_dc_opp_table_init(dc);
> +	if (err < 0)
> +		return err;
> +
>  	dc->regs = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(dc->regs))
>  		return PTR_ERR(dc->regs);
> @@ -3007,6 +3142,7 @@ struct platform_driver tegra_dc_driver = {
>  	.driver = {
>  		.name = "tegra-dc",
>  		.of_match_table = tegra_dc_of_match,
> +		.sync_state = tegra_soc_device_sync_state,
>  	},
>  	.probe = tegra_dc_probe,
>  	.remove = tegra_dc_remove,
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index ba4ed35139fb..fd774fc5c2e4 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -13,6 +13,8 @@
>  
>  #include "drm.h"
>  
> +struct opp_table;
> +struct regulator;
>  struct tegra_output;
>  
>  #define TEGRA_DC_LEGACY_PLANES_NUM	6
> @@ -107,6 +109,9 @@ struct tegra_dc {
>  	struct drm_info_list *debugfs_files;
>  
>  	const struct tegra_dc_soc_info *soc;
> +
> +	struct opp_table *opp_table;
> +	struct regulator *core_reg;

We typically use a _supply suffix on regulators to avoid confusing this
with "register".

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-10 20:29   ` Thierry Reding
@ 2020-11-10 20:32     ` Mark Brown
  2020-11-10 21:23       ` Dmitry Osipenko
  2020-11-10 21:17     ` Dmitry Osipenko
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-11-10 20:32 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Dmitry Osipenko, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 791 bytes --]

On Tue, Nov 10, 2020 at 09:29:45PM +0100, Thierry Reding wrote:
> On Thu, Nov 05, 2020 at 02:44:08AM +0300, Dmitry Osipenko wrote:

> > +	/*
> > +	 * Voltage scaling is optional and trying to set voltage for a dummy
> > +	 * regulator will error out.
> > +	 */
> > +	if (!device_property_present(dc->dev, "core-supply"))
> > +		return;

> This is a potentially heavy operation, so I think we should avoid that
> here. How about you use devm_regulator_get_optional() in ->probe()? That
> returns -ENODEV if no regulator was specified, in which case you can set
> dc->core_reg = NULL and use that as the condition here.

Or enumerate the configurable voltages after getting the regulator and
handle that appropriately which would be more robust in case there's
missing or unusual constraints.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 07/30] soc/tegra: Add sync state API
  2020-11-04 23:44 ` [PATCH v1 07/30] soc/tegra: Add sync state API Dmitry Osipenko
@ 2020-11-10 20:47   ` Thierry Reding
  2020-11-10 21:22     ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Thierry Reding @ 2020-11-10 20:47 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 7234 bytes --]

On Thu, Nov 05, 2020 at 02:44:04AM +0300, Dmitry Osipenko wrote:
> Introduce sync state API that will be used by Tegra device drivers. This
> new API is primarily needed for syncing state of SoC devices that are left
> ON after bootloader or permanently enabled. All these devices belong to a
> shared CORE voltage domain, and thus, we needed to bring all the devices
> into expected state before the voltage scaling could be performed.
> 
> All drivers of DVFS-critical devices shall sync theirs the state before
> Tegra's voltage regulator coupler will be allowed to perform a system-wide
> voltage scaling.
> 
> Tested-by: Peter Geis <pgwipeout@gmail.com>
> Tested-by: Nicolas Chauvet <kwizart@gmail.com>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/soc/tegra/common.c | 152 ++++++++++++++++++++++++++++++++++++-
>  include/soc/tegra/common.h |  22 ++++++
>  2 files changed, 170 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
> index 3dc54f59cafe..f9b2b6f57887 100644
> --- a/drivers/soc/tegra/common.c
> +++ b/drivers/soc/tegra/common.c
> @@ -3,13 +3,52 @@
>   * Copyright (C) 2014 NVIDIA CORPORATION.  All rights reserved.
>   */
>  
> +#define dev_fmt(fmt)	"%s: " fmt, __func__
> +#define pr_fmt(fmt)	"%s: " fmt, __func__
> +
> +#include <linux/export.h>
> +#include <linux/init.h>
> +#include <linux/mutex.h>
>  #include <linux/of.h>
> +#include <linux/of_device.h>
>  
>  #include <soc/tegra/common.h>
>  
> +#define terga_soc_for_each_device(__dev) \

tegra_soc_for_each_device

> +	for ((__dev) = tegra_soc_devices; (__dev) && (__dev)->compatible; \
> +	     (__dev)++)
> +
> +struct tegra_soc_device {
> +	const char *compatible;
> +	const bool dvfs_critical;
> +	unsigned int sync_count;
> +};
> +
> +static DEFINE_MUTEX(tegra_soc_lock);
> +static struct tegra_soc_device *tegra_soc_devices;
> +
> +/*
> + * DVFS-critical devices are either active at a boot time or permanently
> + * active, like EMC for example.  System-wide DVFS should be deferred until
> + * drivers of the critical devices synced theirs state.
> + */
> +
> +static struct tegra_soc_device tegra20_soc_devices[] = {
> +	{ .compatible = "nvidia,tegra20-dc", .dvfs_critical = true, },
> +	{ .compatible = "nvidia,tegra20-emc", .dvfs_critical = true, },
> +	{ }
> +};
> +
> +static struct tegra_soc_device tegra30_soc_devices[] = {
> +	{ .compatible = "nvidia,tegra30-dc", .dvfs_critical = true, },
> +	{ .compatible = "nvidia,tegra30-emc", .dvfs_critical = true, },
> +	{ .compatible = "nvidia,tegra30-pwm", .dvfs_critical = true, },
> +	{ }
> +};
> +
>  static const struct of_device_id tegra_machine_match[] = {
> -	{ .compatible = "nvidia,tegra20", },
> -	{ .compatible = "nvidia,tegra30", },
> +	{ .compatible = "nvidia,tegra20", .data = tegra20_soc_devices, },
> +	{ .compatible = "nvidia,tegra30", .data = tegra30_soc_devices, },
>  	{ .compatible = "nvidia,tegra114", },
>  	{ .compatible = "nvidia,tegra124", },
>  	{ .compatible = "nvidia,tegra132", },
> @@ -17,7 +56,7 @@ static const struct of_device_id tegra_machine_match[] = {
>  	{ }
>  };
>  
> -bool soc_is_tegra(void)
> +static const struct of_device_id *tegra_soc_of_match(void)
>  {
>  	const struct of_device_id *match;
>  	struct device_node *root;
> @@ -29,5 +68,110 @@ bool soc_is_tegra(void)
>  	match = of_match_node(tegra_machine_match, root);
>  	of_node_put(root);
>  
> -	return match != NULL;
> +	return match;
> +}
> +
> +bool soc_is_tegra(void)
> +{
> +	return tegra_soc_of_match() != NULL;
> +}
> +
> +void tegra_soc_device_sync_state(struct device *dev)
> +{
> +	struct tegra_soc_device *soc_dev;
> +
> +	mutex_lock(&tegra_soc_lock);
> +	terga_soc_for_each_device(soc_dev) {

tegra_soc_for_each_device

> +		if (!of_device_is_compatible(dev->of_node, soc_dev->compatible))
> +			continue;
> +
> +		if (!soc_dev->sync_count) {
> +			dev_err(dev, "already synced\n");
> +			break;
> +		}
> +
> +		/*
> +		 * All DVFS-capable devices should have the CORE regulator
> +		 * phandle.  Older device-trees don't have it, hence state
> +		 * won't be synced for the older DTBs, allowing them to work
> +		 * properly.
> +		 */
> +		if (soc_dev->dvfs_critical &&
> +		    !device_property_present(dev, "core-supply")) {
> +			dev_dbg(dev, "doesn't have core supply\n");
> +			break;
> +		}
> +
> +		soc_dev->sync_count--;
> +		dev_dbg(dev, "sync_count=%u\n", soc_dev->sync_count);
> +		break;
> +	}
> +	mutex_unlock(&tegra_soc_lock);
> +}
> +EXPORT_SYMBOL_GPL(tegra_soc_device_sync_state);
> +
> +bool tegra_soc_dvfs_state_synced(void)
> +{
> +	struct tegra_soc_device *soc_dev;
> +	bool synced_state = true;
> +
> +	/*
> +	 * CORE voltage scaling is limited until drivers of the critical
> +	 * devices synced theirs state.
> +	 */
> +	mutex_lock(&tegra_soc_lock);
> +	terga_soc_for_each_device(soc_dev) {

tegra_soc_for_each_device

I wonder if you copy/pasted this or if you got really lucky to mistype
this all three times.

> +		if (!soc_dev->sync_count || !soc_dev->dvfs_critical)
> +			continue;
> +
> +		pr_debug_ratelimited("%s: sync_count=%u\n",
> +				     soc_dev->compatible, soc_dev->sync_count);
> +
> +		synced_state = false;
> +		break;
> +	}
> +	mutex_unlock(&tegra_soc_lock);
> +
> +	return synced_state;
> +}
> +
> +static int __init tegra_soc_devices_init(void)
> +{
> +	struct device_node *np, *prev_np = NULL;
> +	struct tegra_soc_device *soc_dev;
> +	const struct of_device_id *match;
> +
> +	if (!soc_is_tegra())
> +		return 0;
> +
> +	match = tegra_soc_of_match();
> +	tegra_soc_devices = (void *)match->data;
> +
> +	/*
> +	 * If device node is disabled in a device-tree, then we shouldn't
> +	 * care about this device. Even if device is active during boot,
> +	 * its clock will be disabled by CCF as unused.
> +	 */
> +	terga_soc_for_each_device(soc_dev) {
> +		do {
> +			/*
> +			 * Devices like display controller have multiple
> +			 * instances with the same compatible. Hence we need
> +			 * to walk up the whole tree in order to account those
> +			 * multiple instances.
> +			 */
> +			np = of_find_compatible_node(prev_np, NULL,
> +						     soc_dev->compatible);
> +			of_node_put(prev_np);
> +			prev_np = np;
> +
> +			if (of_device_is_available(np)) {
> +				pr_debug("added %s\n", soc_dev->compatible);
> +				soc_dev->sync_count++;
> +			}
> +		} while (np);

Maybe use for_each_compatible_node() for that inside loop?

> +	}
> +
> +	return 0;
>  }
> +postcore_initcall_sync(tegra_soc_devices_init);

This is unfortunate. I recall having this discussion multiple times and
one idea that has been floating around for a while was to let a driver
bind against the top-level "bus" node. That has the advantage that it
both anchors the code somewhere, so we don't have to play this game of
checking for the SoC with soc_is_tegra(), and it properly orders this
with respect to the child devices, so we wouldn't have to make this a
postcore_initcall.

Might be worth looking at that again, but for now this seems okay.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 18/30] pwm: tegra: Support OPP and core voltage scaling
  2020-11-04 23:44 ` [PATCH v1 18/30] pwm: tegra: " Dmitry Osipenko
@ 2020-11-10 20:50   ` Thierry Reding
  2020-11-10 21:17     ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Thierry Reding @ 2020-11-10 20:50 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 1723 bytes --]

On Thu, Nov 05, 2020 at 02:44:15AM +0300, Dmitry Osipenko wrote:
[...]
> +static void tegra_pwm_deinit_opp_table(void *data)
> +{
> +	struct device *dev = data;
> +	struct opp_table *opp_table;
> +
> +	opp_table = dev_pm_opp_get_opp_table(dev);
> +	dev_pm_opp_of_remove_table(dev);
> +	dev_pm_opp_put_regulators(opp_table);
> +	dev_pm_opp_put_opp_table(opp_table);
> +}
> +
> +static int devm_tegra_pwm_init_opp_table(struct device *dev)
> +{
> +	struct opp_table *opp_table;
> +	const char *rname = "core";
> +	int err;
> +
> +	/* voltage scaling is optional */
> +	if (device_property_present(dev, "core-supply"))
> +		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
> +	else
> +		opp_table = dev_pm_opp_get_opp_table(dev);
> +
> +	if (IS_ERR(opp_table))
> +		return dev_err_probe(dev, PTR_ERR(opp_table),
> +				     "failed to prepare OPP table\n");
> +
> +	/*
> +	 * OPP table presence is optional and we want the set_rate() of OPP
> +	 * API to work similarly to clk_set_rate() if table is missing in a
> +	 * device-tree.  The add_table() errors out if OPP is missing in DT.
> +	 */
> +	if (device_property_present(dev, "operating-points-v2")) {
> +		err = dev_pm_opp_of_add_table(dev);
> +		if (err) {
> +			dev_err(dev, "failed to add OPP table: %d\n", err);
> +			goto put_table;
> +		}
> +	}
> +
> +	err = devm_add_action(dev, tegra_pwm_deinit_opp_table, dev);
> +	if (err)
> +		goto remove_table;
> +
> +	return 0;
> +
> +remove_table:
> +	dev_pm_opp_of_remove_table(dev);
> +put_table:
> +	dev_pm_opp_put_regulators(opp_table);
> +
> +	return err;
> +}

These two functions seem to be heavily boilerplate across all these
drivers. Have you considered splitting these out into separate helpers?

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 18/30] pwm: tegra: Support OPP and core voltage scaling
  2020-11-10 20:50   ` Thierry Reding
@ 2020-11-10 21:17     ` Dmitry Osipenko
  0 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-10 21:17 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

10.11.2020 23:50, Thierry Reding пишет:
> On Thu, Nov 05, 2020 at 02:44:15AM +0300, Dmitry Osipenko wrote:
> [...]
>> +static void tegra_pwm_deinit_opp_table(void *data)
>> +{
>> +	struct device *dev = data;
>> +	struct opp_table *opp_table;
>> +
>> +	opp_table = dev_pm_opp_get_opp_table(dev);
>> +	dev_pm_opp_of_remove_table(dev);
>> +	dev_pm_opp_put_regulators(opp_table);
>> +	dev_pm_opp_put_opp_table(opp_table);
>> +}
>> +
>> +static int devm_tegra_pwm_init_opp_table(struct device *dev)
>> +{
>> +	struct opp_table *opp_table;
>> +	const char *rname = "core";
>> +	int err;
>> +
>> +	/* voltage scaling is optional */
>> +	if (device_property_present(dev, "core-supply"))
>> +		opp_table = dev_pm_opp_set_regulators(dev, &rname, 1);
>> +	else
>> +		opp_table = dev_pm_opp_get_opp_table(dev);
>> +
>> +	if (IS_ERR(opp_table))
>> +		return dev_err_probe(dev, PTR_ERR(opp_table),
>> +				     "failed to prepare OPP table\n");
>> +
>> +	/*
>> +	 * OPP table presence is optional and we want the set_rate() of OPP
>> +	 * API to work similarly to clk_set_rate() if table is missing in a
>> +	 * device-tree.  The add_table() errors out if OPP is missing in DT.
>> +	 */
>> +	if (device_property_present(dev, "operating-points-v2")) {
>> +		err = dev_pm_opp_of_add_table(dev);
>> +		if (err) {
>> +			dev_err(dev, "failed to add OPP table: %d\n", err);
>> +			goto put_table;
>> +		}
>> +	}
>> +
>> +	err = devm_add_action(dev, tegra_pwm_deinit_opp_table, dev);
>> +	if (err)
>> +		goto remove_table;
>> +
>> +	return 0;
>> +
>> +remove_table:
>> +	dev_pm_opp_of_remove_table(dev);
>> +put_table:
>> +	dev_pm_opp_put_regulators(opp_table);
>> +
>> +	return err;
>> +}
> 
> These two functions seem to be heavily boilerplate across all these
> drivers. Have you considered splitting these out into separate helpers?

The helper is already prepared for v2.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-10 20:29   ` Thierry Reding
  2020-11-10 20:32     ` Mark Brown
@ 2020-11-10 21:17     ` Dmitry Osipenko
  2020-11-10 21:50     ` Dmitry Osipenko
  2020-11-11  9:28     ` Dan Carpenter
  3 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-10 21:17 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

10.11.2020 23:29, Thierry Reding пишет:
>> +
>> +	dc->opp_table = dev_pm_opp_get_opp_table(dc->dev);
>> +	if (IS_ERR(dc->opp_table))
>> +		return dev_err_probe(dc->dev, PTR_ERR(dc->opp_table),
>> +				     "failed to prepare OPP table\n");
>> +
>> +	if (of_machine_is_compatible("nvidia,tegra20"))
>> +		hw_version = BIT(tegra_sku_info.soc_process_id);
>> +	else
>> +		hw_version = BIT(tegra_sku_info.soc_speedo_id);
>> +
>> +	hw_opp_table = dev_pm_opp_set_supported_hw(dc->dev, &hw_version, 1);
>> +	err = PTR_ERR_OR_ZERO(hw_opp_table);
> What's the point of this? A more canonical version would be:
> 
> 	if (IS_ERR(hw_opp_table)) {
> 		err = PTR_ERR(hw_opp_table);
> 		dev_err(dc->dev, ...);
> 		goto put_table;
> 	}
> 
> That uses the same number of lines but is much easier to read, in my
> opinion, because it is the canonical form.
> 

Your variant is much more difficult to read for me :/

I guess the only reason it could be "canonical" is because
PTR_ERR_OR_ZERO was added not so long time ago.

But don't worry, this code will be moved out in a v2 and it won't use
PTR_ERR_OR_ZERO.

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

* Re: [PATCH v1 07/30] soc/tegra: Add sync state API
  2020-11-10 20:47   ` Thierry Reding
@ 2020-11-10 21:22     ` Dmitry Osipenko
  2020-11-10 21:32       ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-10 21:22 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

10.11.2020 23:47, Thierry Reding пишет:
...
> tegra_soc_for_each_device
> 
> I wonder if you copy/pasted this or if you got really lucky to mistype
> this all three times.

Copied of course :)

I added a special spell checking rule for this typo, but it does help
reliably.

...
>> +	terga_soc_for_each_device(soc_dev) {
>> +		do {
>> +			/*
>> +			 * Devices like display controller have multiple
>> +			 * instances with the same compatible. Hence we need
>> +			 * to walk up the whole tree in order to account those
>> +			 * multiple instances.
>> +			 */
>> +			np = of_find_compatible_node(prev_np, NULL,
>> +						     soc_dev->compatible);
>> +			of_node_put(prev_np);
>> +			prev_np = np;
>> +
>> +			if (of_device_is_available(np)) {
>> +				pr_debug("added %s\n", soc_dev->compatible);
>> +				soc_dev->sync_count++;
>> +			}
>> +		} while (np);
> 
> Maybe use for_each_compatible_node() for that inside loop?

Good point! I think there is actually an of_node_put() bug in current
variant, which for_each_compatible_node() would safe from.

>> +	}
>> +
>> +	return 0;
>>  }
>> +postcore_initcall_sync(tegra_soc_devices_init);
> 
> This is unfortunate. I recall having this discussion multiple times and
> one idea that has been floating around for a while was to let a driver
> bind against the top-level "bus" node. That has the advantage that it
> both anchors the code somewhere, so we don't have to play this game of
> checking for the SoC with soc_is_tegra(), and it properly orders this
> with respect to the child devices, so we wouldn't have to make this a
> postcore_initcall.
> 
> Might be worth looking at that again, but for now this seems okay.

Thanks

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-10 20:32     ` Mark Brown
@ 2020-11-10 21:23       ` Dmitry Osipenko
  2020-11-11 11:55         ` Mark Brown
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-10 21:23 UTC (permalink / raw)
  To: Mark Brown, Thierry Reding
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Liam Girdwood,
	Adrian Hunter, Krzysztof Kozlowski, Greg Kroah-Hartman,
	Lee Jones, Uwe Kleine-König, Ulf Hansson,
	Mauro Carvalho Chehab, Rob Herring, Marek Szyprowski, Peter Geis,
	Nicolas Chauvet, linux-samsung-soc, devel, linux-usb, linux-pwm,
	linux-mmc, linux-kernel, devicetree, dri-devel, linux-media,
	linux-tegra

10.11.2020 23:32, Mark Brown пишет:
> On Tue, Nov 10, 2020 at 09:29:45PM +0100, Thierry Reding wrote:
>> On Thu, Nov 05, 2020 at 02:44:08AM +0300, Dmitry Osipenko wrote:
> 
>>> +	/*
>>> +	 * Voltage scaling is optional and trying to set voltage for a dummy
>>> +	 * regulator will error out.
>>> +	 */
>>> +	if (!device_property_present(dc->dev, "core-supply"))
>>> +		return;
> 
>> This is a potentially heavy operation, so I think we should avoid that
>> here. How about you use devm_regulator_get_optional() in ->probe()? That
>> returns -ENODEV if no regulator was specified, in which case you can set
>> dc->core_reg = NULL and use that as the condition here.
> 
> Or enumerate the configurable voltages after getting the regulator and
> handle that appropriately which would be more robust in case there's
> missing or unusual constraints.
> 

I already changed that code to use regulator_get_optional() for v2.

Regarding the enumerating supported voltage.. I think this should be
done by the OPP core, but regulator core doesn't work well if
regulator_get() is invoked more than one time for the same device, at
least there is a loud debugfs warning about an already existing
directory for a regulator. It's easy to check whether the debug
directory exists before creating it, like thermal framework does it for
example, but then there were some other more difficult issues.. I don't
recall what they were right now. Perhaps will be easier to simply get a
error from regulator_set_voltage() for now because it shouldn't ever
happen in practice, unless device-tree has wrong constraints.

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

* Re: [PATCH v1 07/30] soc/tegra: Add sync state API
  2020-11-10 21:22     ` Dmitry Osipenko
@ 2020-11-10 21:32       ` Dmitry Osipenko
  0 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-10 21:32 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

11.11.2020 00:22, Dmitry Osipenko пишет:
> I added a special spell checking rule for this typo, but it does help
> reliably.

does *not*

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-10 20:29   ` Thierry Reding
  2020-11-10 20:32     ` Mark Brown
  2020-11-10 21:17     ` Dmitry Osipenko
@ 2020-11-10 21:50     ` Dmitry Osipenko
  2020-11-11  9:28     ` Dan Carpenter
  3 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-10 21:50 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Alan Stern, Peter Chen, Mark Brown,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

10.11.2020 23:29, Thierry Reding пишет:
>> +	/* legacy device-trees don't have OPP table */
>> +	if (!device_property_present(dc->dev, "operating-points-v2"))
>> +		return 0;
> "Legacy" is a bit confusing here. For one, no device trees currently
> have these tables and secondly, for newer SoCs we may never need them.
> 

I had the same thought and already improved such comments a day ago.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-10 20:29   ` Thierry Reding
                       ` (2 preceding siblings ...)
  2020-11-10 21:50     ` Dmitry Osipenko
@ 2020-11-11  9:28     ` Dan Carpenter
  3 siblings, 0 replies; 108+ messages in thread
From: Dan Carpenter @ 2020-11-11  9:28 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Dmitry Osipenko, Peter Chen, Ulf Hansson, Liam Girdwood,
	dri-devel, Adrian Hunter, devicetree, Lee Jones,
	Marek Szyprowski, devel, linux-samsung-soc, Nicolas Chauvet,
	Krzysztof Kozlowski, Jonathan Hunter, Alan Stern,
	Uwe Kleine-König, linux-media, linux-pwm, Rob Herring,
	linux-tegra, Mauro Carvalho Chehab, Greg Kroah-Hartman,
	linux-usb, linux-mmc, linux-kernel, Mark Brown, Peter Geis

On Tue, Nov 10, 2020 at 09:29:45PM +0100, Thierry Reding wrote:
> > +	err = dev_pm_opp_of_add_table(dc->dev);
> > +	if (err) {
> > +		dev_err(dc->dev, "failed to add OPP table: %d\n", err);
> > +		goto put_hw;
> > +	}
> > +
> > +	err = devm_add_action(dc->dev, tegra_dc_deinit_opp_table, dc);
> > +	if (err)
> > +		goto remove_table;
> 
> Do these functions return positive values? If not, I'd prefer if this
> check was more explicit (i.e. err < 0) for consistency with the rest of
> this code.
> 

Isn't it the other way around?  It's only when the check is explicitly
for "if (ret < 0)" that we have to wonder about positives. If the codes
says "if (ret)" then we know that it doesn't return positive values and
every non-zero is an error.

In the kernel "if (ret)" is way more popular than "if (ret < 0)":

    $ git grep 'if (\(ret\|rc\|err\))' | wc -l
    92927
    $ git grep 'if (\(ret\|rc\|err\) < 0)' | wc -l
    36577

And some of those are places where "ret" can be positive so we are
forced to use the "if (ret < 0)" format.

Checking for "if (ret)" is easier from a static analysis perspective.
If it's one style is used consistently then they're the same but when
there is a mismatch the "if (ret < 0) " will trigger a false positive
and the "if (ret) " will not.

	int var;

	ret = frob(&var);
	if (ret < 0)
		return ret;

Smatch thinks positive returns are not handled so it complains that
"var can be uninitialized".

regards,
dan carpenter


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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-08 12:19     ` Dmitry Osipenko
  2020-11-09  4:43       ` Viresh Kumar
@ 2020-11-11 11:38       ` Ulf Hansson
  2020-11-12 19:57         ` Dmitry Osipenko
  1 sibling, 1 reply; 108+ messages in thread
From: Ulf Hansson @ 2020-11-11 11:38 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Viresh Kumar, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On Sun, 8 Nov 2020 at 13:19, Dmitry Osipenko <digetx@gmail.com> wrote:
>
> 05.11.2020 18:22, Dmitry Osipenko пишет:
> > 05.11.2020 12:45, Ulf Hansson пишет:
> > ...
> >> I need some more time to review this, but just a quick check found a
> >> few potential issues...
> >
> > Thank you for starting the review! I'm pretty sure it will take a couple
> > revisions until all the questions will be resolved :)
> >
> >> The "core-supply", that you specify as a regulator for each
> >> controller's device node, is not the way we describe power domains.
> >> Instead, it seems like you should register a power-domain provider
> >> (with the help of genpd) and implement the ->set_performance_state()
> >> callback for it. Each device node should then be hooked up to this
> >> power-domain, rather than to a "core-supply". For DT bindings, please
> >> have a look at Documentation/devicetree/bindings/power/power-domain.yaml
> >> and Documentation/devicetree/bindings/power/power_domain.txt.
> >>
> >> In regards to the "sync state" problem (preventing to change
> >> performance states until all consumers have been attached), this can
> >> then be managed by the genpd provider driver instead.
> >
> > I'll need to take a closer look at GENPD, thank you for the suggestion.
> >
> > Sounds like a software GENPD driver which manages clocks and voltages
> > could be a good idea, but it also could be an unnecessary
> > over-engineering. Let's see..
> >
>
> Hello Ulf and all,
>
> I took a detailed look at the GENPD and tried to implement it. Here is
> what was found:
>
> 1. GENPD framework doesn't aggregate performance requests from the
> attached devices. This means that if deviceA requests performance state
> 10 and then deviceB requests state 3, then framework will set domain's
> state to 3 instead of 10.
>
> https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/base/power/domain.c#L376

As Viresh also stated, genpd does aggregate the votes. It even
performs aggregation hierarchy (a genpd is allowed to have parent(s)
to model a topology).

>
> 2. GENPD framework has a sync() callback in the genpd.domain structure,
> but this callback isn't allowed to be used by the GENPD implementation.
> The GENPD framework always overrides that callback for its own needs.
> Hence GENPD doesn't allow to solve the bootstrapping
> state-synchronization problem in a nice way.
>
> https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/base/power/domain.c#L2606

That ->sync() callback isn't the callback you are looking for, it's a
PM domain specific callback - and has other purposes.

To solve the problem you refer to, your genpd provider driver (a
platform driver) should assign its ->sync_state() callback. The
->sync_state() callback will be invoked, when all consumer devices
have been attached (and probed) to their corresponding provider.

You may have a look at drivers/cpuidle/cpuidle-psci-domain.c, to see
an example of how this works. If there is anything unclear, just tell
me and I will try to help.

>
> 3. Tegra doesn't have a dedicated hardware power-controller for the core
> domain, instead there is only an external voltage regulator. Hence we
> will need to create a phony device-tree node for the virtual power
> domain, which is probably a wrong thing to do.

No, this is absolutely the correct thing to do.

This isn't a virtual power domain, it's a real power domain. You only
happen to model the control of it as a regulator, as it fits nicely
with that for *this* SoC. Don't get me wrong, that's fine as long as
the supply is specified only in the power-domain provider node.

On another SoC, you might have a different FW interface for the power
domain provider that doesn't fit well with the regulator. When that
happens, all you need to do is to implement a new power domain
provider and potentially re-define the power domain topology. More
importantly, you don't need to re-invent yet another slew of device
specific bindings - for each SoC.

>
> ===
>
> Perhaps it should be possible to create some hacks to work around
> bullets 2 and 3 in order to achieve what we need for DVFS on Tegra, but
> bullet 1 isn't solvable without changing how the GENPD core works.
>
> Altogether, the GENPD in its current form is a wrong abstraction for a
> system-wide DVFS in a case where multiple devices share power domain and
> this domain is a voltage regulator. The regulator framework is the
> correct abstraction in this case for today.

Well, I admit it's a bit complex. But it solves the problem in a
nicely abstracted way that should work for everybody, at least in my
opinion.

Although, let's not exclude that there are pieces missing in genpd or
the opp layer, as this DVFS feature is rather new - but then we should
just extend/fix it.

Kind regards
Uffe

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

* Re: [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties
  2020-11-04 23:43 ` [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties Dmitry Osipenko
  2020-11-09 18:57   ` Rob Herring
@ 2020-11-11 11:45   ` Ulf Hansson
  1 sibling, 0 replies; 108+ messages in thread
From: Ulf Hansson @ 2020-11-11 11:45 UTC (permalink / raw)
  To: Dmitry Osipenko, Rob Herring
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Mauro Carvalho Chehab, Marek Szyprowski, Peter Geis,
	Nicolas Chauvet, linux-samsung-soc, driverdevel, Linux USB List,
	linux-pwm, linux-mmc, Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On Thu, 5 Nov 2020 at 00:44, Dmitry Osipenko <digetx@gmail.com> wrote:
>
> Document new DVFS OPP table and voltage regulator properties of the
> Host1x bus and devices sitting on the bus.
>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../display/tegra/nvidia,tegra20-host1x.txt   | 56 +++++++++++++++++++
>  1 file changed, 56 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
> index 34d993338453..0593c8df70bb 100644
> --- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
> +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
> @@ -20,6 +20,18 @@ Required properties:
>  - reset-names: Must include the following entries:
>    - host1x
>
> +Optional properties:
> +- operating-points-v2: See ../bindings/opp/opp.txt for details.
> +- core-supply: Phandle of voltage regulator of the SoC "core" power domain.
> +
> +For each opp entry in 'operating-points-v2' table of host1x and its modules:
> +- opp-supported-hw: One bitfield indicating:
> +       On Tegra20: SoC process ID mask
> +       On Tegra30+: SoC speedo ID mask
> +
> +       A bitwise AND is performed against the value and if any bit
> +       matches, the OPP gets enabled.
> +
>  Each host1x client module having to perform DMA through the Memory Controller
>  should have the interconnect endpoints set to the Memory Client and External
>  Memory respectively.
> @@ -45,6 +57,8 @@ of the following host1x client modules:
>    - interconnect-names: Must include name of the interconnect path for each
>      interconnect entry. Consult TRM documentation for information about
>      available memory clients, see MEMORY CONTROLLER section.
> +  - core-supply: Phandle of voltage regulator of the SoC "core" power domain.
> +  - operating-points-v2: See ../bindings/opp/opp.txt for details.
>

As discussed in the thread for the cover-letter.

We already have DT bindings for power-domains (providers and
consumers). Please use them instead of adding SoC specific bindings to
each peripheral device.

[...]

Kind regards
Uffe

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-10 21:23       ` Dmitry Osipenko
@ 2020-11-11 11:55         ` Mark Brown
  2020-11-12 16:59           ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-11-11 11:55 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 1816 bytes --]

On Wed, Nov 11, 2020 at 12:23:41AM +0300, Dmitry Osipenko wrote:
> 10.11.2020 23:32, Mark Brown пишет:

> >>> +	if (!device_property_present(dc->dev, "core-supply"))
> >>> +		return;

> >> This is a potentially heavy operation, so I think we should avoid that
> >> here. How about you use devm_regulator_get_optional() in ->probe()? That
> >> returns -ENODEV if no regulator was specified, in which case you can set
> >> dc->core_reg = NULL and use that as the condition here.

> > Or enumerate the configurable voltages after getting the regulator and
> > handle that appropriately which would be more robust in case there's
> > missing or unusual constraints.

> I already changed that code to use regulator_get_optional() for v2.

That doesn't look entirely appropriate given that the core does most
likely require some kind of power to operate.

> Regarding the enumerating supported voltage.. I think this should be
> done by the OPP core, but regulator core doesn't work well if
> regulator_get() is invoked more than one time for the same device, at
> least there is a loud debugfs warning about an already existing

I don't understand why this would be an issue - if nothing else the core
could just offer an interface to trigger the check.

> directory for a regulator. It's easy to check whether the debug
> directory exists before creating it, like thermal framework does it for
> example, but then there were some other more difficult issues.. I don't
> recall what they were right now. Perhaps will be easier to simply get a
> error from regulator_set_voltage() for now because it shouldn't ever
> happen in practice, unless device-tree has wrong constraints.

The constraints might not be wrong, there might be some board which has
a constraint somewhere for 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-11 11:55         ` Mark Brown
@ 2020-11-12 16:59           ` Dmitry Osipenko
  2020-11-12 17:16             ` Mark Brown
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-12 16:59 UTC (permalink / raw)
  To: Mark Brown
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

11.11.2020 14:55, Mark Brown пишет:
> On Wed, Nov 11, 2020 at 12:23:41AM +0300, Dmitry Osipenko wrote:
>> 10.11.2020 23:32, Mark Brown пишет:
> 
>>>>> +	if (!device_property_present(dc->dev, "core-supply"))
>>>>> +		return;
> 
>>>> This is a potentially heavy operation, so I think we should avoid that
>>>> here. How about you use devm_regulator_get_optional() in ->probe()? That
>>>> returns -ENODEV if no regulator was specified, in which case you can set
>>>> dc->core_reg = NULL and use that as the condition here.
> 
>>> Or enumerate the configurable voltages after getting the regulator and
>>> handle that appropriately which would be more robust in case there's
>>> missing or unusual constraints.
> 
>> I already changed that code to use regulator_get_optional() for v2.
> 
> That doesn't look entirely appropriate given that the core does most
> likely require some kind of power to operate.

We will need to do this because older DTBs won't have that regulator and
we want to keep them working.

Also, some device-trees won't have that regulator anyways because board
schematics isn't available, and thus, we can't fix them.

>> Regarding the enumerating supported voltage.. I think this should be
>> done by the OPP core, but regulator core doesn't work well if
>> regulator_get() is invoked more than one time for the same device, at
>> least there is a loud debugfs warning about an already existing
> 
> I don't understand why this would be an issue - if nothing else the core
> could just offer an interface to trigger the check.

It's not an issue, I just described what happens when device driver
tries to get a regulator twice.

There was an issue once that check is added to the regulator core code.
But perhaps not worth to discuss it for now because I don't remember
details.

>> directory for a regulator. It's easy to check whether the debug
>> directory exists before creating it, like thermal framework does it for
>> example, but then there were some other more difficult issues.. I don't
>> recall what they were right now. Perhaps will be easier to simply get a
>> error from regulator_set_voltage() for now because it shouldn't ever
>> happen in practice, unless device-tree has wrong constraints.
> 
> The constraints might not be wrong, there might be some board which has
> a constraint somewhere for 
> 

In this case board's DT shouldn't specify unsupportable OPPs.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-12 16:59           ` Dmitry Osipenko
@ 2020-11-12 17:16             ` Mark Brown
  2020-11-12 19:16               ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-11-12 17:16 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 2343 bytes --]

On Thu, Nov 12, 2020 at 07:59:36PM +0300, Dmitry Osipenko wrote:
> 11.11.2020 14:55, Mark Brown пишет:
> > On Wed, Nov 11, 2020 at 12:23:41AM +0300, Dmitry Osipenko wrote:

> >> I already changed that code to use regulator_get_optional() for v2.

> > That doesn't look entirely appropriate given that the core does most
> > likely require some kind of power to operate.

> We will need to do this because older DTBs won't have that regulator and
> we want to keep them working.

> Also, some device-trees won't have that regulator anyways because board
> schematics isn't available, and thus, we can't fix them.

This is what dummy supplies are for?

> >> Regarding the enumerating supported voltage.. I think this should be
> >> done by the OPP core, but regulator core doesn't work well if
> >> regulator_get() is invoked more than one time for the same device, at
> >> least there is a loud debugfs warning about an already existing

> > I don't understand why this would be an issue - if nothing else the core
> > could just offer an interface to trigger the check.

> It's not an issue, I just described what happens when device driver
> tries to get a regulator twice.

> There was an issue once that check is added to the regulator core code.
> But perhaps not worth to discuss it for now because I don't remember
> details.

So there's no known obstacle to putting enumeration of supported
voltages into the OPP core then?  I'm a bit confused here.

> >> directory for a regulator. It's easy to check whether the debug
> >> directory exists before creating it, like thermal framework does it for
> >> example, but then there were some other more difficult issues.. I don't
> >> recall what they were right now. Perhaps will be easier to simply get a
> >> error from regulator_set_voltage() for now because it shouldn't ever
> >> happen in practice, unless device-tree has wrong constraints.

> > The constraints might not be wrong, there might be some board which has
> > a constraint somewhere for 

> In this case board's DT shouldn't specify unsupportable OPPs.

Ah, so each board duplicates the OPP tables then, or there's an
expectation that if there's some limit then they'll copy and modify the
table?  If that's the case then it's a bit redundant to do filtering
indeed.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-12 17:16             ` Mark Brown
@ 2020-11-12 19:16               ` Dmitry Osipenko
  2020-11-12 20:01                 ` Mark Brown
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-12 19:16 UTC (permalink / raw)
  To: Mark Brown
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

12.11.2020 20:16, Mark Brown пишет:
> On Thu, Nov 12, 2020 at 07:59:36PM +0300, Dmitry Osipenko wrote:
>> 11.11.2020 14:55, Mark Brown пишет:
>>> On Wed, Nov 11, 2020 at 12:23:41AM +0300, Dmitry Osipenko wrote:
> 
>>>> I already changed that code to use regulator_get_optional() for v2.
> 
>>> That doesn't look entirely appropriate given that the core does most
>>> likely require some kind of power to operate.
> 
>> We will need to do this because older DTBs won't have that regulator and
>> we want to keep them working.
> 
>> Also, some device-trees won't have that regulator anyways because board
>> schematics isn't available, and thus, we can't fix them.
> 
> This is what dummy supplies are for?

But it's not allowed to change voltage of a dummy regulator, is it
intentional?

>>>> Regarding the enumerating supported voltage.. I think this should be
>>>> done by the OPP core, but regulator core doesn't work well if
>>>> regulator_get() is invoked more than one time for the same device, at
>>>> least there is a loud debugfs warning about an already existing
> 
>>> I don't understand why this would be an issue - if nothing else the core
>>> could just offer an interface to trigger the check.
> 
>> It's not an issue, I just described what happens when device driver
>> tries to get a regulator twice.
> 
>> There was an issue once that check is added to the regulator core code.
>> But perhaps not worth to discuss it for now because I don't remember
>> details.
> 
> So there's no known obstacle to putting enumeration of supported
> voltages into the OPP core then?  I'm a bit confused here.

It's an obstacle if both OPP and device driver need to get the same
regulator. Like in the case of this DRM driver, which need to control
the voltage instead of allowing OPP core to do it.

Please notice that devm_tegra_dc_opp_table_init() of this patch doesn't
use dev_pm_opp_set_regulators(), which would allow OPP core to filter
out unsupported OPPs. But then OPP core will need need to get an already
requested regulator and this doesn't work well.

>>>> directory for a regulator. It's easy to check whether the debug
>>>> directory exists before creating it, like thermal framework does it for
>>>> example, but then there were some other more difficult issues.. I don't
>>>> recall what they were right now. Perhaps will be easier to simply get a
>>>> error from regulator_set_voltage() for now because it shouldn't ever
>>>> happen in practice, unless device-tree has wrong constraints.
> 
>>> The constraints might not be wrong, there might be some board which has
>>> a constraint somewhere for 
> 
>> In this case board's DT shouldn't specify unsupportable OPPs.
> 
> Ah, so each board duplicates the OPP tables then, or there's an
> expectation that if there's some limit then they'll copy and modify the
> table?  If that's the case then it's a bit redundant to do filtering
> indeed.

I think this is not strictly defined. Either way will work, although
perhaps it should be more preferred that unsupported OPPs aren't present
in a device-tree.

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-11 11:38       ` Ulf Hansson
@ 2020-11-12 19:57         ` Dmitry Osipenko
  2020-11-12 20:43           ` Thierry Reding
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-12 19:57 UTC (permalink / raw)
  To: Ulf Hansson, Thierry Reding
  Cc: Viresh Kumar, Jonathan Hunter, Alan Stern, Peter Chen,
	Mark Brown, Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Mauro Carvalho Chehab, Rob Herring, Marek Szyprowski, Peter Geis,
	Nicolas Chauvet, linux-samsung-soc, driverdevel, Linux USB List,
	linux-pwm, linux-mmc, Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

11.11.2020 14:38, Ulf Hansson пишет:
> On Sun, 8 Nov 2020 at 13:19, Dmitry Osipenko <digetx@gmail.com> wrote:
>>
>> 05.11.2020 18:22, Dmitry Osipenko пишет:
>>> 05.11.2020 12:45, Ulf Hansson пишет:
>>> ...
>>>> I need some more time to review this, but just a quick check found a
>>>> few potential issues...
>>>
>>> Thank you for starting the review! I'm pretty sure it will take a couple
>>> revisions until all the questions will be resolved :)
>>>
>>>> The "core-supply", that you specify as a regulator for each
>>>> controller's device node, is not the way we describe power domains.
>>>> Instead, it seems like you should register a power-domain provider
>>>> (with the help of genpd) and implement the ->set_performance_state()
>>>> callback for it. Each device node should then be hooked up to this
>>>> power-domain, rather than to a "core-supply". For DT bindings, please
>>>> have a look at Documentation/devicetree/bindings/power/power-domain.yaml
>>>> and Documentation/devicetree/bindings/power/power_domain.txt.
>>>>
>>>> In regards to the "sync state" problem (preventing to change
>>>> performance states until all consumers have been attached), this can
>>>> then be managed by the genpd provider driver instead.
>>>
>>> I'll need to take a closer look at GENPD, thank you for the suggestion.
>>>
>>> Sounds like a software GENPD driver which manages clocks and voltages
>>> could be a good idea, but it also could be an unnecessary
>>> over-engineering. Let's see..
>>>
>>
>> Hello Ulf and all,
>>
>> I took a detailed look at the GENPD and tried to implement it. Here is
>> what was found:
>>
>> 1. GENPD framework doesn't aggregate performance requests from the
>> attached devices. This means that if deviceA requests performance state
>> 10 and then deviceB requests state 3, then framework will set domain's
>> state to 3 instead of 10.
>>
>> https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/base/power/domain.c#L376
> 
> As Viresh also stated, genpd does aggregate the votes. It even
> performs aggregation hierarchy (a genpd is allowed to have parent(s)
> to model a topology).

Yes, I already found and fixed the bug which confused me previously and
it's working well now.

>> 2. GENPD framework has a sync() callback in the genpd.domain structure,
>> but this callback isn't allowed to be used by the GENPD implementation.
>> The GENPD framework always overrides that callback for its own needs.
>> Hence GENPD doesn't allow to solve the bootstrapping
>> state-synchronization problem in a nice way.
>>
>> https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/base/power/domain.c#L2606
> 
> That ->sync() callback isn't the callback you are looking for, it's a
> PM domain specific callback - and has other purposes.
> 
> To solve the problem you refer to, your genpd provider driver (a
> platform driver) should assign its ->sync_state() callback. The
> ->sync_state() callback will be invoked, when all consumer devices
> have been attached (and probed) to their corresponding provider.
> 
> You may have a look at drivers/cpuidle/cpuidle-psci-domain.c, to see
> an example of how this works. If there is anything unclear, just tell
> me and I will try to help.

Indeed, thank you for the clarification. This variant works well.

>> 3. Tegra doesn't have a dedicated hardware power-controller for the core
>> domain, instead there is only an external voltage regulator. Hence we
>> will need to create a phony device-tree node for the virtual power
>> domain, which is probably a wrong thing to do.
> 
> No, this is absolutely the correct thing to do.
> 
> This isn't a virtual power domain, it's a real power domain. You only
> happen to model the control of it as a regulator, as it fits nicely
> with that for *this* SoC. Don't get me wrong, that's fine as long as
> the supply is specified only in the power-domain provider node.
> 
> On another SoC, you might have a different FW interface for the power
> domain provider that doesn't fit well with the regulator. When that
> happens, all you need to do is to implement a new power domain
> provider and potentially re-define the power domain topology. More
> importantly, you don't need to re-invent yet another slew of device
> specific bindings - for each SoC.
> 
>>
>> ===
>>
>> Perhaps it should be possible to create some hacks to work around
>> bullets 2 and 3 in order to achieve what we need for DVFS on Tegra, but
>> bullet 1 isn't solvable without changing how the GENPD core works.
>>
>> Altogether, the GENPD in its current form is a wrong abstraction for a
>> system-wide DVFS in a case where multiple devices share power domain and
>> this domain is a voltage regulator. The regulator framework is the
>> correct abstraction in this case for today.
> 
> Well, I admit it's a bit complex. But it solves the problem in a
> nicely abstracted way that should work for everybody, at least in my
> opinion.

The OPP framework supports both voltage regulator and power domain,
hiding the implementation details from drivers. This means that OPP API
usage will be the same regardless of what approach (regulator or power
domain) is used for a particular SoC.

> Although, let's not exclude that there are pieces missing in genpd or
> the opp layer, as this DVFS feature is rather new - but then we should
> just extend/fix it.

Will be nice to have a per-device GENPD performance stats.

Thierry, could you please let me know what do you think about replacing
regulator with the power domain? Do you think it's a worthwhile change?

The difference in comparison to using voltage regulator directly is
minimal, basically the core-supply phandle is replaced is replaced with
a power-domain phandle in a device tree.

The only thing which makes me feel a bit uncomfortable is that there is
no real hardware node for the power domain node in a device-tree.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-12 19:16               ` Dmitry Osipenko
@ 2020-11-12 20:01                 ` Mark Brown
  2020-11-12 22:37                   ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-11-12 20:01 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 2620 bytes --]

On Thu, Nov 12, 2020 at 10:16:14PM +0300, Dmitry Osipenko wrote:
> 12.11.2020 20:16, Mark Brown пишет:
> > On Thu, Nov 12, 2020 at 07:59:36PM +0300, Dmitry Osipenko wrote:

> >> Also, some device-trees won't have that regulator anyways because board
> >> schematics isn't available, and thus, we can't fix them.

> > This is what dummy supplies are for?

> But it's not allowed to change voltage of a dummy regulator, is it
> intentional?

Of course not, we can't know if the requested new voltage is valid - the
driver would have to have explict support for handling situations where
it's not possible to change the voltage (which it can detect through
enumerating the values it wants to set at startup).

[Requesting the same supply multiple times]
> > So there's no known obstacle to putting enumeration of supported
> > voltages into the OPP core then?  I'm a bit confused here.

> It's an obstacle if both OPP and device driver need to get the same
> regulator. Like in the case of this DRM driver, which need to control
> the voltage instead of allowing OPP core to do it.

It wasn't entirely deliberate but the warnings have proven useful in
catching bugs (eg, leaked regulator requests).  The general thought is
that if two things both claim to control the same supply on a consumer
then they really ought to be coordinating with each other.

> Please notice that devm_tegra_dc_opp_table_init() of this patch doesn't
> use dev_pm_opp_set_regulators(), which would allow OPP core to filter
> out unsupported OPPs. But then OPP core will need need to get an already
> requested regulator and this doesn't work well.

There is nothing stopping us adding a variant of that call which passes
in the regulators that were acquired by the caller rather than having
the OPP core do the requesting, or equally the OPP core could provide a
mechanism for the caller to get the regulators that were requested.

> > Ah, so each board duplicates the OPP tables then, or there's an
> > expectation that if there's some limit then they'll copy and modify the
> > table?  If that's the case then it's a bit redundant to do filtering
> > indeed.

> I think this is not strictly defined. Either way will work, although
> perhaps it should be more preferred that unsupported OPPs aren't present
> in a device-tree.

OTOH that does mean that if there's an updated information on OPPs (new
ones added, old ones determined to be unstable) then you can't just
update a central place.  It depends if the OPPs are thought of as
describing the SoC or the system as a whole I guess.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-12 19:57         ` Dmitry Osipenko
@ 2020-11-12 20:43           ` Thierry Reding
  2020-11-12 22:14             ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Thierry Reding @ 2020-11-12 20:43 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Ulf Hansson, Viresh Kumar, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 7076 bytes --]

On Thu, Nov 12, 2020 at 10:57:27PM +0300, Dmitry Osipenko wrote:
> 11.11.2020 14:38, Ulf Hansson пишет:
> > On Sun, 8 Nov 2020 at 13:19, Dmitry Osipenko <digetx@gmail.com> wrote:
> >>
> >> 05.11.2020 18:22, Dmitry Osipenko пишет:
> >>> 05.11.2020 12:45, Ulf Hansson пишет:
> >>> ...
> >>>> I need some more time to review this, but just a quick check found a
> >>>> few potential issues...
> >>>
> >>> Thank you for starting the review! I'm pretty sure it will take a couple
> >>> revisions until all the questions will be resolved :)
> >>>
> >>>> The "core-supply", that you specify as a regulator for each
> >>>> controller's device node, is not the way we describe power domains.
> >>>> Instead, it seems like you should register a power-domain provider
> >>>> (with the help of genpd) and implement the ->set_performance_state()
> >>>> callback for it. Each device node should then be hooked up to this
> >>>> power-domain, rather than to a "core-supply". For DT bindings, please
> >>>> have a look at Documentation/devicetree/bindings/power/power-domain.yaml
> >>>> and Documentation/devicetree/bindings/power/power_domain.txt.
> >>>>
> >>>> In regards to the "sync state" problem (preventing to change
> >>>> performance states until all consumers have been attached), this can
> >>>> then be managed by the genpd provider driver instead.
> >>>
> >>> I'll need to take a closer look at GENPD, thank you for the suggestion.
> >>>
> >>> Sounds like a software GENPD driver which manages clocks and voltages
> >>> could be a good idea, but it also could be an unnecessary
> >>> over-engineering. Let's see..
> >>>
> >>
> >> Hello Ulf and all,
> >>
> >> I took a detailed look at the GENPD and tried to implement it. Here is
> >> what was found:
> >>
> >> 1. GENPD framework doesn't aggregate performance requests from the
> >> attached devices. This means that if deviceA requests performance state
> >> 10 and then deviceB requests state 3, then framework will set domain's
> >> state to 3 instead of 10.
> >>
> >> https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/base/power/domain.c#L376
> > 
> > As Viresh also stated, genpd does aggregate the votes. It even
> > performs aggregation hierarchy (a genpd is allowed to have parent(s)
> > to model a topology).
> 
> Yes, I already found and fixed the bug which confused me previously and
> it's working well now.
> 
> >> 2. GENPD framework has a sync() callback in the genpd.domain structure,
> >> but this callback isn't allowed to be used by the GENPD implementation.
> >> The GENPD framework always overrides that callback for its own needs.
> >> Hence GENPD doesn't allow to solve the bootstrapping
> >> state-synchronization problem in a nice way.
> >>
> >> https://elixir.bootlin.com/linux/v5.10-rc2/source/drivers/base/power/domain.c#L2606
> > 
> > That ->sync() callback isn't the callback you are looking for, it's a
> > PM domain specific callback - and has other purposes.
> > 
> > To solve the problem you refer to, your genpd provider driver (a
> > platform driver) should assign its ->sync_state() callback. The
> > ->sync_state() callback will be invoked, when all consumer devices
> > have been attached (and probed) to their corresponding provider.
> > 
> > You may have a look at drivers/cpuidle/cpuidle-psci-domain.c, to see
> > an example of how this works. If there is anything unclear, just tell
> > me and I will try to help.
> 
> Indeed, thank you for the clarification. This variant works well.
> 
> >> 3. Tegra doesn't have a dedicated hardware power-controller for the core
> >> domain, instead there is only an external voltage regulator. Hence we
> >> will need to create a phony device-tree node for the virtual power
> >> domain, which is probably a wrong thing to do.
> > 
> > No, this is absolutely the correct thing to do.
> > 
> > This isn't a virtual power domain, it's a real power domain. You only
> > happen to model the control of it as a regulator, as it fits nicely
> > with that for *this* SoC. Don't get me wrong, that's fine as long as
> > the supply is specified only in the power-domain provider node.
> > 
> > On another SoC, you might have a different FW interface for the power
> > domain provider that doesn't fit well with the regulator. When that
> > happens, all you need to do is to implement a new power domain
> > provider and potentially re-define the power domain topology. More
> > importantly, you don't need to re-invent yet another slew of device
> > specific bindings - for each SoC.
> > 
> >>
> >> ===
> >>
> >> Perhaps it should be possible to create some hacks to work around
> >> bullets 2 and 3 in order to achieve what we need for DVFS on Tegra, but
> >> bullet 1 isn't solvable without changing how the GENPD core works.
> >>
> >> Altogether, the GENPD in its current form is a wrong abstraction for a
> >> system-wide DVFS in a case where multiple devices share power domain and
> >> this domain is a voltage regulator. The regulator framework is the
> >> correct abstraction in this case for today.
> > 
> > Well, I admit it's a bit complex. But it solves the problem in a
> > nicely abstracted way that should work for everybody, at least in my
> > opinion.
> 
> The OPP framework supports both voltage regulator and power domain,
> hiding the implementation details from drivers. This means that OPP API
> usage will be the same regardless of what approach (regulator or power
> domain) is used for a particular SoC.
> 
> > Although, let's not exclude that there are pieces missing in genpd or
> > the opp layer, as this DVFS feature is rather new - but then we should
> > just extend/fix it.
> 
> Will be nice to have a per-device GENPD performance stats.
> 
> Thierry, could you please let me know what do you think about replacing
> regulator with the power domain? Do you think it's a worthwhile change?
> 
> The difference in comparison to using voltage regulator directly is
> minimal, basically the core-supply phandle is replaced is replaced with
> a power-domain phandle in a device tree.

These new power-domain handles would have to be added to devices that
potentially already have a power-domain handle, right? Isn't that going
to cause issues? I vaguely recall that we already have multiple power
domains for the XUSB controller and we have to jump through extra hoops
to make that work.

> The only thing which makes me feel a bit uncomfortable is that there is
> no real hardware node for the power domain node in a device-tree.

Could we anchor the new power domain at the PMC for example? That would
allow us to avoid the "virtual" node. On the other hand, if we were to
use a regulator, we'd be adding a node for that, right? So isn't this
effectively going to be the same node if we use a power domain? Both
software constructs are using the same voltage regulator, so they should
be able to be described by the same device tree node, shouldn't they?

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-12 20:43           ` Thierry Reding
@ 2020-11-12 22:14             ` Dmitry Osipenko
  2020-11-13 14:45               ` Ulf Hansson
  2020-11-13 16:35               ` Thierry Reding
  0 siblings, 2 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-12 22:14 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Ulf Hansson, Viresh Kumar, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

12.11.2020 23:43, Thierry Reding пишет:
>> The difference in comparison to using voltage regulator directly is
>> minimal, basically the core-supply phandle is replaced is replaced with
>> a power-domain phandle in a device tree.
> These new power-domain handles would have to be added to devices that
> potentially already have a power-domain handle, right? Isn't that going
> to cause issues? I vaguely recall that we already have multiple power
> domains for the XUSB controller and we have to jump through extra hoops
> to make that work.

I modeled the core PD as a parent of the PMC sub-domains, which
presumably is a correct way to represent the domains topology.

https://gist.github.com/digetx/dfd92c7f7e0aa6cef20403c4298088d7

>> The only thing which makes me feel a bit uncomfortable is that there is
>> no real hardware node for the power domain node in a device-tree.
> Could we anchor the new power domain at the PMC for example? That would
> allow us to avoid the "virtual" node.

I had a thought about using PMC for the core domain, but not sure
whether it will be an entirely correct hardware description. Although,
it will be nice to have it this way.

This is what Tegra TRM says about PMC:

"The Power Management Controller (PMC) block interacts with an external
or Power Manager Unit (PMU). The PMC mostly controls the entry and exit
of the system from different sleep modes. It provides power-gating
controllers for SOC and CPU power-islands and also provides scratch
storage to save some of the context during sleep modes (when CPU and/or
SOC power rails are off). Additionally, PMC interacts with the external
Power Manager Unit (PMU)."

The core voltage regulator is a part of the PMU.

Not all core SoC devices are behind PMC, IIUC.

> On the other hand, if we were to
> use a regulator, we'd be adding a node for that, right? So isn't this
> effectively going to be the same node if we use a power domain? Both
> software constructs are using the same voltage regulator, so they should
> be able to be described by the same device tree node, shouldn't they?

I'm not exactly sure what you're meaning by "use a regulator" and "we'd
be adding a node for that", could you please clarify? This v1 approach
uses a core-supply phandle (i.e. regulator is used), it doesn't require
extra nodes.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-12 20:01                 ` Mark Brown
@ 2020-11-12 22:37                   ` Dmitry Osipenko
  2020-11-13 14:29                     ` Mark Brown
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-12 22:37 UTC (permalink / raw)
  To: Mark Brown
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

12.11.2020 23:01, Mark Brown пишет:
>> But it's not allowed to change voltage of a dummy regulator, is it
>> intentional?
> Of course not, we can't know if the requested new voltage is valid - the
> driver would have to have explict support for handling situations where
> it's not possible to change the voltage (which it can detect through
> enumerating the values it wants to set at startup).
> 
> [Requesting the same supply multiple times]

But how driver is supposed to recognize that it's a dummy or buggy
regulator if it rejects all voltages?

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-12 22:37                   ` Dmitry Osipenko
@ 2020-11-13 14:29                     ` Mark Brown
  2020-11-13 15:55                       ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-11-13 14:29 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 1586 bytes --]

On Fri, Nov 13, 2020 at 01:37:01AM +0300, Dmitry Osipenko wrote:
> 12.11.2020 23:01, Mark Brown пишет:
> >> But it's not allowed to change voltage of a dummy regulator, is it
> >> intentional?

> > Of course not, we can't know if the requested new voltage is valid - the
> > driver would have to have explict support for handling situations where
> > it's not possible to change the voltage (which it can detect through
> > enumerating the values it wants to set at startup).

> > [Requesting the same supply multiple times]

> But how driver is supposed to recognize that it's a dummy or buggy
> regulator if it rejects all voltages?

It's not clear if it matters - it's more a policy decision on the part
of the driver about what it thinks safe error handling is.  If it's not
possible to read voltages from the regulator the consumer driver has to
decide what it thinks it's safe for it to do, either way it has no idea
what the actual current voltage is.  It could assume that it's something
that supports all the use cases it wants to use and just carry on with
no configuration of voltages, it could decide that it might not support
everything and not make any changes to be safe, or do something like
try to figure out that if we're currently at a given OPP that's the top
OPP possible.  Historically when we've not had regulator control in
these drivers so they have effectively gone with the first option of
just assuming it's a generally safe value, this often aligns with what
the power on requirements for SoCs are so it's not unreasonable.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-12 22:14             ` Dmitry Osipenko
@ 2020-11-13 14:45               ` Ulf Hansson
  2020-11-13 16:00                 ` Dmitry Osipenko
  2020-11-13 16:35               ` Thierry Reding
  1 sibling, 1 reply; 108+ messages in thread
From: Ulf Hansson @ 2020-11-13 14:45 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Viresh Kumar, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

On Thu, 12 Nov 2020 at 23:14, Dmitry Osipenko <digetx@gmail.com> wrote:
>
> 12.11.2020 23:43, Thierry Reding пишет:
> >> The difference in comparison to using voltage regulator directly is
> >> minimal, basically the core-supply phandle is replaced is replaced with
> >> a power-domain phandle in a device tree.
> > These new power-domain handles would have to be added to devices that
> > potentially already have a power-domain handle, right? Isn't that going
> > to cause issues? I vaguely recall that we already have multiple power
> > domains for the XUSB controller and we have to jump through extra hoops
> > to make that work.
>
> I modeled the core PD as a parent of the PMC sub-domains, which
> presumably is a correct way to represent the domains topology.
>
> https://gist.github.com/digetx/dfd92c7f7e0aa6cef20403c4298088d7

That could make sense, it seems.

Anyway, this made me realize that
dev_pm_genpd_set_performance_state(dev) returns -EINVAL, in case the
device's genpd doesn't have the ->set_performance_state() assigned.
This may not be correct. Instead we should likely consider an empty
callback as okay and continue to walk the topology upwards to the
parent domain, etc.

Just wanted to point this out. I intend to post a patch as soon as I
can for this.

[...]

Kind regards
Uffe

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-13 14:29                     ` Mark Brown
@ 2020-11-13 15:55                       ` Dmitry Osipenko
  2020-11-13 16:15                         ` Mark Brown
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-13 15:55 UTC (permalink / raw)
  To: Mark Brown
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

13.11.2020 17:29, Mark Brown пишет:
> On Fri, Nov 13, 2020 at 01:37:01AM +0300, Dmitry Osipenko wrote:
>> 12.11.2020 23:01, Mark Brown пишет:
>>>> But it's not allowed to change voltage of a dummy regulator, is it
>>>> intentional?
> 
>>> Of course not, we can't know if the requested new voltage is valid - the
>>> driver would have to have explict support for handling situations where
>>> it's not possible to change the voltage (which it can detect through
>>> enumerating the values it wants to set at startup).
> 
>>> [Requesting the same supply multiple times]
> 
>> But how driver is supposed to recognize that it's a dummy or buggy
>> regulator if it rejects all voltages?
> 
> It's not clear if it matters - it's more a policy decision on the part
> of the driver about what it thinks safe error handling is.  If it's not
> possible to read voltages from the regulator the consumer driver has to
> decide what it thinks it's safe for it to do, either way it has no idea
> what the actual current voltage is.  It could assume that it's something
> that supports all the use cases it wants to use and just carry on with
> no configuration of voltages, it could decide that it might not support
> everything and not make any changes to be safe, or do something like
> try to figure out that if we're currently at a given OPP that's the top
> OPP possible.  Historically when we've not had regulator control in
> these drivers so they have effectively gone with the first option of
> just assuming it's a generally safe value, this often aligns with what
> the power on requirements for SoCs are so it's not unreasonable.

I don't think that in a case of this particular driver there is a way to
make any decisions other than to assume that all changes are safe to be
done if regulator isn't specified in a device-tree.

If regulator_get() returns a dummy regulator, then this means that
regulator isn't specified in a device-tree. But then the only way for a
consumer driver to check whether regulator is dummy, is to check
presence of the supply property in a device-tree.

We want to emit error messages when something goes wrong, for example
when regulator voltage fails to change. It's fine that voltage changes
are failing for a dummy regulator, but then consumer driver shouldn't
recognize it as a error condition.

The regulator_get_optional() provides a more consistent and
straightforward way for consumer drivers to check presence of a physical
voltage regulator in comparison to dealing with a regulator_get(). The
dummy regulator is nice to use when there is no need to change
regulator's voltage, which doesn't work for a dummy regulator.

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-13 14:45               ` Ulf Hansson
@ 2020-11-13 16:00                 ` Dmitry Osipenko
  0 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-13 16:00 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Thierry Reding, Viresh Kumar, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

13.11.2020 17:45, Ulf Hansson пишет:
> On Thu, 12 Nov 2020 at 23:14, Dmitry Osipenko <digetx@gmail.com> wrote:
>>
>> 12.11.2020 23:43, Thierry Reding пишет:
>>>> The difference in comparison to using voltage regulator directly is
>>>> minimal, basically the core-supply phandle is replaced is replaced with
>>>> a power-domain phandle in a device tree.
>>> These new power-domain handles would have to be added to devices that
>>> potentially already have a power-domain handle, right? Isn't that going
>>> to cause issues? I vaguely recall that we already have multiple power
>>> domains for the XUSB controller and we have to jump through extra hoops
>>> to make that work.
>>
>> I modeled the core PD as a parent of the PMC sub-domains, which
>> presumably is a correct way to represent the domains topology.
>>
>> https://gist.github.com/digetx/dfd92c7f7e0aa6cef20403c4298088d7
> 
> That could make sense, it seems.
> 
> Anyway, this made me realize that
> dev_pm_genpd_set_performance_state(dev) returns -EINVAL, in case the
> device's genpd doesn't have the ->set_performance_state() assigned.
> This may not be correct. Instead we should likely consider an empty
> callback as okay and continue to walk the topology upwards to the
> parent domain, etc.
> 
> Just wanted to point this out. I intend to post a patch as soon as I
> can for this.

Thank you, I was also going to make the same change, but haven't
bothered to do it so far. Please feel free to CC me on the patch.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-13 15:55                       ` Dmitry Osipenko
@ 2020-11-13 16:15                         ` Mark Brown
  2020-11-13 17:13                           ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-11-13 16:15 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 1892 bytes --]

On Fri, Nov 13, 2020 at 06:55:27PM +0300, Dmitry Osipenko wrote:
> 13.11.2020 17:29, Mark Brown пишет:

> > It's not clear if it matters - it's more a policy decision on the part
> > of the driver about what it thinks safe error handling is.  If it's not

> If regulator_get() returns a dummy regulator, then this means that
> regulator isn't specified in a device-tree. But then the only way for a
> consumer driver to check whether regulator is dummy, is to check
> presence of the supply property in a device-tree.

My point here is that the driver shouldn't be checking for a dummy
regulator, the driver should be checking the features that are provided
to it by the regulator and handling those.  It doesn't matter if this is
a dummy regulator or an actual regulator with limited features, the
effect is the same and the handling should be the same.  If the driver
is doing anything to handle dummy regulators explicitly as dummy
regulators it is doing it wrong.

> We want to emit error messages when something goes wrong, for example
> when regulator voltage fails to change. It's fine that voltage changes
> are failing for a dummy regulator, but then consumer driver shouldn't
> recognize it as a error condition.

If you're fine with that you should also be fine with any other
regulator for which you failed to enumerate any voltages which you can
set.

> The regulator_get_optional() provides a more consistent and
> straightforward way for consumer drivers to check presence of a physical
> voltage regulator in comparison to dealing with a regulator_get(). The
> dummy regulator is nice to use when there is no need to change
> regulator's voltage, which doesn't work for a dummy regulator.

To repeat you should *only* be using regulator_get_optional() in the
case where the supply may be physically absent which is not the case
here.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-12 22:14             ` Dmitry Osipenko
  2020-11-13 14:45               ` Ulf Hansson
@ 2020-11-13 16:35               ` Thierry Reding
  2020-11-15 16:29                 ` Dmitry Osipenko
  1 sibling, 1 reply; 108+ messages in thread
From: Thierry Reding @ 2020-11-13 16:35 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Ulf Hansson, Viresh Kumar, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 3162 bytes --]

On Fri, Nov 13, 2020 at 01:14:45AM +0300, Dmitry Osipenko wrote:
> 12.11.2020 23:43, Thierry Reding пишет:
> >> The difference in comparison to using voltage regulator directly is
> >> minimal, basically the core-supply phandle is replaced is replaced with
> >> a power-domain phandle in a device tree.
> > These new power-domain handles would have to be added to devices that
> > potentially already have a power-domain handle, right? Isn't that going
> > to cause issues? I vaguely recall that we already have multiple power
> > domains for the XUSB controller and we have to jump through extra hoops
> > to make that work.
> 
> I modeled the core PD as a parent of the PMC sub-domains, which
> presumably is a correct way to represent the domains topology.
> 
> https://gist.github.com/digetx/dfd92c7f7e0aa6cef20403c4298088d7
> 
> >> The only thing which makes me feel a bit uncomfortable is that there is
> >> no real hardware node for the power domain node in a device-tree.
> > Could we anchor the new power domain at the PMC for example? That would
> > allow us to avoid the "virtual" node.
> 
> I had a thought about using PMC for the core domain, but not sure
> whether it will be an entirely correct hardware description. Although,
> it will be nice to have it this way.
> 
> This is what Tegra TRM says about PMC:
> 
> "The Power Management Controller (PMC) block interacts with an external
> or Power Manager Unit (PMU). The PMC mostly controls the entry and exit
> of the system from different sleep modes. It provides power-gating
> controllers for SOC and CPU power-islands and also provides scratch
> storage to save some of the context during sleep modes (when CPU and/or
> SOC power rails are off). Additionally, PMC interacts with the external
> Power Manager Unit (PMU)."
> 
> The core voltage regulator is a part of the PMU.
> 
> Not all core SoC devices are behind PMC, IIUC.

There are usually some SoC devices that are always-on. Things like the
RTC for example, can never be power-gated, as far as I recall. On newer
chips there are usually many more blocks that can't be powergated at
all.

> > On the other hand, if we were to
> > use a regulator, we'd be adding a node for that, right? So isn't this
> > effectively going to be the same node if we use a power domain? Both
> > software constructs are using the same voltage regulator, so they should
> > be able to be described by the same device tree node, shouldn't they?
> 
> I'm not exactly sure what you're meaning by "use a regulator" and "we'd
> be adding a node for that", could you please clarify? This v1 approach
> uses a core-supply phandle (i.e. regulator is used), it doesn't require
> extra nodes.

What I meant to say was that the actual supply voltage is generated by
some device (typically one of the SD outputs of the PMIC). Whether we
model this as a power domain or a regulator doesn't really matter,
right? So I'm wondering if the device that generates the voltage should
be the power domain provider, just like it is the provider of the
regulator if this was modelled as a regulator.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-13 16:15                         ` Mark Brown
@ 2020-11-13 17:13                           ` Dmitry Osipenko
  2020-11-13 17:28                             ` Mark Brown
  2020-11-13 17:30                             ` Thierry Reding
  0 siblings, 2 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-13 17:13 UTC (permalink / raw)
  To: Mark Brown
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

13.11.2020 19:15, Mark Brown пишет:
> On Fri, Nov 13, 2020 at 06:55:27PM +0300, Dmitry Osipenko wrote:
>> 13.11.2020 17:29, Mark Brown пишет:
> 
>>> It's not clear if it matters - it's more a policy decision on the part
>>> of the driver about what it thinks safe error handling is.  If it's not
> 
>> If regulator_get() returns a dummy regulator, then this means that
>> regulator isn't specified in a device-tree. But then the only way for a
>> consumer driver to check whether regulator is dummy, is to check
>> presence of the supply property in a device-tree.
> 
> My point here is that the driver shouldn't be checking for a dummy
> regulator, the driver should be checking the features that are provided
> to it by the regulator and handling those.

I understand yours point, but then we need dummy regulator to provide
all the features, and currently it does the opposite.

> It doesn't matter if this is
> a dummy regulator or an actual regulator with limited features, the
> effect is the same and the handling should be the same.  If the driver
> is doing anything to handle dummy regulators explicitly as dummy
> regulators it is doing it wrong.

It matters because dummy regulator errors out all checks and changes
other than enable/disable, instead of accepting them. If we could add an
option for dummy regulator to succeed all the checks and accept all the
values, then it could become more usable.

>> We want to emit error messages when something goes wrong, for example
>> when regulator voltage fails to change. It's fine that voltage changes
>> are failing for a dummy regulator, but then consumer driver shouldn't
>> recognize it as a error condition.
> 
> If you're fine with that you should also be fine with any other
> regulator for which you failed to enumerate any voltages which you can
> set.

It's not fine.

In the case of this driver the dummy regulator should succeed instead of
failing.

>> The regulator_get_optional() provides a more consistent and
>> straightforward way for consumer drivers to check presence of a physical
>> voltage regulator in comparison to dealing with a regulator_get(). The
>> dummy regulator is nice to use when there is no need to change
>> regulator's voltage, which doesn't work for a dummy regulator.
> 
> To repeat you should *only* be using regulator_get_optional() in the
> case where the supply may be physically absent which is not the case
> here.
> 

Alright, but then we either need to improve regulator core to make dummy
regulator a bit more usable, or continue to work around it in drivers.
What should we do?

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-13 17:13                           ` Dmitry Osipenko
@ 2020-11-13 17:28                             ` Mark Brown
  2020-11-15 17:42                               ` Dmitry Osipenko
  2020-11-13 17:30                             ` Thierry Reding
  1 sibling, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-11-13 17:28 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 2228 bytes --]

On Fri, Nov 13, 2020 at 08:13:49PM +0300, Dmitry Osipenko wrote:
> 13.11.2020 19:15, Mark Brown пишет:

> > My point here is that the driver shouldn't be checking for a dummy
> > regulator, the driver should be checking the features that are provided
> > to it by the regulator and handling those.

> I understand yours point, but then we need dummy regulator to provide
> all the features, and currently it does the opposite.

As could any other regulator?

> > It doesn't matter if this is
> > a dummy regulator or an actual regulator with limited features, the
> > effect is the same and the handling should be the same.  If the driver
> > is doing anything to handle dummy regulators explicitly as dummy
> > regulators it is doing it wrong.

> It matters because dummy regulator errors out all checks and changes
> other than enable/disable, instead of accepting them. If we could add an
> option for dummy regulator to succeed all the checks and accept all the
> values, then it could become more usable.

I'm a bit confused here TBH - I'm not sure I see a substantial
difference between a consumer detecting that it can't set any voltages
at all and the handling for an optional regulator.  Either way if it's
going to carry on and assume that whatever voltage is there works for
everything it boils down to setting a flag saying to skip the set
voltage operation.  I think you are too focused on the specific
implementation you currently have here.

We obviously can't just accept voltage change operations when we've no
idea what the current voltage of the device is.

> > To repeat you should *only* be using regulator_get_optional() in the
> > case where the supply may be physically absent which is not the case
> > here.
> 
> Alright, but then we either need to improve regulator core to make dummy
> regulator a bit more usable, or continue to work around it in drivers.
> What should we do?

As I keep saying the consumer driver should be enumerating the voltages
it can set, if it can't find any and wants to continue then it can just
skip setting voltages later on.  If only some are unavailable then it
probably wants to eliminate those specific OPPs instead.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-13 17:13                           ` Dmitry Osipenko
  2020-11-13 17:28                             ` Mark Brown
@ 2020-11-13 17:30                             ` Thierry Reding
  1 sibling, 0 replies; 108+ messages in thread
From: Thierry Reding @ 2020-11-13 17:30 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Mark Brown, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 1354 bytes --]

On Fri, Nov 13, 2020 at 08:13:49PM +0300, Dmitry Osipenko wrote:
> 13.11.2020 19:15, Mark Brown пишет:
> > On Fri, Nov 13, 2020 at 06:55:27PM +0300, Dmitry Osipenko wrote:
> >> 13.11.2020 17:29, Mark Brown пишет:
> > 
> >>> It's not clear if it matters - it's more a policy decision on the part
> >>> of the driver about what it thinks safe error handling is.  If it's not
> > 
> >> If regulator_get() returns a dummy regulator, then this means that
> >> regulator isn't specified in a device-tree. But then the only way for a
> >> consumer driver to check whether regulator is dummy, is to check
> >> presence of the supply property in a device-tree.
> > 
> > My point here is that the driver shouldn't be checking for a dummy
> > regulator, the driver should be checking the features that are provided
> > to it by the regulator and handling those.
> 
> I understand yours point, but then we need dummy regulator to provide
> all the features, and currently it does the opposite.

But that's exactly Mark's point. Any regular regulator could be lacking
all of the features just as well. If the regulator supports a fixed
voltage, then it's not going to allow you to set a different one, etc.
The point is that the regulator consumer should then be written in a
way to deal with varying levels of features.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-11-13 16:35               ` Thierry Reding
@ 2020-11-15 16:29                 ` Dmitry Osipenko
  0 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-15 16:29 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Ulf Hansson, Viresh Kumar, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	driverdevel, Linux USB List, linux-pwm, linux-mmc,
	Linux Kernel Mailing List, DTML, dri-devel,
	Linux Media Mailing List, linux-tegra

13.11.2020 19:35, Thierry Reding пишет:
> On Fri, Nov 13, 2020 at 01:14:45AM +0300, Dmitry Osipenko wrote:
>> 12.11.2020 23:43, Thierry Reding пишет:
>>>> The difference in comparison to using voltage regulator directly is
>>>> minimal, basically the core-supply phandle is replaced is replaced with
>>>> a power-domain phandle in a device tree.
>>> These new power-domain handles would have to be added to devices that
>>> potentially already have a power-domain handle, right? Isn't that going
>>> to cause issues? I vaguely recall that we already have multiple power
>>> domains for the XUSB controller and we have to jump through extra hoops
>>> to make that work.
>>
>> I modeled the core PD as a parent of the PMC sub-domains, which
>> presumably is a correct way to represent the domains topology.
>>
>> https://gist.github.com/digetx/dfd92c7f7e0aa6cef20403c4298088d7
>>
>>>> The only thing which makes me feel a bit uncomfortable is that there is
>>>> no real hardware node for the power domain node in a device-tree.
>>> Could we anchor the new power domain at the PMC for example? That would
>>> allow us to avoid the "virtual" node.
>>
>> I had a thought about using PMC for the core domain, but not sure
>> whether it will be an entirely correct hardware description. Although,
>> it will be nice to have it this way.
>>
>> This is what Tegra TRM says about PMC:
>>
>> "The Power Management Controller (PMC) block interacts with an external
>> or Power Manager Unit (PMU). The PMC mostly controls the entry and exit
>> of the system from different sleep modes. It provides power-gating
>> controllers for SOC and CPU power-islands and also provides scratch
>> storage to save some of the context during sleep modes (when CPU and/or
>> SOC power rails are off). Additionally, PMC interacts with the external
>> Power Manager Unit (PMU)."
>>
>> The core voltage regulator is a part of the PMU.
>>
>> Not all core SoC devices are behind PMC, IIUC.
> 
> There are usually some SoC devices that are always-on. Things like the
> RTC for example, can never be power-gated, as far as I recall. On newer
> chips there are usually many more blocks that can't be powergated at
> all.

The RTC is actually a special power domain on Tegra, it's not a part of
the CORE domain, they are separate from each other.

We need to know what blocks belong to a power domain and what's the
power topology of these blocks. I think we already have this knowledge,
so it shouldn't be a problem.

>>> On the other hand, if we were to
>>> use a regulator, we'd be adding a node for that, right? So isn't this
>>> effectively going to be the same node if we use a power domain? Both
>>> software constructs are using the same voltage regulator, so they should
>>> be able to be described by the same device tree node, shouldn't they?
>>
>> I'm not exactly sure what you're meaning by "use a regulator" and "we'd
>> be adding a node for that", could you please clarify? This v1 approach
>> uses a core-supply phandle (i.e. regulator is used), it doesn't require
>> extra nodes.
> 
> What I meant to say was that the actual supply voltage is generated by
> some device (typically one of the SD outputs of the PMIC). Whether we
> model this as a power domain or a regulator doesn't really matter,
> right? So I'm wondering if the device that generates the voltage should
> be the power domain provider, just like it is the provider of the
> regulator if this was modelled as a regulator.

Technically this could be done and it shouldn't be difficult to add
GENPD support to the regulator framework, but I think this is an
inaccurate hardware description.

It shouldn't be correct to describe internal SoC parts as
directly-connected to an external voltage regulator. The core voltage
regulator is connected to a one of several power rails of the Tegra
chip. There is no good way to describe hardware in terms of voltage
regulators, hence that's why this v1 series added a core-supply to each
SoC component of each board's DT individually.

It's actually one of the benefits of using a separate DT node for the
power-domain, which describes the "Tegra Core" part of the Tegra SoC,
and thus, it all stays within tegra.dtsi. This means that PD explicitly
belongs to the SoC internals in oppose to describing PD like it's an
external/off-chip component.

Initially I didn't like much that there is no hardware address to back
up the power domain node in a DT, but actually there is no address for
the power rail. Hence it should be better to describe hardware by
keeping PD internally to the SoC. Note that potentially PD may require
knowledge about specifics of a particular SoC, while external regulator
doesn't belong to a SoC. Also, I guess technically there could be
multiple external regulators which power a single SoC rail.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-13 17:28                             ` Mark Brown
@ 2020-11-15 17:42                               ` Dmitry Osipenko
  2020-11-16 13:33                                 ` Mark Brown
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-15 17:42 UTC (permalink / raw)
  To: Mark Brown
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

13.11.2020 20:28, Mark Brown пишет:
> On Fri, Nov 13, 2020 at 08:13:49PM +0300, Dmitry Osipenko wrote:
>> 13.11.2020 19:15, Mark Brown пишет:
> 
>>> My point here is that the driver shouldn't be checking for a dummy
>>> regulator, the driver should be checking the features that are provided
>>> to it by the regulator and handling those.
> 
>> I understand yours point, but then we need dummy regulator to provide
>> all the features, and currently it does the opposite.
> 
> As could any other regulator?

Yes

>>> It doesn't matter if this is
>>> a dummy regulator or an actual regulator with limited features, the
>>> effect is the same and the handling should be the same.  If the driver
>>> is doing anything to handle dummy regulators explicitly as dummy
>>> regulators it is doing it wrong.
> 
>> It matters because dummy regulator errors out all checks and changes
>> other than enable/disable, instead of accepting them. If we could add an
>> option for dummy regulator to succeed all the checks and accept all the
>> values, then it could become more usable.
> 
> I'm a bit confused here TBH - I'm not sure I see a substantial
> difference between a consumer detecting that it can't set any voltages
> at all and the handling for an optional regulator.  Either way if it's
> going to carry on and assume that whatever voltage is there works for
> everything it boils down to setting a flag saying to skip the set
> voltage operation.  I think you are too focused on the specific
> implementation you currently have here.
> 
> We obviously can't just accept voltage change operations when we've no
> idea what the current voltage of the device is.
> 
>>> To repeat you should *only* be using regulator_get_optional() in the
>>> case where the supply may be physically absent which is not the case
>>> here.
>>
>> Alright, but then we either need to improve regulator core to make dummy
>> regulator a bit more usable, or continue to work around it in drivers.
>> What should we do?
> 
> As I keep saying the consumer driver should be enumerating the voltages
> it can set, if it can't find any and wants to continue then it can just
> skip setting voltages later on.  If only some are unavailable then it
> probably wants to eliminate those specific OPPs instead.

I'm seeing a dummy regulator as a helper for consumer drivers which
removes burden of handling an absent (optional) regulator. Is this a
correct understanding of a dummy regulator?

Older DTBs don't have a regulator and we want to keep them working. This
is equal to a physically absent regulator and in this case it's an
optional regulator, IMO.

Consumer drivers definitely should check voltages, but this should be
done only for a physical regulator.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-15 17:42                               ` Dmitry Osipenko
@ 2020-11-16 13:33                                 ` Mark Brown
  2020-11-19 14:22                                   ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-11-16 13:33 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 1612 bytes --]

On Sun, Nov 15, 2020 at 08:42:10PM +0300, Dmitry Osipenko wrote:
> 13.11.2020 20:28, Mark Brown пишет:

> >> What should we do?

> > As I keep saying the consumer driver should be enumerating the voltages
> > it can set, if it can't find any and wants to continue then it can just
> > skip setting voltages later on.  If only some are unavailable then it
> > probably wants to eliminate those specific OPPs instead.

> I'm seeing a dummy regulator as a helper for consumer drivers which
> removes burden of handling an absent (optional) regulator. Is this a
> correct understanding of a dummy regulator?

> Older DTBs don't have a regulator and we want to keep them working. This
> is equal to a physically absent regulator and in this case it's an
> optional regulator, IMO.

No, you are failing to understand the purpose of this code.  To
reiterate unless the device supports operating with the supply
physically absent then the driver should not be attempting to use
regulator_get_optional().  That exists specifically for the case where
the supply may be absent, nothing else.  The dummy regulator is there
precisely for the case where the system does not describe supplies that
we know are required for the device to function, it fixes up that
omission so we don't need to open code handling of this in every single
consumer driver.

Regulators that are present but not described by the firmware are a
clearly different case to regulators that are not physically there,
hardware with actually optional regulators will generally require some
configuration for this case.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-16 13:33                                 ` Mark Brown
@ 2020-11-19 14:22                                   ` Dmitry Osipenko
  2020-11-19 15:19                                     ` Mark Brown
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-11-19 14:22 UTC (permalink / raw)
  To: Mark Brown
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

16.11.2020 16:33, Mark Brown пишет:
> On Sun, Nov 15, 2020 at 08:42:10PM +0300, Dmitry Osipenko wrote:
>> 13.11.2020 20:28, Mark Brown пишет:
> 
>>>> What should we do?
> 
>>> As I keep saying the consumer driver should be enumerating the voltages
>>> it can set, if it can't find any and wants to continue then it can just
>>> skip setting voltages later on.  If only some are unavailable then it
>>> probably wants to eliminate those specific OPPs instead.
> 
>> I'm seeing a dummy regulator as a helper for consumer drivers which
>> removes burden of handling an absent (optional) regulator. Is this a
>> correct understanding of a dummy regulator?
> 
>> Older DTBs don't have a regulator and we want to keep them working. This
>> is equal to a physically absent regulator and in this case it's an
>> optional regulator, IMO.
> 
> No, you are failing to understand the purpose of this code.  To
> reiterate unless the device supports operating with the supply
> physically absent then the driver should not be attempting to use
> regulator_get_optional().  That exists specifically for the case where
> the supply may be absent, nothing else.  The dummy regulator is there
> precisely for the case where the system does not describe supplies that
> we know are required for the device to function, it fixes up that
> omission so we don't need to open code handling of this in every single
> consumer driver.

The original intention of regulator_get_optional() is clear to me, but
nothing really stops drivers from slightly re-purposing this API, IMO.

Drivers should be free to assume that if regulator isn't defined by
firmware, then it's physically absent if this doesn't break anything. Of
course in some cases it's unsafe to make such assumptions. I think it's
a bit unpractical to artificially limit API usage without a good reason,
i.e. if nothing breaks underneath of a driver.

> Regulators that are present but not described by the firmware are a
> clearly different case to regulators that are not physically there,
> hardware with actually optional regulators will generally require some
> configuration for this case.
> 

I have good news. After spending some more time on trying out different
things, I found that my previous assumption about the fixed-regulator
was wrong, it actually accepts voltage changes, i.e. regulator consumer
doesn't get a error on a voltage-change. This is exactly what is needed
for the OPP core to work properly.

This means that there is no need to add special quirks to work around
absent regulators, we will just add a fixed regulator to the DTs which
don't specify a real regulator. The OPP core will perform voltage
checking and filter out unsupported OPPs. The older DTBs will continue
to work as well.

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

* Re: [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling
  2020-11-19 14:22                                   ` Dmitry Osipenko
@ 2020-11-19 15:19                                     ` Mark Brown
  0 siblings, 0 replies; 108+ messages in thread
From: Mark Brown @ 2020-11-19 15:19 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Alan Stern, Peter Chen,
	Liam Girdwood, Adrian Hunter, Krzysztof Kozlowski,
	Greg Kroah-Hartman, Lee Jones, Uwe Kleine-König,
	Ulf Hansson, Mauro Carvalho Chehab, Rob Herring,
	Marek Szyprowski, Peter Geis, Nicolas Chauvet, linux-samsung-soc,
	devel, linux-usb, linux-pwm, linux-mmc, linux-kernel, devicetree,
	dri-devel, linux-media, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 2026 bytes --]

On Thu, Nov 19, 2020 at 05:22:43PM +0300, Dmitry Osipenko wrote:
> 16.11.2020 16:33, Mark Brown пишет:

> > No, you are failing to understand the purpose of this code.  To
> > reiterate unless the device supports operating with the supply
> > physically absent then the driver should not be attempting to use
> > regulator_get_optional().  That exists specifically for the case where

> The original intention of regulator_get_optional() is clear to me, but
> nothing really stops drivers from slightly re-purposing this API, IMO.

> Drivers should be free to assume that if regulator isn't defined by
> firmware, then it's physically absent if this doesn't break anything. Of
> course in some cases it's unsafe to make such assumptions. I think it's
> a bit unpractical to artificially limit API usage without a good reason,
> i.e. if nothing breaks underneath of a driver.

If the supply can be physically absent without breaking anything then
this is the intended use case for optional regulators.  This is a *very*
uncommon.

> > Regulators that are present but not described by the firmware are a
> > clearly different case to regulators that are not physically there,
> > hardware with actually optional regulators will generally require some
> > configuration for this case.

> I have good news. After spending some more time on trying out different
> things, I found that my previous assumption about the fixed-regulator
> was wrong, it actually accepts voltage changes, i.e. regulator consumer
> doesn't get a error on a voltage-change. This is exactly what is needed
> for the OPP core to work properly.

To be clear when you set a voltage range you will get the minimum
voltage that can be supported within that range on the system given all
the other constraints the system has.  For fixed voltage regulators or
regulators constraints to not change voltage this means that if whatever
voltage they are fixed at is in the range requested then the API will
report success.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
       [not found] ` <160683107675.35139.13466076210885462180.b4-ty@kernel.org>
@ 2020-12-01 14:17   ` Dmitry Osipenko
  2020-12-01 14:34     ` Mark Brown
  0 siblings, 1 reply; 108+ messages in thread
From: Dmitry Osipenko @ 2020-12-01 14:17 UTC (permalink / raw)
  To: Mark Brown, Liam Girdwood, Krzysztof Kozlowski, Peter Chen,
	Jonathan Hunter, Uwe Kleine-König, Ulf Hansson, Rob Herring,
	Greg Kroah-Hartman, Alan Stern, Adrian Hunter, Peter Geis,
	Marek Szyprowski, Nicolas Chauvet, Mauro Carvalho Chehab,
	Lee Jones, Thierry Reding
  Cc: linux-mmc, devel, devicetree, linux-tegra, linux-pwm,
	linux-kernel, linux-samsung-soc, linux-usb, dri-devel,
	linux-media

01.12.2020 16:57, Mark Brown пишет:
> On Thu, 5 Nov 2020 02:43:57 +0300, Dmitry Osipenko wrote:
>> Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs, which reduces
>> power consumption and heating of the Tegra chips. Tegra SoC has multiple
>> hardware units which belong to a core power domain of the SoC and share
>> the core voltage. The voltage must be selected in accordance to a minimum
>> requirement of every core hardware unit.
>>
>> The minimum core voltage requirement depends on:
>>
>> [...]
> 
> Applied to
> 
>    https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
> 
> Thanks!
> 
> [1/1] regulator: Allow skipping disabled regulators in regulator_check_consumers()
>       (no commit info)
> 
> All being well this means that it will be integrated into the linux-next
> tree (usually sometime in the next 24 hours) and sent to Linus during
> the next merge window (or sooner if it is a bug fix), however if
> problems are discovered then the patch may be dropped or reverted.
> 
> You may get further e-mails resulting from automated or manual testing
> and review of the tree, please engage with people reporting problems and
> send followup patches addressing any issues that are reported if needed.
> 
> If any updates are required or you are submitting further changes they
> should be sent as incremental updates against current git, existing
> patches will not be replaced.
> 
> Please add any relevant lists and maintainers to the CCs when replying
> to this mail.

Hello Mark,

Could you please hold on this patch? It won't be needed in a v2, which
will use power domains.

Also, I'm not sure whether the "sound" tree is suitable for any of the
patches in this series.

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-12-01 14:17   ` Dmitry Osipenko
@ 2020-12-01 14:34     ` Mark Brown
  2020-12-01 14:44       ` Dmitry Osipenko
  0 siblings, 1 reply; 108+ messages in thread
From: Mark Brown @ 2020-12-01 14:34 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Liam Girdwood, Krzysztof Kozlowski, Peter Chen, Jonathan Hunter,
	Uwe Kleine-König, Ulf Hansson, Rob Herring,
	Greg Kroah-Hartman, Alan Stern, Adrian Hunter, Peter Geis,
	Marek Szyprowski, Nicolas Chauvet, Mauro Carvalho Chehab,
	Lee Jones, Thierry Reding, linux-mmc, devel, devicetree,
	linux-tegra, linux-pwm, linux-kernel, linux-samsung-soc,
	linux-usb, dri-devel, linux-media

[-- Attachment #1: Type: text/plain, Size: 631 bytes --]

On Tue, Dec 01, 2020 at 05:17:20PM +0300, Dmitry Osipenko wrote:
> 01.12.2020 16:57, Mark Brown пишет:

> > [1/1] regulator: Allow skipping disabled regulators in regulator_check_consumers()
> >       (no commit info)

> Could you please hold on this patch? It won't be needed in a v2, which
> will use power domains.

> Also, I'm not sure whether the "sound" tree is suitable for any of the
> patches in this series.

It didn't actually get applied (note the "no commit info") - it looks
like b4's matching code got confused and decided to generate mails for
anything that I've ever downloaded and not posted.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs
  2020-12-01 14:34     ` Mark Brown
@ 2020-12-01 14:44       ` Dmitry Osipenko
  0 siblings, 0 replies; 108+ messages in thread
From: Dmitry Osipenko @ 2020-12-01 14:44 UTC (permalink / raw)
  To: Mark Brown
  Cc: Liam Girdwood, Krzysztof Kozlowski, Peter Chen, Jonathan Hunter,
	Uwe Kleine-König, Ulf Hansson, Rob Herring,
	Greg Kroah-Hartman, Alan Stern, Adrian Hunter, Peter Geis,
	Marek Szyprowski, Nicolas Chauvet, Mauro Carvalho Chehab,
	Lee Jones, Thierry Reding, linux-mmc, devel, devicetree,
	linux-tegra, linux-pwm, linux-kernel, linux-samsung-soc,
	linux-usb, dri-devel, linux-media

01.12.2020 17:34, Mark Brown пишет:
> On Tue, Dec 01, 2020 at 05:17:20PM +0300, Dmitry Osipenko wrote:
>> 01.12.2020 16:57, Mark Brown пишет:
> 
>>> [1/1] regulator: Allow skipping disabled regulators in regulator_check_consumers()
>>>       (no commit info)
> 
>> Could you please hold on this patch? It won't be needed in a v2, which
>> will use power domains.
> 
>> Also, I'm not sure whether the "sound" tree is suitable for any of the
>> patches in this series.
> 
> It didn't actually get applied (note the "no commit info") - it looks
> like b4's matching code got confused and decided to generate mails for
> anything that I've ever downloaded and not posted.
> 

Alright, thank you for the clarification.

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

* Re: [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and core voltage scaling
  2020-11-09 11:20                           ` Frank Lee
@ 2020-12-22  8:54                             ` Viresh Kumar
  0 siblings, 0 replies; 108+ messages in thread
From: Viresh Kumar @ 2020-12-22  8:54 UTC (permalink / raw)
  To: Frank Lee
  Cc: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Alan Stern,
	Peter Chen, Mark Brown, Liam Girdwood, Adrian Hunter,
	Krzysztof Kozlowski, Greg Kroah-Hartman, Lee Jones,
	Uwe Kleine-König, Ulf Hansson, Mauro Carvalho Chehab,
	Rob Herring, Marek Szyprowski, Peter Geis, Nicolas Chauvet,
	driver-dev, linux-pwm, linux-samsung-soc, DTML,
	open list:ULTRA-WIDEBAND (UWB) SUBSYSTEM:,
	open list:SECURE DIGITAL HO...,
	Linux Kernel Mailing List, dri-devel, linux-tegra, linux-media

On Mon, 9 Nov 2020 at 16:51, Frank Lee <tiny.windzz@gmail.com> wrote:
> On Mon, Nov 9, 2020 at 1:53 PM Viresh Kumar <viresh.kumar@linaro.org> wrote:

> > > devm_pm_opp_set_supported_hw()
> > > devm_pm_opp_set_regulators() [if we won't use GENPD]
> > > devm_pm_opp_set_clkname()
> > > devm_pm_opp_of_add_table()
> >
> > I tried to look earlier for the stuff already merged in and didn't
> > find a lot of stuff where the devm_* could be used, maybe I missed
> > some of it.
> >
> > Frank, would you like to refresh your series based on suggestions from
> > Dmitry and make other drivers adapt to the new APIs ?
>
> I am glad to do this.:)

Frank,

Dmitry has submitted a series with a patch that does stuff like this since you
never resent your patches.

http://lore.kernel.org/lkml/20201217180638.22748-14-digetx@gmail.com

Since you were the first one to get to this, I would still like to
give you a chance
to get these patches merged under your authorship, otherwise I would be going
to pick patches from Dmitry.

--
viresh

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

end of thread, other threads:[~2020-12-22  8:56 UTC | newest]

Thread overview: 108+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-04 23:43 [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Dmitry Osipenko
2020-11-04 23:43 ` [PATCH v1 01/30] dt-bindings: host1x: Document OPP and voltage regulator properties Dmitry Osipenko
2020-11-09 18:57   ` Rob Herring
2020-11-11 11:45   ` Ulf Hansson
2020-11-04 23:43 ` [PATCH v1 02/30] dt-bindings: mmc: tegra: " Dmitry Osipenko
2020-11-09 18:58   ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 03/30] dt-bindings: pwm: " Dmitry Osipenko
2020-11-09 19:00   ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 04/30] media: dt: bindings: tegra-vde: " Dmitry Osipenko
2020-11-09 19:01   ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 05/30] dt-binding: usb: ci-hdrc-usb2: " Dmitry Osipenko
2020-11-09 19:01   ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 06/30] dt-bindings: usb: tegra-ehci: " Dmitry Osipenko
2020-11-09 19:01   ` Rob Herring
2020-11-04 23:44 ` [PATCH v1 07/30] soc/tegra: Add sync state API Dmitry Osipenko
2020-11-10 20:47   ` Thierry Reding
2020-11-10 21:22     ` Dmitry Osipenko
2020-11-10 21:32       ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 08/30] soc/tegra: regulators: Support Tegra SoC device " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 09/30] soc/tegra: regulators: Fix lockup when voltage-spread is out of range Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 10/30] regulator: Allow skipping disabled regulators in regulator_check_consumers() Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 11/30] drm/tegra: dc: Support OPP and SoC core voltage scaling Dmitry Osipenko
2020-11-10 20:29   ` Thierry Reding
2020-11-10 20:32     ` Mark Brown
2020-11-10 21:23       ` Dmitry Osipenko
2020-11-11 11:55         ` Mark Brown
2020-11-12 16:59           ` Dmitry Osipenko
2020-11-12 17:16             ` Mark Brown
2020-11-12 19:16               ` Dmitry Osipenko
2020-11-12 20:01                 ` Mark Brown
2020-11-12 22:37                   ` Dmitry Osipenko
2020-11-13 14:29                     ` Mark Brown
2020-11-13 15:55                       ` Dmitry Osipenko
2020-11-13 16:15                         ` Mark Brown
2020-11-13 17:13                           ` Dmitry Osipenko
2020-11-13 17:28                             ` Mark Brown
2020-11-15 17:42                               ` Dmitry Osipenko
2020-11-16 13:33                                 ` Mark Brown
2020-11-19 14:22                                   ` Dmitry Osipenko
2020-11-19 15:19                                     ` Mark Brown
2020-11-13 17:30                             ` Thierry Reding
2020-11-10 21:17     ` Dmitry Osipenko
2020-11-10 21:50     ` Dmitry Osipenko
2020-11-11  9:28     ` Dan Carpenter
2020-11-04 23:44 ` [PATCH v1 12/30] drm/tegra: gr2d: Correct swapped device-tree compatibles Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 13/30] drm/tegra: gr2d: Support OPP and SoC core voltage scaling Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 14/30] drm/tegra: gr3d: " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 15/30] drm/tegra: hdmi: " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 16/30] gpu: host1x: " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 17/30] mmc: sdhci-tegra: Support OPP and " Dmitry Osipenko
2020-11-05  9:58   ` Viresh Kumar
2020-11-05 14:18     ` Dmitry Osipenko
2020-11-06  6:15       ` Viresh Kumar
2020-11-06 13:17         ` Dmitry Osipenko
2020-11-06 13:41           ` Frank Lee
2020-11-09  5:00             ` Viresh Kumar
2020-11-09  5:08               ` Dmitry Osipenko
2020-11-09  5:10                 ` Viresh Kumar
2020-11-09  5:19                   ` Dmitry Osipenko
2020-11-09  5:35                     ` Viresh Kumar
2020-11-09  5:44                       ` Dmitry Osipenko
2020-11-09  5:53                         ` Viresh Kumar
2020-11-09 11:20                           ` Frank Lee
2020-12-22  8:54                             ` Viresh Kumar
2020-11-04 23:44 ` [PATCH v1 18/30] pwm: tegra: " Dmitry Osipenko
2020-11-10 20:50   ` Thierry Reding
2020-11-10 21:17     ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 19/30] media: staging: tegra-vde: Support OPP and SoC " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 20/30] usb: chipidea: tegra: " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 21/30] usb: host: ehci-tegra: " Dmitry Osipenko
2020-11-05 16:07   ` Alan Stern
2020-11-05 17:54     ` Dmitry Osipenko
2020-11-05 18:02     ` Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 22/30] memory: tegra20-emc: Support Tegra SoC device state syncing Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 23/30] memory: tegra30-emc: " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 24/30] ARM: tegra: Add OPP tables for Tegra20 peripheral devices Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 25/30] ARM: tegra: Add OPP tables for Tegra30 " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 26/30] ARM: tegra: ventana: Add voltage supplies to DVFS-capable devices Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 27/30] ARM: tegra: paz00: " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 28/30] ARM: tegra: acer-a500: " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 29/30] ARM: tegra: cardhu-a04: " Dmitry Osipenko
2020-11-04 23:44 ` [PATCH v1 30/30] ARM: tegra: nexus7: " Dmitry Osipenko
2020-11-05  1:45 ` [PATCH v1 00/30] Introduce core voltage scaling for NVIDIA Tegra20/30 SoCs Michał Mirosław
2020-11-05 13:57   ` Dmitry Osipenko
2020-11-05  9:45 ` Ulf Hansson
2020-11-05 10:06   ` Viresh Kumar
2020-11-05 10:34     ` Ulf Hansson
2020-11-05 10:40       ` Viresh Kumar
2020-11-05 10:56         ` Ulf Hansson
2020-11-05 11:13           ` Viresh Kumar
2020-11-05 12:52             ` Ulf Hansson
2020-11-05 15:22   ` Dmitry Osipenko
2020-11-08 12:19     ` Dmitry Osipenko
2020-11-09  4:43       ` Viresh Kumar
2020-11-09  4:47         ` Dmitry Osipenko
2020-11-09  5:10           ` Dmitry Osipenko
2020-11-09  5:12             ` Viresh Kumar
2020-11-11 11:38       ` Ulf Hansson
2020-11-12 19:57         ` Dmitry Osipenko
2020-11-12 20:43           ` Thierry Reding
2020-11-12 22:14             ` Dmitry Osipenko
2020-11-13 14:45               ` Ulf Hansson
2020-11-13 16:00                 ` Dmitry Osipenko
2020-11-13 16:35               ` Thierry Reding
2020-11-15 16:29                 ` Dmitry Osipenko
     [not found] ` <160683107675.35139.13466076210885462180.b4-ty@kernel.org>
2020-12-01 14:17   ` Dmitry Osipenko
2020-12-01 14:34     ` Mark Brown
2020-12-01 14:44       ` 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).