linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v9 00/22] SC7 entry and exit support for Tegra210
@ 2019-08-16 19:41 Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 01/22] pinctrl: tegra: Fix write barrier placement in pmx_writel Sowjanya Komatineni
                   ` (21 more replies)
  0 siblings, 22 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch series includes Tegra210 deepsleep (SC7) support with RTC alarm
wake event.

This series also includes save and restore of PLLs, clocks, OSC contexts
for deepsleep exit to normal operation.

This patch series doesn't support 100% suspend/resume to allow fully
functional state upon resume and we are working on some more drivers suspend
and resume implementations.

[V9]: Changed betweenv8 & v9 are
	- v8 feedback fixes

	Note:
	  Below patch is also needed for SC7 support as GPIO restore need
	  to happen prior to pinctrl.
	  https://patchwork.kernel.org/patch/11012077/

[v8]: Changes between v7 & v8 are
	- v7 feedback fixes
	- moved clock enable/disable state and reset enable/disable state
	  restore from clk_save/restore_context back to clk-tegra210 driver
	  to do complete register value store/restore.
	- Removed manual store/restore of peripheral parent context and added
	  API in clk core to retrieve clock parent index to use during
	  restoring parent on resume.
	- Implemented Tegra recommended clock source programming sequence
	  during restore (CLK ENB ON followed by divider/source programming
	  followed by restoring CLK ENB ON/OFF state followed by restoring
	  RST state).
	- Removed pinctrl suspend/resume patch from this series as pinctrl
	  suspend/resume patch from v7 got acked and merged.
	- Added pinctrl patch-0001 to update pmx_writel for proper placement
	  of write barrier.
	- Added pinctrl patch-0002 to insert write barrier after all pinctrl
	  register writes during pinctrl resume.

	Note:
	  Below patch is also needed for SC7 support as GPIO restore need
	  to happen prior to pinctrl.
	  https://patchwork.kernel.org/patch/11012077/

[v7]: Changes between V6 & v7 are
	- V6 feedback fixes
	- Removed patch-0001 from V6 which keeps COP IRQ enabled. Looking
	  more into ATF FW, it loads SC7 entry FW into IRAM and sets the
	  COP reset vector to SC7 FW load address and resets COP. So, COP
	  IRQ can be cleared during suspend.

	Note:
	  Below patch is also needed for SC7 support as GPIO restore need
	  to happen prior to pinctrl.
	  https://patchwork.kernel.org/patch/11012077/

[V6]: Changes between V5 & V6 are
	- V5 feedback fixes
	- DFLL suspend and resume moved to DFLL clock driver
	- Add suspend and resume support for CPUFreq driver to explicitly
	  switch source to safe source of PLLP and disable DFLL clock.
	- Fix to super clock driver to enable PLLP branch to CPU before
	  source switch to PLLP.
	- Added save and restore support for super clock driver.

[V5]: Changes between V4 & V5 are
	- V4 feedback fixes

[V4]: Changes between V3 & V4 are
	- V3 feedback fixes
	- Removed park bits clear for EMMC pads in pinctrl-tegra driver
	  function tegra_pinctrl_clear_parked_bits as based on V3 feedback
	  parked_bit is updated to parked_bitmask to use with DRV_PINGROUP
	  as well and thierry posted patch series for this.
	- Implemented all peripheral clocks save and restore through their
	  corresponding clk_ops save_context and restore_context and removed
	  all direct registers store and restore in clk-tegra210 driver.
	- Created separate patch for fence_delay update during PLLU init based
	  on V3 feedback.
	- Added more comments in tegra210_clk_resume regarding dfll restore
	  sequence and its dependency on peripheral clocks restore.

[V3]: Changes between V2 & V3 are
	- V2 feedback fixes
	- GPIO restore should happen prior to Pinctrl restore to prevent
	  glitch on GPIO lines. So using resume_noirq for gpio tegra to allow
	  gpio resume prior to pinctrl resume.
	- Implemented save_context and restore_context callbacks for clock
	  plls, pll outs and dividers in corresponding drivers.
	  Note: Peripheral clocks and clock enable and reset need to be in
	  Tegra210 clock suspend/resume as they need to be in proper sequence
	  w.r.t DFLL resume for restoring CPU clock.
	- Removed gpio-tegra changes for hierarchical support to have PMC as
	  parent to GPIOs for GPIO wake event support. Thierry is working on
	  gpiolib for some cleanup before adding hierarchical support. So
	  holding on to GPIO wake support for now.

[V2] : V1 feedback fixes
	Patch 0002: This version still using syscore. Thierry suggest not to
	use syscore and waiting on suggestion from Linux Walleij for any better
	way of storing current state of pins before suspend entry and restoring
	them on resume at very early stage. So left this the same way as V1 and
	will address once I get more feedback on this.
	Also need to findout and implement proper way of forcing resume order
	between pinctrl and gpio driver.

[V1]:	Tegra210 SC7 entry and exit thru RTC wake and Power button GPIO wake
	using hierarchical IRQ with PMC as parent to GPIO.


Sowjanya Komatineni (22):
  pinctrl: tegra: Fix write barrier placement in pmx_writel
  pinctrl: tegra: Flush pinctrl writes during resume
  clk: tegra: divider: Save and restore divider rate
  clk: tegra: pllout: Save and restore pllout context
  clk: tegra: pll: Save and restore pll context
  clk: tegra: Support for OSC context save and restore
  clk: Add API to get index of the clock parent
  clk: tegra: periph: Add restore_context support
  clk: tegra: clk-super: Fix to enable PLLP branches to CPU
  clk: tegra: clk-super: Add restore-context support
  clk: tegra: clk-dfll: Add suspend and resume support
  cpufreq: tegra124: Add suspend and resume support
  clk: tegra210: Use fence_udelay during PLLU init
  clk: tegra: Share clk and rst register defines with Tegra clock driver
  clk: tegra210: Add suspend and resume support
  soc/tegra: pmc: Allow to support more tegras wake
  soc/tegra: pmc: Add pmc wake support for tegra210
  arm64: tegra: Enable wake from deep sleep on RTC alarm
  soc/tegra: pmc: Configure core power request polarity
  soc/tegra: pmc: Configure deep sleep control settings
  arm64: dts: tegra210-p2180: Jetson TX1 SC7 timings
  arm64: dts: tegra210-p3450: Jetson Nano SC7 timings

 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi     |   7 ++
 arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts |   7 ++
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |   5 +-
 drivers/clk/clk.c                                  |  17 +++
 drivers/clk/tegra/clk-dfll.c                       |  56 +++++++++
 drivers/clk/tegra/clk-dfll.h                       |   2 +
 drivers/clk/tegra/clk-divider.c                    |  11 ++
 drivers/clk/tegra/clk-periph.c                     |  18 +++
 drivers/clk/tegra/clk-pll-out.c                    |   9 ++
 drivers/clk/tegra/clk-pll.c                        |  86 +++++++++-----
 drivers/clk/tegra/clk-sdmmc-mux.c                  |  12 ++
 drivers/clk/tegra/clk-super.c                      |  35 ++++++
 drivers/clk/tegra/clk-tegra-fixed.c                |  15 +++
 drivers/clk/tegra/clk-tegra-super-gen4.c           |   7 +-
 drivers/clk/tegra/clk-tegra124-dfll-fcpu.c         |   1 +
 drivers/clk/tegra/clk-tegra210.c                   | 104 +++++++++++++++--
 drivers/clk/tegra/clk.c                            | 112 +++++++++++-------
 drivers/clk/tegra/clk.h                            |  67 +++++++++++
 drivers/cpufreq/tegra124-cpufreq.c                 |  59 ++++++++++
 drivers/pinctrl/tegra/pinctrl-tegra.c              |   8 +-
 drivers/soc/tegra/pmc.c                            | 130 ++++++++++++++++++++-
 include/linux/clk-provider.h                       |   1 +
 22 files changed, 677 insertions(+), 92 deletions(-)

-- 
2.7.4


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

* [PATCH v9 01/22] pinctrl: tegra: Fix write barrier placement in pmx_writel
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-18 22:20   ` Linus Walleij
  2019-08-16 19:41 ` [PATCH v9 02/22] pinctrl: tegra: Flush pinctrl writes during resume Sowjanya Komatineni
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

pmx_writel uses writel which inserts write barrier before the
register write.

This patch has fix to replace writel with writel_relaxed followed
by a readback and memory barrier to ensure write operation is
completed for successful pinctrl change.

Acked-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/pinctrl/tegra/pinctrl-tegra.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index e3a237534281..5e3c00137d71 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -32,7 +32,9 @@ static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg)
 
 static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
 {
-	writel(val, pmx->regs[bank] + reg);
+	writel_relaxed(val, pmx->regs[bank] + reg);
+	/* make sure pinmux register write completed */
+	pmx_readl(pmx, bank, reg);
 }
 
 static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
-- 
2.7.4


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

* [PATCH v9 02/22] pinctrl: tegra: Flush pinctrl writes during resume
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 01/22] pinctrl: tegra: Fix write barrier placement in pmx_writel Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-18 22:20   ` Linus Walleij
  2019-08-16 19:41 ` [PATCH v9 03/22] clk: tegra: divider: Save and restore divider rate Sowjanya Komatineni
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch adds pinctrl register read to flush all the prior pinctrl
writes and then adds barrier for pinctrl register read to complete
during resume to make sure all pinctrl changes are effective.

Acked-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/pinctrl/tegra/pinctrl-tegra.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index 5e3c00137d71..e9a7cbb9aa33 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -677,6 +677,10 @@ static int tegra_pinctrl_resume(struct device *dev)
 			writel_relaxed(*backup_regs++, regs++);
 	}
 
+	/* flush all the prior writes */
+	readl_relaxed(pmx->regs[0]);
+	/* wait for pinctrl register read to complete */
+	rmb();
 	return 0;
 }
 
-- 
2.7.4


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

* [PATCH v9 03/22] clk: tegra: divider: Save and restore divider rate
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 01/22] pinctrl: tegra: Fix write barrier placement in pmx_writel Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 02/22] pinctrl: tegra: Flush pinctrl writes during resume Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 04/22] clk: tegra: pllout: Save and restore pllout context Sowjanya Komatineni
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch implements context restore for clock divider.

During system suspend, core power goes off and looses the settings
of the Tegra CAR controller registers.

So on resume, clock dividers are restored back for normal operation.

Acked-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-divider.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
index e76731fb7d69..ca0de5f11f84 100644
--- a/drivers/clk/tegra/clk-divider.c
+++ b/drivers/clk/tegra/clk-divider.c
@@ -109,10 +109,21 @@ static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate,
 	return 0;
 }
 
+static void clk_divider_restore_context(struct clk_hw *hw)
+{
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	unsigned long parent_rate = clk_hw_get_rate(parent);
+	unsigned long rate = clk_hw_get_rate(hw);
+
+	if (clk_frac_div_set_rate(hw, rate, parent_rate) < 0)
+		WARN_ON(1);
+}
+
 const struct clk_ops tegra_clk_frac_div_ops = {
 	.recalc_rate = clk_frac_div_recalc_rate,
 	.set_rate = clk_frac_div_set_rate,
 	.round_rate = clk_frac_div_round_rate,
+	.restore_context = clk_divider_restore_context,
 };
 
 struct clk *tegra_clk_register_divider(const char *name,
-- 
2.7.4


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

* [PATCH v9 04/22] clk: tegra: pllout: Save and restore pllout context
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (2 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 03/22] clk: tegra: divider: Save and restore divider rate Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 05/22] clk: tegra: pll: Save and restore pll context Sowjanya Komatineni
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch implements save and restore of pllout context.

During system suspend, core power goes off and looses the settings
of the Tegra CAR controller registers.

So during suspend entry the state of pllout is saved and on resume
it is restored back to have pllout in same state as before suspend.

pllout rate is saved and restore in clock divider so it will be at
same rate as before suspend when pllout state is restored.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-pll-out.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/tegra/clk-pll-out.c b/drivers/clk/tegra/clk-pll-out.c
index 35f2bf00e1e6..d8bf89a81e6d 100644
--- a/drivers/clk/tegra/clk-pll-out.c
+++ b/drivers/clk/tegra/clk-pll-out.c
@@ -69,10 +69,19 @@ static void clk_pll_out_disable(struct clk_hw *hw)
 		spin_unlock_irqrestore(pll_out->lock, flags);
 }
 
+static void tegra_clk_pll_out_restore_context(struct clk_hw *hw)
+{
+	if (!__clk_get_enable_count(hw->clk))
+		clk_pll_out_disable(hw);
+	else
+		clk_pll_out_enable(hw);
+}
+
 const struct clk_ops tegra_clk_pll_out_ops = {
 	.is_enabled = clk_pll_out_is_enabled,
 	.enable = clk_pll_out_enable,
 	.disable = clk_pll_out_disable,
+	.restore_context = tegra_clk_pll_out_restore_context,
 };
 
 struct clk *tegra_clk_register_pll_out(const char *name,
-- 
2.7.4


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

* [PATCH v9 05/22] clk: tegra: pll: Save and restore pll context
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (3 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 04/22] clk: tegra: pllout: Save and restore pllout context Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 06/22] clk: tegra: Support for OSC context save and restore Sowjanya Komatineni
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch implements save and restore of PLL context.

During system suspend, core power goes off and looses the settings
of the Tegra CAR controller registers.

So during resume, pll context is restored based on cached rate
and state.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-pll.c | 86 ++++++++++++++++++++++++++++-----------------
 1 file changed, 54 insertions(+), 32 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 1583f5fc992f..531c2b3d814e 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -1008,6 +1008,27 @@ static unsigned long clk_plle_recalc_rate(struct clk_hw *hw,
 	return rate;
 }
 
+static void tegra_clk_pll_restore_context(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	unsigned long parent_rate = clk_hw_get_rate(parent);
+	unsigned long rate = clk_hw_get_rate(hw);
+
+	if (clk_pll_is_enabled(hw))
+		return;
+
+	if (pll->params->set_defaults)
+		pll->params->set_defaults(pll);
+
+	clk_pll_set_rate(hw, rate, parent_rate);
+
+	if (!__clk_get_enable_count(hw->clk))
+		clk_pll_disable(hw);
+	else
+		clk_pll_enable(hw);
+}
+
 const struct clk_ops tegra_clk_pll_ops = {
 	.is_enabled = clk_pll_is_enabled,
 	.enable = clk_pll_enable,
@@ -1015,6 +1036,7 @@ const struct clk_ops tegra_clk_pll_ops = {
 	.recalc_rate = clk_pll_recalc_rate,
 	.round_rate = clk_pll_round_rate,
 	.set_rate = clk_pll_set_rate,
+	.restore_context = tegra_clk_pll_restore_context,
 };
 
 const struct clk_ops tegra_clk_plle_ops = {
@@ -1802,6 +1824,27 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw)
 
 	return ret;
 }
+
+static void _clk_plle_tegra_init_parent(struct tegra_clk_pll *pll)
+{
+	u32 val, val_aux;
+
+	/* ensure parent is set to pll_ref */
+	val = pll_readl_base(pll);
+	val_aux = pll_readl(pll->params->aux_reg, pll);
+
+	if (val & PLL_BASE_ENABLE) {
+		if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
+		    (val_aux & PLLE_AUX_PLLP_SEL))
+			WARN(1, "pll_e enabled with unsupported parent %s\n",
+			     (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
+			     "pll_re_vco");
+	} else {
+		val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
+		pll_writel(val_aux, pll->params->aux_reg, pll);
+		fence_udelay(1, pll->clk_base);
+	}
+}
 #endif
 
 static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
@@ -2214,27 +2257,12 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
 {
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
-	u32 val, val_aux;
 
 	pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
 
-	/* ensure parent is set to pll_re_vco */
-
-	val = pll_readl_base(pll);
-	val_aux = pll_readl(pll_params->aux_reg, pll);
-
-	if (val & PLL_BASE_ENABLE) {
-		if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
-			(val_aux & PLLE_AUX_PLLP_SEL))
-			WARN(1, "pll_e enabled with unsupported parent %s\n",
-			  (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
-					"pll_re_vco");
-	} else {
-		val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
-		pll_writel(val_aux, pll_params->aux_reg, pll);
-	}
+	_clk_plle_tegra_init_parent(pll);
 
 	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
 				      &tegra_clk_plle_tegra114_ops);
@@ -2276,6 +2304,7 @@ static const struct clk_ops tegra_clk_pllss_ops = {
 	.recalc_rate = clk_pll_recalc_rate,
 	.round_rate = clk_pll_ramp_round_rate,
 	.set_rate = clk_pllxc_set_rate,
+	.restore_context = tegra_clk_pll_restore_context,
 };
 
 struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
@@ -2520,11 +2549,19 @@ static void clk_plle_tegra210_disable(struct clk_hw *hw)
 		spin_unlock_irqrestore(pll->lock, flags);
 }
 
+static void tegra_clk_plle_t210_restore_context(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+
+	_clk_plle_tegra_init_parent(pll);
+}
+
 static const struct clk_ops tegra_clk_plle_tegra210_ops = {
 	.is_enabled =  clk_plle_tegra210_is_enabled,
 	.enable = clk_plle_tegra210_enable,
 	.disable = clk_plle_tegra210_disable,
 	.recalc_rate = clk_pll_recalc_rate,
+	.restore_context = tegra_clk_plle_t210_restore_context,
 };
 
 struct clk *tegra_clk_register_plle_tegra210(const char *name,
@@ -2535,27 +2572,12 @@ struct clk *tegra_clk_register_plle_tegra210(const char *name,
 {
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
-	u32 val, val_aux;
 
 	pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
 
-	/* ensure parent is set to pll_re_vco */
-
-	val = pll_readl_base(pll);
-	val_aux = pll_readl(pll_params->aux_reg, pll);
-
-	if (val & PLLE_BASE_ENABLE) {
-		if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
-			(val_aux & PLLE_AUX_PLLP_SEL))
-			WARN(1, "pll_e enabled with unsupported parent %s\n",
-			  (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
-					"pll_re_vco");
-	} else {
-		val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
-		pll_writel(val_aux, pll_params->aux_reg, pll);
-	}
+	_clk_plle_tegra_init_parent(pll);
 
 	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
 				      &tegra_clk_plle_tegra210_ops);
-- 
2.7.4


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

* [PATCH v9 06/22] clk: tegra: Support for OSC context save and restore
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (4 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 05/22] clk: tegra: pll: Save and restore pll context Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 07/22] clk: Add API to get index of the clock parent Sowjanya Komatineni
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch adds support for saving OSC clock frequency and the
drive-strength during OSC clock init and creates an API to restore
OSC control register value from the saved context.

This API is invoked by Tegra210 clock driver during system resume
to restore the  OSC clock settings.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-tegra-fixed.c | 15 +++++++++++++++
 drivers/clk/tegra/clk.h             |  1 +
 2 files changed, 16 insertions(+)

diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c
index 8d91b2b191cf..7c6c8abfcde6 100644
--- a/drivers/clk/tegra/clk-tegra-fixed.c
+++ b/drivers/clk/tegra/clk-tegra-fixed.c
@@ -17,6 +17,10 @@
 #define OSC_CTRL			0x50
 #define OSC_CTRL_OSC_FREQ_SHIFT		28
 #define OSC_CTRL_PLL_REF_DIV_SHIFT	26
+#define OSC_CTRL_MASK			(0x3f2 |	\
+					(0xf << OSC_CTRL_OSC_FREQ_SHIFT))
+
+static u32 osc_ctrl_ctx;
 
 int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
 			      unsigned long *input_freqs, unsigned int num,
@@ -29,6 +33,7 @@ int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
 	unsigned osc_idx;
 
 	val = readl_relaxed(clk_base + OSC_CTRL);
+	osc_ctrl_ctx = val & OSC_CTRL_MASK;
 	osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;
 
 	if (osc_idx < num)
@@ -96,3 +101,13 @@ void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
 		*dt_clk = clk;
 	}
 }
+
+void tegra_clk_osc_resume(void __iomem *clk_base)
+{
+	u32 val;
+
+	val = readl_relaxed(clk_base + OSC_CTRL) & ~OSC_CTRL_MASK;
+	val |= osc_ctrl_ctx;
+	writel_relaxed(val, clk_base + OSC_CTRL);
+	fence_udelay(2, clk_base);
+}
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 905bf1096558..cbbca28bf7e4 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -829,6 +829,7 @@ u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate);
 int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div);
 int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
 		 u8 frac_width, u8 flags);
+void tegra_clk_osc_resume(void __iomem *clk_base);
 
 
 /* Combined read fence with delay */
-- 
2.7.4


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

* [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (5 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 06/22] clk: tegra: Support for OSC context save and restore Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-11-06 23:10   ` Stephen Boyd
  2019-08-16 19:41 ` [PATCH v9 08/22] clk: tegra: periph: Add restore_context support Sowjanya Komatineni
                   ` (14 subsequent siblings)
  21 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch adds an API clk_hw_get_parent_index to get index of the
clock parent to use during the clock restore operations on system
resume.

Reviewed-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/clk.c            | 17 +++++++++++++++++
 include/linux/clk-provider.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index cbcc333aec84..12ad0e9b8591 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1645,6 +1645,23 @@ static int clk_fetch_parent_index(struct clk_core *core,
 	return i;
 }
 
+/**
+ * clk_hw_get_parent_index - return the index of parent clock
+ * @hw: clk_hw associated with the clk being consumed
+ * @parent_hw: clk_hw associated with the parent of clk
+ *
+ * Fetches and returns the index of parent clock.
+ * If hw or parent_hw is NULL, returns -EINVAL.
+ */
+int clk_hw_get_parent_index(struct clk_hw *hw, struct clk_hw *parent_hw)
+{
+	if (!hw || !parent_hw)
+		return -EINVAL;
+
+	return clk_fetch_parent_index(hw->core, parent_hw->core);
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_parent_index);
+
 /*
  * Update the orphan status of @core and all its children.
  */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index dce5521a9bf6..cce830780900 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -817,6 +817,7 @@ unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
 struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
 struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
 					  unsigned int index);
+int clk_hw_get_parent_index(struct clk_hw *hw, struct clk_hw *parent_hw);
 int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *new_parent);
 unsigned int __clk_get_enable_count(struct clk *clk);
 unsigned long clk_hw_get_rate(const struct clk_hw *hw);
-- 
2.7.4


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

* [PATCH v9 08/22] clk: tegra: periph: Add restore_context support
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (6 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 07/22] clk: Add API to get index of the clock parent Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 09/22] clk: tegra: clk-super: Fix to enable PLLP branches to CPU Sowjanya Komatineni
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch implements restore_context support for clk-periph and
clk-sdmmc-mux clock operations to restore clock parent and rates
on system resume.

During system suspend, core power goes off and looses the context
of the Tegra clock controller registers.

So on system resume, clocks parent and rate are restored back to
the context before suspend based on cached data.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-periph.c    | 18 ++++++++++++++++++
 drivers/clk/tegra/clk-sdmmc-mux.c | 12 ++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 58437da25156..c9d28cbadccc 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/export.h>
 #include <linux/slab.h>
@@ -99,6 +100,20 @@ static void clk_periph_disable(struct clk_hw *hw)
 	gate_ops->disable(gate_hw);
 }
 
+static void clk_periph_restore_context(struct clk_hw *hw)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *div_ops = periph->div_ops;
+	struct clk_hw *div_hw = &periph->divider.hw;
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	int parent_id = clk_hw_get_parent_index(hw, parent);
+
+	if (!(periph->gate.flags & TEGRA_PERIPH_NO_DIV))
+		div_ops->restore_context(div_hw);
+
+	clk_periph_set_parent(hw, parent_id);
+}
+
 const struct clk_ops tegra_clk_periph_ops = {
 	.get_parent = clk_periph_get_parent,
 	.set_parent = clk_periph_set_parent,
@@ -108,6 +123,7 @@ const struct clk_ops tegra_clk_periph_ops = {
 	.is_enabled = clk_periph_is_enabled,
 	.enable = clk_periph_enable,
 	.disable = clk_periph_disable,
+	.restore_context = clk_periph_restore_context,
 };
 
 static const struct clk_ops tegra_clk_periph_nodiv_ops = {
@@ -116,6 +132,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = {
 	.is_enabled = clk_periph_is_enabled,
 	.enable = clk_periph_enable,
 	.disable = clk_periph_disable,
+	.restore_context = clk_periph_restore_context,
 };
 
 static const struct clk_ops tegra_clk_periph_no_gate_ops = {
@@ -124,6 +141,7 @@ static const struct clk_ops tegra_clk_periph_no_gate_ops = {
 	.recalc_rate = clk_periph_recalc_rate,
 	.round_rate = clk_periph_round_rate,
 	.set_rate = clk_periph_set_rate,
+	.restore_context = clk_periph_restore_context,
 };
 
 static struct clk *_tegra_clk_register_periph(const char *name,
diff --git a/drivers/clk/tegra/clk-sdmmc-mux.c b/drivers/clk/tegra/clk-sdmmc-mux.c
index a5cd3e31dbae..8db48966b100 100644
--- a/drivers/clk/tegra/clk-sdmmc-mux.c
+++ b/drivers/clk/tegra/clk-sdmmc-mux.c
@@ -194,6 +194,17 @@ static void clk_sdmmc_mux_disable(struct clk_hw *hw)
 	gate_ops->disable(gate_hw);
 }
 
+static void clk_sdmmc_mux_restore_context(struct clk_hw *hw)
+{
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	unsigned long parent_rate = clk_hw_get_rate(parent);
+	unsigned long rate = clk_hw_get_rate(hw);
+	int parent_id = clk_hw_get_parent_index(hw, parent);
+
+	clk_sdmmc_mux_set_parent(hw, parent_id);
+	clk_sdmmc_mux_set_rate(hw, rate, parent_rate);
+}
+
 static const struct clk_ops tegra_clk_sdmmc_mux_ops = {
 	.get_parent = clk_sdmmc_mux_get_parent,
 	.set_parent = clk_sdmmc_mux_set_parent,
@@ -203,6 +214,7 @@ static const struct clk_ops tegra_clk_sdmmc_mux_ops = {
 	.is_enabled = clk_sdmmc_mux_is_enabled,
 	.enable = clk_sdmmc_mux_enable,
 	.disable = clk_sdmmc_mux_disable,
+	.restore_context = clk_sdmmc_mux_restore_context,
 };
 
 struct clk *tegra_clk_register_sdmmc_mux_div(const char *name,
-- 
2.7.4


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

* [PATCH v9 09/22] clk: tegra: clk-super: Fix to enable PLLP branches to CPU
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (7 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 08/22] clk: tegra: periph: Add restore_context support Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 10/22] clk: tegra: clk-super: Add restore-context support Sowjanya Komatineni
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch has a fix to enable PLLP branches to CPU before changing
the CPU cluster clock source to PLLP for Gen5 Super clock and
disables PLLP branches to CPU when not in use.

During system suspend entry and exit, CPU source will be switched
to PLLP and this needs PLLP branches to be enabled to CPU prior to
the switch.

On system resume, warmboot code enables PLLP branches to CPU and
powers up the CPU with PLLP clock source.

Acked-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-super.c            | 14 ++++++++++++++
 drivers/clk/tegra/clk-tegra-super-gen4.c |  7 ++++++-
 drivers/clk/tegra/clk.c                  | 14 ++++++++++++++
 drivers/clk/tegra/clk.h                  |  5 +++++
 4 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
index 39ef31b46df5..e2a1e95a8db7 100644
--- a/drivers/clk/tegra/clk-super.c
+++ b/drivers/clk/tegra/clk-super.c
@@ -28,6 +28,9 @@
 #define super_state_to_src_shift(m, s) ((m->width * s))
 #define super_state_to_src_mask(m) (((1 << m->width) - 1))
 
+#define CCLK_SRC_PLLP_OUT0 4
+#define CCLK_SRC_PLLP_OUT4 5
+
 static u8 clk_super_get_parent(struct clk_hw *hw)
 {
 	struct tegra_clk_super_mux *mux = to_clk_super_mux(hw);
@@ -97,12 +100,23 @@ static int clk_super_set_parent(struct clk_hw *hw, u8 index)
 		if (index == mux->div2_index)
 			index = mux->pllx_index;
 	}
+
+	/* enable PLLP branches to CPU before selecting PLLP source */
+	if ((mux->flags & TEGRA210_CPU_CLK) &&
+	    (index == CCLK_SRC_PLLP_OUT0 || index == CCLK_SRC_PLLP_OUT4))
+		tegra_clk_set_pllp_out_cpu(true);
+
 	val &= ~((super_state_to_src_mask(mux)) << shift);
 	val |= (index & (super_state_to_src_mask(mux))) << shift;
 
 	writel_relaxed(val, mux->reg);
 	udelay(2);
 
+	/* disable PLLP branches to CPU if not used */
+	if ((mux->flags & TEGRA210_CPU_CLK) &&
+	    index != CCLK_SRC_PLLP_OUT0 && index != CCLK_SRC_PLLP_OUT4)
+		tegra_clk_set_pllp_out_cpu(false);
+
 out:
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c
index cdfe7c9697e1..5760c978bef7 100644
--- a/drivers/clk/tegra/clk-tegra-super-gen4.c
+++ b/drivers/clk/tegra/clk-tegra-super-gen4.c
@@ -180,7 +180,7 @@ static void __init tegra_super_clk_init(void __iomem *clk_base,
 					gen_info->num_cclk_g_parents,
 					CLK_SET_RATE_PARENT,
 					clk_base + CCLKG_BURST_POLICY,
-					0, 4, 8, 0, NULL);
+					TEGRA210_CPU_CLK, 4, 8, 0, NULL);
 		} else {
 			clk = tegra_clk_register_super_mux("cclk_g",
 					gen_info->cclk_g_parents,
@@ -196,6 +196,11 @@ static void __init tegra_super_clk_init(void __iomem *clk_base,
 	dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks);
 	if (dt_clk) {
 		if (gen_info->gen == gen5) {
+			/*
+			 * TEGRA210_CPU_CLK flag is not needed for cclk_lp as
+			 * cluster switching is not currently supported on
+			 * Tegra210 and also cpu_lp is not used.
+			 */
 			clk = tegra_clk_register_super_mux("cclk_lp",
 					gen_info->cclk_lp_parents,
 					gen_info->num_cclk_lp_parents,
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 573e3c967ae1..eb08047fd02f 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -23,6 +23,7 @@
 #define CLK_OUT_ENB_W			0x364
 #define CLK_OUT_ENB_X			0x280
 #define CLK_OUT_ENB_Y			0x298
+#define CLK_ENB_PLLP_OUT_CPU		BIT(31)
 #define CLK_OUT_ENB_SET_L		0x320
 #define CLK_OUT_ENB_CLR_L		0x324
 #define CLK_OUT_ENB_SET_H		0x328
@@ -199,6 +200,19 @@ const struct tegra_clk_periph_regs *get_reg_bank(int clkid)
 	}
 }
 
+void tegra_clk_set_pllp_out_cpu(bool enable)
+{
+	u32 val;
+
+	val = readl_relaxed(clk_base + CLK_OUT_ENB_Y);
+	if (enable)
+		val |= CLK_ENB_PLLP_OUT_CPU;
+	else
+		val &= ~CLK_ENB_PLLP_OUT_CPU;
+
+	writel_relaxed(val, clk_base + CLK_OUT_ENB_Y);
+}
+
 struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
 {
 	clk_base = regs;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index cbbca28bf7e4..55c4b78280be 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -669,6 +669,9 @@ struct clk *tegra_clk_register_periph_data(void __iomem *clk_base,
  * Flags:
  * TEGRA_DIVIDER_2 - LP cluster has additional divider. This flag indicates
  *     that this is LP cluster clock.
+ * TEGRA210_CPU_CLK - This flag is used to identify CPU cluster for gen5
+ * super mux parent using PLLP branches. To use PLLP branches to CPU, need
+ * to configure additional bit PLLP_OUT_CPU in the clock registers.
  */
 struct tegra_clk_super_mux {
 	struct clk_hw	hw;
@@ -685,6 +688,7 @@ struct tegra_clk_super_mux {
 #define to_clk_super_mux(_hw) container_of(_hw, struct tegra_clk_super_mux, hw)
 
 #define TEGRA_DIVIDER_2 BIT(0)
+#define TEGRA210_CPU_CLK BIT(1)
 
 extern const struct clk_ops tegra_clk_super_ops;
 struct clk *tegra_clk_register_super_mux(const char *name,
@@ -830,6 +834,7 @@ int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div);
 int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
 		 u8 frac_width, u8 flags);
 void tegra_clk_osc_resume(void __iomem *clk_base);
+void tegra_clk_set_pllp_out_cpu(bool enable);
 
 
 /* Combined read fence with delay */
-- 
2.7.4


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

* [PATCH v9 10/22] clk: tegra: clk-super: Add restore-context support
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (8 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 09/22] clk: tegra: clk-super: Fix to enable PLLP branches to CPU Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 11/22] clk: tegra: clk-dfll: Add suspend and resume support Sowjanya Komatineni
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch implements restore_context for clk_super_mux and clk_super.

During system supend, core power goes off the and context of Tegra
CAR registers is lost.

So on system resume, context of super clock registers are restored
to have them in same state as before suspend.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-super.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
index e2a1e95a8db7..74c9e913e41c 100644
--- a/drivers/clk/tegra/clk-super.c
+++ b/drivers/clk/tegra/clk-super.c
@@ -124,9 +124,18 @@ static int clk_super_set_parent(struct clk_hw *hw, u8 index)
 	return err;
 }
 
+static void clk_super_mux_restore_context(struct clk_hw *hw)
+{
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	int parent_id = clk_hw_get_parent_index(hw, parent);
+
+	clk_super_set_parent(hw, parent_id);
+}
+
 static const struct clk_ops tegra_clk_super_mux_ops = {
 	.get_parent = clk_super_get_parent,
 	.set_parent = clk_super_set_parent,
+	.restore_context = clk_super_mux_restore_context,
 };
 
 static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -162,12 +171,24 @@ static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate,
 	return super->div_ops->set_rate(div_hw, rate, parent_rate);
 }
 
+static void clk_super_restore_context(struct clk_hw *hw)
+{
+	struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
+	struct clk_hw *div_hw = &super->frac_div.hw;
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	int parent_id = clk_hw_get_parent_index(hw, parent);
+
+	super->div_ops->restore_context(div_hw);
+	clk_super_set_parent(hw, parent_id);
+}
+
 const struct clk_ops tegra_clk_super_ops = {
 	.get_parent = clk_super_get_parent,
 	.set_parent = clk_super_set_parent,
 	.set_rate = clk_super_set_rate,
 	.round_rate = clk_super_round_rate,
 	.recalc_rate = clk_super_recalc_rate,
+	.restore_context = clk_super_restore_context,
 };
 
 struct clk *tegra_clk_register_super_mux(const char *name,
-- 
2.7.4


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

* [PATCH v9 11/22] clk: tegra: clk-dfll: Add suspend and resume support
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (9 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 10/22] clk: tegra: clk-super: Add restore-context support Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-11-08 21:20   ` Stephen Boyd
  2019-08-16 19:41 ` [PATCH v9 12/22] cpufreq: tegra124: " Sowjanya Komatineni
                   ` (10 subsequent siblings)
  21 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch implements DFLL suspend and resume operation.

During system suspend entry, CPU clock will switch CPU to safe
clock source of PLLP and disables DFLL clock output.

DFLL driver suspend confirms DFLL disable state and errors out on
being active.

DFLL is re-initialized during the DFLL driver resume as it goes
through complete reset during suspend entry.

Acked-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-dfll.c               | 56 ++++++++++++++++++++++++++++++
 drivers/clk/tegra/clk-dfll.h               |  2 ++
 drivers/clk/tegra/clk-tegra124-dfll-fcpu.c |  1 +
 3 files changed, 59 insertions(+)

diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
index f8688c2ddf1a..c051d92c2bbf 100644
--- a/drivers/clk/tegra/clk-dfll.c
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -1487,6 +1487,7 @@ static int dfll_init(struct tegra_dfll *td)
 	td->last_unrounded_rate = 0;
 
 	pm_runtime_enable(td->dev);
+	pm_runtime_irq_safe(td->dev);
 	pm_runtime_get_sync(td->dev);
 
 	dfll_set_mode(td, DFLL_DISABLED);
@@ -1513,6 +1514,61 @@ static int dfll_init(struct tegra_dfll *td)
 	return ret;
 }
 
+/**
+ * tegra_dfll_suspend - check DFLL is disabled
+ * @dev: DFLL device *
+ *
+ * DFLL clock should be disabled by the CPUFreq driver. So, make
+ * sure it is disabled and disable all clocks needed by the DFLL.
+ */
+int tegra_dfll_suspend(struct device *dev)
+{
+	struct tegra_dfll *td = dev_get_drvdata(dev);
+
+	if (dfll_is_running(td)) {
+		dev_err(td->dev, "DFLL still enabled while suspending\n");
+		return -EBUSY;
+	}
+
+	reset_control_assert(td->dvco_rst);
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_suspend);
+
+/**
+ * tegra_dfll_resume - reinitialize DFLL on resume
+ * @dev: DFLL instance
+ *
+ * DFLL is disabled and reset during suspend and resume.
+ * So, reinitialize the DFLL IP block back for use.
+ * DFLL clock is enabled later in closed loop mode by CPUFreq
+ * driver before switching its clock source to DFLL output.
+ */
+int tegra_dfll_resume(struct device *dev)
+{
+	struct tegra_dfll *td = dev_get_drvdata(dev);
+
+	reset_control_deassert(td->dvco_rst);
+
+	pm_runtime_get_sync(td->dev);
+
+	dfll_set_mode(td, DFLL_DISABLED);
+	dfll_set_default_params(td);
+
+	if (td->soc->init_clock_trimmers)
+		td->soc->init_clock_trimmers();
+
+	dfll_set_open_loop_config(td);
+
+	dfll_init_out_if(td);
+
+	pm_runtime_put_sync(td->dev);
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_dfll_resume);
+
 /*
  * DT data fetch
  */
diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h
index 1b14ebe7268b..fb209eb5f365 100644
--- a/drivers/clk/tegra/clk-dfll.h
+++ b/drivers/clk/tegra/clk-dfll.h
@@ -42,5 +42,7 @@ int tegra_dfll_register(struct platform_device *pdev,
 struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev);
 int tegra_dfll_runtime_suspend(struct device *dev);
 int tegra_dfll_runtime_resume(struct device *dev);
+int tegra_dfll_suspend(struct device *dev);
+int tegra_dfll_resume(struct device *dev);
 
 #endif /* __DRIVERS_CLK_TEGRA_CLK_DFLL_H */
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
index e84b6d52cbbd..2ac2679d696d 100644
--- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
+++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
@@ -631,6 +631,7 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
 static const struct dev_pm_ops tegra124_dfll_pm_ops = {
 	SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
 			   tegra_dfll_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_dfll_suspend, tegra_dfll_resume)
 };
 
 static struct platform_driver tegra124_dfll_fcpu_driver = {
-- 
2.7.4


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

* [PATCH v9 12/22] cpufreq: tegra124: Add suspend and resume support
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (10 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 11/22] clk: tegra: clk-dfll: Add suspend and resume support Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-11-02 14:42   ` Thierry Reding
  2019-08-16 19:41 ` [PATCH v9 13/22] clk: tegra210: Use fence_udelay during PLLU init Sowjanya Komatineni
                   ` (9 subsequent siblings)
  21 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch adds suspend and resume pm ops for cpufreq driver.

PLLP is the safe clock source for CPU during system suspend and
resume as PLLP rate is below the CPU Fmax at Vmin.

CPUFreq driver suspend switches the CPU clock source to PLLP and
disables the DFLL clock.

During system resume, warmboot code powers up the CPU with PLLP
clock source. So CPUFreq driver resume enabled DFLL clock and
switches CPU back to DFLL clock source.

Acked-by: Thierry Reding <treding@nvidia.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/cpufreq/tegra124-cpufreq.c | 59 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c
index 4f0c637b3b49..7a1ea6fdcab6 100644
--- a/drivers/cpufreq/tegra124-cpufreq.c
+++ b/drivers/cpufreq/tegra124-cpufreq.c
@@ -6,6 +6,7 @@
 #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
 
 #include <linux/clk.h>
+#include <linux/cpufreq.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -128,8 +129,66 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
 	return ret;
 }
 
+static int __maybe_unused tegra124_cpufreq_suspend(struct device *dev)
+{
+	struct tegra124_cpufreq_priv *priv = dev_get_drvdata(dev);
+	int err;
+
+	/*
+	 * PLLP rate 408Mhz is below the CPU Fmax at Vmin and is safe to
+	 * use during suspend and resume. So, switch the CPU clock source
+	 * to PLLP and disable DFLL.
+	 */
+	err = clk_set_parent(priv->cpu_clk, priv->pllp_clk);
+	if (err < 0) {
+		dev_err(dev, "failed to reparent to PLLP: %d\n", err);
+		return err;
+	}
+
+	clk_disable_unprepare(priv->dfll_clk);
+
+	return 0;
+}
+
+static int __maybe_unused tegra124_cpufreq_resume(struct device *dev)
+{
+	struct tegra124_cpufreq_priv *priv = dev_get_drvdata(dev);
+	int err;
+
+	/*
+	 * Warmboot code powers up the CPU with PLLP clock source.
+	 * Enable DFLL clock and switch CPU clock source back to DFLL.
+	 */
+	err = clk_prepare_enable(priv->dfll_clk);
+	if (err < 0) {
+		dev_err(dev, "failed to enable DFLL clock for CPU: %d\n", err);
+		goto disable_cpufreq;
+	}
+
+	err = clk_set_parent(priv->cpu_clk, priv->dfll_clk);
+	if (err < 0) {
+		dev_err(dev, "failed to reparent to DFLL clock: %d\n", err);
+		goto disable_dfll;
+	}
+
+	return 0;
+
+disable_dfll:
+	clk_disable_unprepare(priv->dfll_clk);
+disable_cpufreq:
+	disable_cpufreq();
+
+	return err;
+}
+
+static const struct dev_pm_ops tegra124_cpufreq_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tegra124_cpufreq_suspend,
+				tegra124_cpufreq_resume)
+};
+
 static struct platform_driver tegra124_cpufreq_platdrv = {
 	.driver.name	= "cpufreq-tegra124",
+	.driver.pm	= &tegra124_cpufreq_pm_ops,
 	.probe		= tegra124_cpufreq_probe,
 };
 
-- 
2.7.4


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

* [PATCH v9 13/22] clk: tegra210: Use fence_udelay during PLLU init
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (11 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 12/22] cpufreq: tegra124: " Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:41 ` [PATCH v9 14/22] clk: tegra: Share clk and rst register defines with Tegra clock driver Sowjanya Komatineni
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch uses fence_udelay rather than udelay during PLLU
initialization to ensure writes to clock registers happens before
waiting for specified delay.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-tegra210.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index df172d5772d7..4c9538bd28ad 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -2841,7 +2841,7 @@ static int tegra210_enable_pllu(void)
 	reg = readl_relaxed(clk_base + pllu.params->ext_misc_reg[0]);
 	reg &= ~BIT(pllu.params->iddq_bit_idx);
 	writel_relaxed(reg, clk_base + pllu.params->ext_misc_reg[0]);
-	udelay(5);
+	fence_udelay(5, clk_base);
 
 	reg = readl_relaxed(clk_base + PLLU_BASE);
 	reg &= ~GENMASK(20, 0);
@@ -2849,7 +2849,7 @@ static int tegra210_enable_pllu(void)
 	reg |= fentry->n << 8;
 	reg |= fentry->p << 16;
 	writel(reg, clk_base + PLLU_BASE);
-	udelay(1);
+	fence_udelay(1, clk_base);
 	reg |= PLL_ENABLE;
 	writel(reg, clk_base + PLLU_BASE);
 
@@ -2895,12 +2895,12 @@ static int tegra210_init_pllu(void)
 		reg = readl_relaxed(clk_base + XUSB_PLL_CFG0);
 		reg &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK;
 		writel_relaxed(reg, clk_base + XUSB_PLL_CFG0);
-		udelay(1);
+		fence_udelay(1, clk_base);
 
 		reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0);
 		reg |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
 		writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0);
-		udelay(1);
+		fence_udelay(1, clk_base);
 
 		reg = readl_relaxed(clk_base + PLLU_BASE);
 		reg &= ~PLLU_BASE_CLKENABLE_USB;
-- 
2.7.4


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

* [PATCH v9 14/22] clk: tegra: Share clk and rst register defines with Tegra clock driver
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (12 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 13/22] clk: tegra210: Use fence_udelay during PLLU init Sowjanya Komatineni
@ 2019-08-16 19:41 ` Sowjanya Komatineni
  2019-08-16 19:42 ` [PATCH v9 15/22] clk: tegra210: Add suspend and resume support Sowjanya Komatineni
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:41 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

Move CLK_OUT_ENB and RST_DEVICES registers to clk.h to share these with
Tegra clock driver.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk.c | 45 ---------------------------------------------
 drivers/clk/tegra/clk.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index eb08047fd02f..33ac88ee324a 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -16,51 +16,6 @@
 
 #include "clk.h"
 
-#define CLK_OUT_ENB_L			0x010
-#define CLK_OUT_ENB_H			0x014
-#define CLK_OUT_ENB_U			0x018
-#define CLK_OUT_ENB_V			0x360
-#define CLK_OUT_ENB_W			0x364
-#define CLK_OUT_ENB_X			0x280
-#define CLK_OUT_ENB_Y			0x298
-#define CLK_ENB_PLLP_OUT_CPU		BIT(31)
-#define CLK_OUT_ENB_SET_L		0x320
-#define CLK_OUT_ENB_CLR_L		0x324
-#define CLK_OUT_ENB_SET_H		0x328
-#define CLK_OUT_ENB_CLR_H		0x32c
-#define CLK_OUT_ENB_SET_U		0x330
-#define CLK_OUT_ENB_CLR_U		0x334
-#define CLK_OUT_ENB_SET_V		0x440
-#define CLK_OUT_ENB_CLR_V		0x444
-#define CLK_OUT_ENB_SET_W		0x448
-#define CLK_OUT_ENB_CLR_W		0x44c
-#define CLK_OUT_ENB_SET_X		0x284
-#define CLK_OUT_ENB_CLR_X		0x288
-#define CLK_OUT_ENB_SET_Y		0x29c
-#define CLK_OUT_ENB_CLR_Y		0x2a0
-
-#define RST_DEVICES_L			0x004
-#define RST_DEVICES_H			0x008
-#define RST_DEVICES_U			0x00C
-#define RST_DEVICES_V			0x358
-#define RST_DEVICES_W			0x35C
-#define RST_DEVICES_X			0x28C
-#define RST_DEVICES_Y			0x2a4
-#define RST_DEVICES_SET_L		0x300
-#define RST_DEVICES_CLR_L		0x304
-#define RST_DEVICES_SET_H		0x308
-#define RST_DEVICES_CLR_H		0x30c
-#define RST_DEVICES_SET_U		0x310
-#define RST_DEVICES_CLR_U		0x314
-#define RST_DEVICES_SET_V		0x430
-#define RST_DEVICES_CLR_V		0x434
-#define RST_DEVICES_SET_W		0x438
-#define RST_DEVICES_CLR_W		0x43c
-#define RST_DEVICES_SET_X		0x290
-#define RST_DEVICES_CLR_X		0x294
-#define RST_DEVICES_SET_Y		0x2a8
-#define RST_DEVICES_CLR_Y		0x2ac
-
 /* Global data of Tegra CPU CAR ops */
 static struct tegra_cpu_car_ops dummy_car_ops;
 struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 55c4b78280be..ba123ba4a1da 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -10,6 +10,51 @@
 #include <linux/clkdev.h>
 #include <linux/delay.h>
 
+#define CLK_OUT_ENB_L			0x010
+#define CLK_OUT_ENB_H			0x014
+#define CLK_OUT_ENB_U			0x018
+#define CLK_OUT_ENB_V			0x360
+#define CLK_OUT_ENB_W			0x364
+#define CLK_OUT_ENB_X			0x280
+#define CLK_OUT_ENB_Y			0x298
+#define CLK_ENB_PLLP_OUT_CPU		BIT(31)
+#define CLK_OUT_ENB_SET_L		0x320
+#define CLK_OUT_ENB_CLR_L		0x324
+#define CLK_OUT_ENB_SET_H		0x328
+#define CLK_OUT_ENB_CLR_H		0x32c
+#define CLK_OUT_ENB_SET_U		0x330
+#define CLK_OUT_ENB_CLR_U		0x334
+#define CLK_OUT_ENB_SET_V		0x440
+#define CLK_OUT_ENB_CLR_V		0x444
+#define CLK_OUT_ENB_SET_W		0x448
+#define CLK_OUT_ENB_CLR_W		0x44c
+#define CLK_OUT_ENB_SET_X		0x284
+#define CLK_OUT_ENB_CLR_X		0x288
+#define CLK_OUT_ENB_SET_Y		0x29c
+#define CLK_OUT_ENB_CLR_Y		0x2a0
+
+#define RST_DEVICES_L			0x004
+#define RST_DEVICES_H			0x008
+#define RST_DEVICES_U			0x00C
+#define RST_DEVICES_V			0x358
+#define RST_DEVICES_W			0x35C
+#define RST_DEVICES_X			0x28C
+#define RST_DEVICES_Y			0x2a4
+#define RST_DEVICES_SET_L		0x300
+#define RST_DEVICES_CLR_L		0x304
+#define RST_DEVICES_SET_H		0x308
+#define RST_DEVICES_CLR_H		0x30c
+#define RST_DEVICES_SET_U		0x310
+#define RST_DEVICES_CLR_U		0x314
+#define RST_DEVICES_SET_V		0x430
+#define RST_DEVICES_CLR_V		0x434
+#define RST_DEVICES_SET_W		0x438
+#define RST_DEVICES_CLR_W		0x43c
+#define RST_DEVICES_SET_X		0x290
+#define RST_DEVICES_CLR_X		0x294
+#define RST_DEVICES_SET_Y		0x2a8
+#define RST_DEVICES_CLR_Y		0x2ac
+
 /**
  * struct tegra_clk_sync_source - external clock source from codec
  *
-- 
2.7.4


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

* [PATCH v9 15/22] clk: tegra210: Add suspend and resume support
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (13 preceding siblings ...)
  2019-08-16 19:41 ` [PATCH v9 14/22] clk: tegra: Share clk and rst register defines with Tegra clock driver Sowjanya Komatineni
@ 2019-08-16 19:42 ` Sowjanya Komatineni
  2019-08-19 16:47   ` Dmitry Osipenko
  2019-08-16 19:42 ` [PATCH v9 16/22] soc/tegra: pmc: Allow to support more tegras wake Sowjanya Komatineni
                   ` (6 subsequent siblings)
  21 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:42 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch adds support for clk: tegra210: suspend-resume.

All the CAR controller settings are lost on suspend when core
power goes off.

This patch has implementation for saving and restoring all PLLs
and clocks context during system suspend and resume to have the
clocks back to same state for normal operation.

Clock driver suspend and resume are registered as syscore_ops as clocks
restore need to happen before the other drivers resume to have all their
clocks back to the same state as before suspend.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-tegra210.c | 96 ++++++++++++++++++++++++++++++++++++++--
 drivers/clk/tegra/clk.c          | 55 +++++++++++++++++++++++
 drivers/clk/tegra/clk.h          | 16 +++++++
 3 files changed, 163 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 4c9538bd28ad..d28d99cb0e9c 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -9,13 +9,13 @@
 #include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/syscore_ops.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/clk/tegra.h>
 #include <dt-bindings/clock/tegra210-car.h>
 #include <dt-bindings/reset/tegra210-car.h>
-#include <linux/iopoll.h>
 #include <linux/sizes.h>
 #include <soc/tegra/pmc.h>
 
@@ -220,11 +220,15 @@
 #define CLK_M_DIVISOR_SHIFT 2
 #define CLK_M_DIVISOR_MASK 0x3
 
+#define CLK_MASK_ARM	0x44
+#define MISC_CLK_ENB	0x48
+
 #define RST_DFLL_DVCO 0x2f4
 #define DVFS_DFLL_RESET_SHIFT 0
 
 #define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8
 #define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac
+#define CPU_SOFTRST_CTRL 0x380
 
 #define LVL2_CLK_GATE_OVRA 0xf8
 #define LVL2_CLK_GATE_OVRC 0x3a0
@@ -2825,6 +2829,7 @@ static int tegra210_enable_pllu(void)
 	struct tegra_clk_pll_freq_table *fentry;
 	struct tegra_clk_pll pllu;
 	u32 reg;
+	int ret;
 
 	for (fentry = pll_u_freq_table; fentry->input_rate; fentry++) {
 		if (fentry->input_rate == pll_ref_freq)
@@ -2853,9 +2858,14 @@ static int tegra210_enable_pllu(void)
 	reg |= PLL_ENABLE;
 	writel(reg, clk_base + PLLU_BASE);
 
-	readl_relaxed_poll_timeout_atomic(clk_base + PLLU_BASE, reg,
-					  reg & PLL_BASE_LOCK, 2, 1000);
-	if (!(reg & PLL_BASE_LOCK)) {
+	/*
+	 * During clocks resume, same PLLU init and enable sequence get
+	 * executed. So, readx_poll_timeout_atomic can't be used here as it
+	 * uses ktime_get() and timekeeping resume doesn't happen by that
+	 * time. So, using tegra210_wait_for_mask for PLL LOCK.
+	 */
+	ret = tegra210_wait_for_mask(&pllu, PLLU_BASE, PLL_BASE_LOCK);
+	if (ret) {
 		pr_err("Timed out waiting for PLL_U to lock\n");
 		return -ETIMEDOUT;
 	}
@@ -3287,6 +3297,77 @@ static void tegra210_disable_cpu_clock(u32 cpu)
 }
 
 #ifdef CONFIG_PM_SLEEP
+#define car_readl(_base, _off) readl_relaxed(clk_base + (_base) + ((_off) * 4))
+#define car_writel(_val, _base, _off) \
+		writel_relaxed(_val, clk_base + (_base) + ((_off) * 4))
+
+static u32 spare_reg_ctx, misc_clk_enb_ctx, clk_msk_arm_ctx;
+static u32 cpu_softrst_ctx[3];
+
+static int tegra210_clk_suspend(void)
+{
+	unsigned int i;
+
+	clk_save_context();
+
+	/*
+	 * Save the bootloader configured clock registers SPARE_REG0,
+	 * MISC_CLK_ENB, CLK_MASK_ARM, CPU_SOFTRST_CTRL.
+	 */
+	spare_reg_ctx = readl_relaxed(clk_base + SPARE_REG0);
+	misc_clk_enb_ctx = readl_relaxed(clk_base + MISC_CLK_ENB);
+	clk_msk_arm_ctx = readl_relaxed(clk_base + CLK_MASK_ARM);
+
+	for (i = 0; i < ARRAY_SIZE(cpu_softrst_ctx); i++)
+		cpu_softrst_ctx[i] = car_readl(CPU_SOFTRST_CTRL, i);
+
+	tegra_clk_periph_suspend();
+	return 0;
+}
+
+static void tegra210_clk_resume(void)
+{
+	unsigned int i;
+
+	tegra_clk_osc_resume(clk_base);
+
+	/*
+	 * Restore the bootloader configured clock registers SPARE_REG0,
+	 * MISC_CLK_ENB, CLK_MASK_ARM, CPU_SOFTRST_CTRL from saved context.
+	 */
+	writel_relaxed(spare_reg_ctx, clk_base + SPARE_REG0);
+	writel_relaxed(misc_clk_enb_ctx, clk_base + MISC_CLK_ENB);
+	writel_relaxed(clk_msk_arm_ctx, clk_base + CLK_MASK_ARM);
+
+	for (i = 0; i < ARRAY_SIZE(cpu_softrst_ctx); i++)
+		car_writel(cpu_softrst_ctx[i], CPU_SOFTRST_CTRL, i);
+
+	/*
+	 * Tegra clock programming sequence recommends peripheral clock to
+	 * be enabled prior to changing its clock source and divider to
+	 * prevent glitchless frequency switch.
+	 * So, enable all peripheral clocks before restoring their source
+	 * and dividers.
+	 */
+	writel_relaxed(TEGRA210_CLK_ENB_VLD_MSK_L, clk_base + CLK_OUT_ENB_L);
+	writel_relaxed(TEGRA210_CLK_ENB_VLD_MSK_H, clk_base + CLK_OUT_ENB_H);
+	writel_relaxed(TEGRA210_CLK_ENB_VLD_MSK_U, clk_base + CLK_OUT_ENB_U);
+	writel_relaxed(TEGRA210_CLK_ENB_VLD_MSK_V, clk_base + CLK_OUT_ENB_V);
+	writel_relaxed(TEGRA210_CLK_ENB_VLD_MSK_W, clk_base + CLK_OUT_ENB_W);
+	writel_relaxed(TEGRA210_CLK_ENB_VLD_MSK_X, clk_base + CLK_OUT_ENB_X);
+	writel_relaxed(TEGRA210_CLK_ENB_VLD_MSK_Y, clk_base + CLK_OUT_ENB_Y);
+
+	/* wait for all writes to happen to have all the clocks enabled */
+	fence_udelay(2, clk_base);
+
+	/* restore PLLs and all peripheral clock rates */
+	tegra210_init_pllu();
+	clk_restore_context();
+
+	/* restore saved context of peripheral clocks and reset state */
+	tegra_clk_periph_resume();
+}
+
 static void tegra210_cpu_clock_suspend(void)
 {
 	/* switch coresite to clk_m, save off original source */
@@ -3302,6 +3383,11 @@ static void tegra210_cpu_clock_resume(void)
 }
 #endif
 
+static struct syscore_ops tegra_clk_syscore_ops = {
+	.suspend = tegra210_clk_suspend,
+	.resume = tegra210_clk_resume,
+};
+
 static struct tegra_cpu_car_ops tegra210_cpu_car_ops = {
 	.wait_for_reset	= tegra210_wait_cpu_in_reset,
 	.disable_clock	= tegra210_disable_cpu_clock,
@@ -3586,5 +3672,7 @@ static void __init tegra210_clock_init(struct device_node *np)
 	tegra210_mbist_clk_init();
 
 	tegra_cpu_car_ops = &tegra210_cpu_car_ops;
+
+	register_syscore_ops(&tegra_clk_syscore_ops);
 }
 CLK_OF_DECLARE(tegra210, "nvidia,tegra210-car", tegra210_clock_init);
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 33ac88ee324a..e6bd6d1ea012 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -22,6 +22,7 @@ struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
 
 int *periph_clk_enb_refcnt;
 static int periph_banks;
+static u32 *periph_state_ctx;
 static struct clk **clks;
 static int clk_num;
 static struct clk_onecell_data clk_data;
@@ -168,6 +169,52 @@ void tegra_clk_set_pllp_out_cpu(bool enable)
 	writel_relaxed(val, clk_base + CLK_OUT_ENB_Y);
 }
 
+void tegra_clk_periph_suspend(void)
+{
+	unsigned int i, idx;
+
+	idx = 0;
+	for (i = 0; i < periph_banks; i++, idx++)
+		periph_state_ctx[idx] =
+			readl_relaxed(clk_base + periph_regs[i].enb_reg);
+
+	for (i = 0; i < periph_banks; i++, idx++)
+		periph_state_ctx[idx] =
+			readl_relaxed(clk_base + periph_regs[i].rst_reg);
+}
+
+void tegra_clk_periph_resume(void)
+{
+	unsigned int i, idx;
+
+	idx = 0;
+	for (i = 0; i < periph_banks; i++, idx++)
+		writel_relaxed(periph_state_ctx[idx],
+			       clk_base + periph_regs[i].enb_reg);
+	/*
+	 * All non-boot peripherals will be in reset state on resume.
+	 * Wait for 5us of reset propagation delay before de-asserting
+	 * the peripherals based on the saved context.
+	 */
+	fence_udelay(5, clk_base);
+
+	for (i = 0; i < periph_banks; i++, idx++)
+		writel_relaxed(periph_state_ctx[idx],
+			       clk_base + periph_regs[i].rst_reg);
+
+	fence_udelay(2, clk_base);
+}
+
+static int tegra_clk_periph_ctx_init(int banks)
+{
+	periph_state_ctx = kcalloc(2 * banks, sizeof(*periph_state_ctx),
+				   GFP_KERNEL);
+	if (!periph_state_ctx)
+		return -ENOMEM;
+
+	return 0;
+}
+
 struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
 {
 	clk_base = regs;
@@ -189,6 +236,14 @@ struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
 
 	clk_num = num;
 
+	if (IS_ENABLED(CONFIG_PM_SLEEP)) {
+		if (tegra_clk_periph_ctx_init(banks)) {
+			kfree(periph_clk_enb_refcnt);
+			kfree(clks);
+			return NULL;
+		}
+	}
+
 	return clks;
 }
 
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index ba123ba4a1da..30247b8fe912 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -55,6 +55,20 @@
 #define RST_DEVICES_SET_Y		0x2a8
 #define RST_DEVICES_CLR_Y		0x2ac
 
+/*
+ * Tegra CLK_OUT_ENB registers have some undefined bits which are not used and
+ * any accidental write of 1 to these bits can cause PSLVERR.
+ * So below are the valid mask defines for each CLK_OUT_ENB register used to
+ * turn ON only the valid clocks.
+ */
+#define TEGRA210_CLK_ENB_VLD_MSK_L	0xdcd7dff9
+#define TEGRA210_CLK_ENB_VLD_MSK_H	0x87d1f3e7
+#define TEGRA210_CLK_ENB_VLD_MSK_U	0xf3fed3fa
+#define TEGRA210_CLK_ENB_VLD_MSK_V	0xffc18cfb
+#define TEGRA210_CLK_ENB_VLD_MSK_W	0x793fb7ff
+#define TEGRA210_CLK_ENB_VLD_MSK_X	0x3fe66fff
+#define TEGRA210_CLK_ENB_VLD_MSK_Y	0xfc1fc7ff
+
 /**
  * struct tegra_clk_sync_source - external clock source from codec
  *
@@ -880,6 +894,8 @@ int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
 		 u8 frac_width, u8 flags);
 void tegra_clk_osc_resume(void __iomem *clk_base);
 void tegra_clk_set_pllp_out_cpu(bool enable);
+void tegra_clk_periph_suspend(void);
+void tegra_clk_periph_resume(void);
 
 
 /* Combined read fence with delay */
-- 
2.7.4


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

* [PATCH v9 16/22] soc/tegra: pmc: Allow to support more tegras wake
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (14 preceding siblings ...)
  2019-08-16 19:42 ` [PATCH v9 15/22] clk: tegra210: Add suspend and resume support Sowjanya Komatineni
@ 2019-08-16 19:42 ` Sowjanya Komatineni
  2019-08-16 19:42 ` [PATCH v9 17/22] soc/tegra: pmc: Add pmc wake support for tegra210 Sowjanya Komatineni
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:42 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch allows to create separate irq_set_wake and irq_set_type
implementations for different tegra designs PMC that has different
wake models which require difference wake registers and different
programming sequence.

AOWAKE model support is available for Tegra186 and Tegra194 only
and it resides within PMC and supports tiered wake architecture.

Tegra210 and prior tegra designs uses PMC directly to receive wake
events and coordinate the wake sequence.

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 9f9c1c677cf4..91c84d0e66ae 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -226,6 +226,8 @@ struct tegra_pmc_soc {
 	void (*setup_irq_polarity)(struct tegra_pmc *pmc,
 				   struct device_node *np,
 				   bool invert);
+	int (*irq_set_wake)(struct irq_data *data, unsigned int on);
+	int (*irq_set_type)(struct irq_data *data, unsigned int type);
 
 	const char * const *reset_sources;
 	unsigned int num_reset_sources;
@@ -1920,7 +1922,7 @@ static const struct irq_domain_ops tegra_pmc_irq_domain_ops = {
 	.alloc = tegra_pmc_irq_alloc,
 };
 
-static int tegra_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
+static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
 {
 	struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
 	unsigned int offset, bit;
@@ -1952,7 +1954,7 @@ static int tegra_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
 	return 0;
 }
 
-static int tegra_pmc_irq_set_type(struct irq_data *data, unsigned int type)
+static int tegra186_pmc_irq_set_type(struct irq_data *data, unsigned int type)
 {
 	struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
 	u32 value;
@@ -2006,8 +2008,8 @@ static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
 	pmc->irq.irq_unmask = irq_chip_unmask_parent;
 	pmc->irq.irq_eoi = irq_chip_eoi_parent;
 	pmc->irq.irq_set_affinity = irq_chip_set_affinity_parent;
-	pmc->irq.irq_set_type = tegra_pmc_irq_set_type;
-	pmc->irq.irq_set_wake = tegra_pmc_irq_set_wake;
+	pmc->irq.irq_set_type = pmc->soc->irq_set_type;
+	pmc->irq.irq_set_wake = pmc->soc->irq_set_wake;
 
 	pmc->domain = irq_domain_add_hierarchy(parent, 0, 96, pmc->dev->of_node,
 					       &tegra_pmc_irq_domain_ops, pmc);
@@ -2680,6 +2682,8 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
 	.regs = &tegra186_pmc_regs,
 	.init = NULL,
 	.setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+	.irq_set_wake = tegra186_pmc_irq_set_wake,
+	.irq_set_type = tegra186_pmc_irq_set_type,
 	.reset_sources = tegra186_reset_sources,
 	.num_reset_sources = ARRAY_SIZE(tegra186_reset_sources),
 	.reset_levels = tegra186_reset_levels,
-- 
2.7.4


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

* [PATCH v9 17/22] soc/tegra: pmc: Add pmc wake support for tegra210
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (15 preceding siblings ...)
  2019-08-16 19:42 ` [PATCH v9 16/22] soc/tegra: pmc: Allow to support more tegras wake Sowjanya Komatineni
@ 2019-08-16 19:42 ` Sowjanya Komatineni
  2019-08-16 19:42 ` [PATCH v9 18/22] arm64: tegra: Enable wake from deep sleep on RTC alarm Sowjanya Komatineni
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:42 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch implements PMC wakeup sequence for Tegra210 and defines
common used RTC alarm wake event.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 91c84d0e66ae..76e7292ded25 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -58,6 +58,11 @@
 #define  PMC_CNTRL_SYSCLK_POLARITY	BIT(10) /* sys clk polarity */
 #define  PMC_CNTRL_MAIN_RST		BIT(4)
 
+#define PMC_WAKE_MASK			0x0c
+#define PMC_WAKE_LEVEL			0x10
+#define PMC_WAKE_STATUS			0x14
+#define PMC_SW_WAKE_STATUS		0x18
+
 #define DPD_SAMPLE			0x020
 #define  DPD_SAMPLE_ENABLE		BIT(0)
 #define  DPD_SAMPLE_DISABLE		(0 << 0)
@@ -87,6 +92,11 @@
 
 #define PMC_SCRATCH41			0x140
 
+#define PMC_WAKE2_MASK			0x160
+#define PMC_WAKE2_LEVEL			0x164
+#define PMC_WAKE2_STATUS		0x168
+#define PMC_SW_WAKE2_STATUS		0x16c
+
 #define PMC_SENSOR_CTRL			0x1b0
 #define  PMC_SENSOR_CTRL_SCRATCH_WRITE	BIT(2)
 #define  PMC_SENSOR_CTRL_ENABLE_RST	BIT(1)
@@ -1922,6 +1932,43 @@ static const struct irq_domain_ops tegra_pmc_irq_domain_ops = {
 	.alloc = tegra_pmc_irq_alloc,
 };
 
+static int tegra210_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+	struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
+	unsigned int offset, bit;
+	u32 value;
+
+	if (data->hwirq == ULONG_MAX)
+		return 0;
+
+	offset = data->hwirq / 32;
+	bit = data->hwirq % 32;
+
+	/* clear wake status */
+	tegra_pmc_writel(pmc, 0, PMC_SW_WAKE_STATUS);
+	tegra_pmc_writel(pmc, 0, PMC_SW_WAKE2_STATUS);
+
+	tegra_pmc_writel(pmc, 0, PMC_WAKE_STATUS);
+	tegra_pmc_writel(pmc, 0, PMC_WAKE2_STATUS);
+
+	/* enable PMC wake */
+	if (data->hwirq >= 32)
+		offset = PMC_WAKE2_MASK;
+	else
+		offset = PMC_WAKE_MASK;
+
+	value = tegra_pmc_readl(pmc, offset);
+
+	if (on)
+		value |= BIT(bit);
+	else
+		value &= ~BIT(bit);
+
+	tegra_pmc_writel(pmc, value, offset);
+
+	return 0;
+}
+
 static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
 {
 	struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
@@ -1954,6 +2001,49 @@ static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
 	return 0;
 }
 
+static int tegra210_pmc_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
+	unsigned int offset, bit;
+	u32 value;
+
+	if (data->hwirq == ULONG_MAX)
+		return 0;
+
+	offset = data->hwirq / 32;
+	bit = data->hwirq % 32;
+
+	if (data->hwirq >= 32)
+		offset = PMC_WAKE2_LEVEL;
+	else
+		offset = PMC_WAKE_LEVEL;
+
+	value = tegra_pmc_readl(pmc, offset);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+	case IRQ_TYPE_LEVEL_HIGH:
+		value |= BIT(bit);
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_LEVEL_LOW:
+		value &= ~BIT(bit);
+		break;
+
+	case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
+		value ^= BIT(bit);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	tegra_pmc_writel(pmc, value, offset);
+
+	return 0;
+}
+
 static int tegra186_pmc_irq_set_type(struct irq_data *data, unsigned int type)
 {
 	struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
@@ -2540,6 +2630,10 @@ static const struct pinctrl_pin_desc tegra210_pin_descs[] = {
 	TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
 };
 
+static const struct tegra_wake_event tegra210_wake_events[] = {
+	TEGRA_WAKE_IRQ("rtc", 16, 2),
+};
+
 static const struct tegra_pmc_soc tegra210_pmc_soc = {
 	.num_powergates = ARRAY_SIZE(tegra210_powergates),
 	.powergates = tegra210_powergates,
@@ -2557,10 +2651,14 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
 	.regs = &tegra20_pmc_regs,
 	.init = tegra20_pmc_init,
 	.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
+	.irq_set_wake = tegra210_pmc_irq_set_wake,
+	.irq_set_type = tegra210_pmc_irq_set_type,
 	.reset_sources = tegra210_reset_sources,
 	.num_reset_sources = ARRAY_SIZE(tegra210_reset_sources),
 	.reset_levels = NULL,
 	.num_reset_levels = 0,
+	.num_wake_events = ARRAY_SIZE(tegra210_wake_events),
+	.wake_events = tegra210_wake_events,
 };
 
 #define TEGRA186_IO_PAD_TABLE(_pad)					     \
-- 
2.7.4


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

* [PATCH v9 18/22] arm64: tegra: Enable wake from deep sleep on RTC alarm
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (16 preceding siblings ...)
  2019-08-16 19:42 ` [PATCH v9 17/22] soc/tegra: pmc: Add pmc wake support for tegra210 Sowjanya Komatineni
@ 2019-08-16 19:42 ` Sowjanya Komatineni
  2019-08-16 19:42 ` [PATCH v9 19/22] soc/tegra: pmc: Configure core power request polarity Sowjanya Komatineni
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:42 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch updates device tree for RTC and PMC to allow system wake
from deep sleep on RTC alarm.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 659753118e96..30a7c48385a2 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -768,7 +768,8 @@
 	rtc@7000e000 {
 		compatible = "nvidia,tegra210-rtc", "nvidia,tegra20-rtc";
 		reg = <0x0 0x7000e000 0x0 0x100>;
-		interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <16 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-parent = <&pmc>;
 		clocks = <&tegra_car TEGRA210_CLK_RTC>;
 		clock-names = "rtc";
 	};
@@ -778,6 +779,8 @@
 		reg = <0x0 0x7000e400 0x0 0x400>;
 		clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
 		clock-names = "pclk", "clk32k_in";
+		#interrupt-cells = <2>;
+		interrupt-controller;
 
 		powergates {
 			pd_audio: aud {
-- 
2.7.4


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

* [PATCH v9 19/22] soc/tegra: pmc: Configure core power request polarity
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (17 preceding siblings ...)
  2019-08-16 19:42 ` [PATCH v9 18/22] arm64: tegra: Enable wake from deep sleep on RTC alarm Sowjanya Komatineni
@ 2019-08-16 19:42 ` Sowjanya Komatineni
  2019-08-16 19:42 ` [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings Sowjanya Komatineni
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:42 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch configures polarity of the core power request signal
in PMC control register based on the device tree property.

PMC asserts and de-asserts power request signal based on it polarity
when it need to power-up and power-down the core rail during SC7.

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 76e7292ded25..53ed70773872 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -56,6 +56,7 @@
 #define  PMC_CNTRL_SIDE_EFFECT_LP0	BIT(14) /* LP0 when CPU pwr gated */
 #define  PMC_CNTRL_SYSCLK_OE		BIT(11) /* system clock enable */
 #define  PMC_CNTRL_SYSCLK_POLARITY	BIT(10) /* sys clk polarity */
+#define  PMC_CNTRL_PWRREQ_POLARITY	BIT(8)
 #define  PMC_CNTRL_MAIN_RST		BIT(4)
 
 #define PMC_WAKE_MASK			0x0c
@@ -2290,6 +2291,11 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
 	else
 		value |= PMC_CNTRL_SYSCLK_POLARITY;
 
+	if (pmc->corereq_high)
+		value &= ~PMC_CNTRL_PWRREQ_POLARITY;
+	else
+		value |= PMC_CNTRL_PWRREQ_POLARITY;
+
 	/* configure the output polarity while the request is tristated */
 	tegra_pmc_writel(pmc, value, PMC_CNTRL);
 
-- 
2.7.4


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

* [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (18 preceding siblings ...)
  2019-08-16 19:42 ` [PATCH v9 19/22] soc/tegra: pmc: Configure core power request polarity Sowjanya Komatineni
@ 2019-08-16 19:42 ` Sowjanya Komatineni
  2019-08-19 16:48   ` Dmitry Osipenko
  2019-08-16 19:42 ` [PATCH v9 21/22] arm64: dts: tegra210-p2180: Jetson TX1 SC7 timings Sowjanya Komatineni
  2019-08-16 19:42 ` [PATCH v9 22/22] arm64: dts: tegra210-p3450: Jetson Nano " Sowjanya Komatineni
  21 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:42 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
timings which are platform specific that should be configured before
entering into deep sleep.

Below are the timing specific configurations for deep sleep entry and
wakeup.
- Core rail power-on stabilization timer
- OSC clock stabilization timer after SOC rail power is stabilized.
- Core power off time is the minimum wake delay to keep the system
  in deep sleep state irrespective of any quick wake event.

These values depends on the discharge time of regulators and turn OFF
time of the PMIC to allow the complete system to finish entering into
deep sleep state.

These values vary based on the platform design and are specified
through the device tree.

This patch has implementation to configure these timings which are must
to have for proper deep sleep and wakeup operations.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/soc/tegra/pmc.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 53ed70773872..710969043668 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -88,6 +88,8 @@
 
 #define PMC_CPUPWRGOOD_TIMER		0xc8
 #define PMC_CPUPWROFF_TIMER		0xcc
+#define PMC_COREPWRGOOD_TIMER		0x3c
+#define PMC_COREPWROFF_TIMER		0xe0
 
 #define PMC_PWR_DET_VALUE		0xe4
 
@@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs tegra20_pmc_regs = {
 
 static void tegra20_pmc_init(struct tegra_pmc *pmc)
 {
-	u32 value;
+	u32 value, osc, pmu, off;
 
 	/* Always enable CPU power request */
 	value = tegra_pmc_readl(pmc, PMC_CNTRL);
@@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
 	value = tegra_pmc_readl(pmc, PMC_CNTRL);
 	value |= PMC_CNTRL_SYSCLK_OE;
 	tegra_pmc_writel(pmc, value, PMC_CNTRL);
+
+	/* program core timings which are applicable only for suspend state */
+	if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
+		osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
+		pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
+		off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
+		tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
+				 PMC_COREPWRGOOD_TIMER);
+		tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
+	}
 }
 
 static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
-- 
2.7.4


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

* [PATCH v9 21/22] arm64: dts: tegra210-p2180: Jetson TX1 SC7 timings
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (19 preceding siblings ...)
  2019-08-16 19:42 ` [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings Sowjanya Komatineni
@ 2019-08-16 19:42 ` Sowjanya Komatineni
  2019-08-16 19:42 ` [PATCH v9 22/22] arm64: dts: tegra210-p3450: Jetson Nano " Sowjanya Komatineni
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:42 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch has Jetson TX1 platform specific SC7 timing configuration
in device tree.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
index 27723829d033..cb58f79deb48 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
@@ -279,6 +279,13 @@
 
 	pmc@7000e400 {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <0>;
+		nvidia,cpu-pwr-good-time = <0>;
+		nvidia,cpu-pwr-off-time = <0>;
+		nvidia,core-pwr-good-time = <4587 3876>;
+		nvidia,core-pwr-off-time = <39065>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	/* eMMC */
-- 
2.7.4


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

* [PATCH v9 22/22] arm64: dts: tegra210-p3450: Jetson Nano SC7 timings
  2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
                   ` (20 preceding siblings ...)
  2019-08-16 19:42 ` [PATCH v9 21/22] arm64: dts: tegra210-p2180: Jetson TX1 SC7 timings Sowjanya Komatineni
@ 2019-08-16 19:42 ` Sowjanya Komatineni
  21 siblings, 0 replies; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-16 19:42 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch adds Jetson Nano platform specific SC7 timing configuration
in the device tree.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
index 9d17ec707bce..b525e69c172a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
@@ -382,6 +382,13 @@
 
 	pmc@7000e400 {
 		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <0>;
+		nvidia,cpu-pwr-good-time = <0>;
+		nvidia,cpu-pwr-off-time = <0>;
+		nvidia,core-pwr-good-time = <4587 3876>;
+		nvidia,core-pwr-off-time = <39065>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
 	};
 
 	hda@70030000 {
-- 
2.7.4


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

* Re: [PATCH v9 01/22] pinctrl: tegra: Fix write barrier placement in pmx_writel
  2019-08-16 19:41 ` [PATCH v9 01/22] pinctrl: tegra: Fix write barrier placement in pmx_writel Sowjanya Komatineni
@ 2019-08-18 22:20   ` Linus Walleij
  0 siblings, 0 replies; 41+ messages in thread
From: Linus Walleij @ 2019-08-18 22:20 UTC (permalink / raw)
  To: Sowjanya Komatineni
  Cc: thierry.reding, Jon Hunter, Thomas Gleixner, Jason Cooper,
	Marc Zyngier, Stefan Agner, Mark Rutland, Peter De Schrijver,
	Prashant Gaikwad, Stephen Boyd, linux-clk,
	open list:GPIO SUBSYSTEM, jckuo, Joseph Lo, talho, linux-tegra,
	linux-kernel, Mikko Perttunen, spatra, Rob Herring,
	Dmitry Osipenko,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rafael J. Wysocki, viresh kumar, Linux PM list

On Fri, Aug 16, 2019 at 9:42 PM Sowjanya Komatineni
<skomatineni@nvidia.com> wrote:
>
> pmx_writel uses writel which inserts write barrier before the
> register write.
>
> This patch has fix to replace writel with writel_relaxed followed
> by a readback and memory barrier to ensure write operation is
> completed for successful pinctrl change.
>
> Acked-by: Thierry Reding <treding@nvidia.com>
> Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>

Took out the previous patches and applied this instead.

Yours,
Linus Walleij

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

* Re: [PATCH v9 02/22] pinctrl: tegra: Flush pinctrl writes during resume
  2019-08-16 19:41 ` [PATCH v9 02/22] pinctrl: tegra: Flush pinctrl writes during resume Sowjanya Komatineni
@ 2019-08-18 22:20   ` Linus Walleij
  0 siblings, 0 replies; 41+ messages in thread
From: Linus Walleij @ 2019-08-18 22:20 UTC (permalink / raw)
  To: Sowjanya Komatineni
  Cc: thierry.reding, Jon Hunter, Thomas Gleixner, Jason Cooper,
	Marc Zyngier, Stefan Agner, Mark Rutland, Peter De Schrijver,
	Prashant Gaikwad, Stephen Boyd, linux-clk,
	open list:GPIO SUBSYSTEM, jckuo, Joseph Lo, talho, linux-tegra,
	linux-kernel, Mikko Perttunen, spatra, Rob Herring,
	Dmitry Osipenko,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Rafael J. Wysocki, viresh kumar, Linux PM list

On Fri, Aug 16, 2019 at 9:42 PM Sowjanya Komatineni
<skomatineni@nvidia.com> wrote:

> This patch adds pinctrl register read to flush all the prior pinctrl
> writes and then adds barrier for pinctrl register read to complete
> during resume to make sure all pinctrl changes are effective.
>
> Acked-by: Thierry Reding <treding@nvidia.com>
> Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>

Patch applied.

Yours,
Linus Walleij

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

* Re: [PATCH v9 15/22] clk: tegra210: Add suspend and resume support
  2019-08-16 19:42 ` [PATCH v9 15/22] clk: tegra210: Add suspend and resume support Sowjanya Komatineni
@ 2019-08-19 16:47   ` Dmitry Osipenko
  0 siblings, 0 replies; 41+ messages in thread
From: Dmitry Osipenko @ 2019-08-19 16:47 UTC (permalink / raw)
  To: Sowjanya Komatineni, thierry.reding, jonathanh, tglx, jason,
	marc.zyngier, linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
	robh+dt, devicetree, rjw, viresh.kumar, linux-pm

16.08.2019 22:42, Sowjanya Komatineni пишет:
> This patch adds support for clk: tegra210: suspend-resume.
> 
> All the CAR controller settings are lost on suspend when core
> power goes off.
> 
> This patch has implementation for saving and restoring all PLLs
> and clocks context during system suspend and resume to have the
> clocks back to same state for normal operation.
> 
> Clock driver suspend and resume are registered as syscore_ops as clocks
> restore need to happen before the other drivers resume to have all their
> clocks back to the same state as before suspend.
> 
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>

Looks good, thanks!

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>

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

* Re: [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings
  2019-08-16 19:42 ` [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings Sowjanya Komatineni
@ 2019-08-19 16:48   ` Dmitry Osipenko
  2019-08-19 18:20     ` Sowjanya Komatineni
  0 siblings, 1 reply; 41+ messages in thread
From: Dmitry Osipenko @ 2019-08-19 16:48 UTC (permalink / raw)
  To: Sowjanya Komatineni, thierry.reding, jonathanh, tglx, jason,
	marc.zyngier, linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
	robh+dt, devicetree, rjw, viresh.kumar, linux-pm

16.08.2019 22:42, Sowjanya Komatineni пишет:
> Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
> timings which are platform specific that should be configured before
> entering into deep sleep.
> 
> Below are the timing specific configurations for deep sleep entry and
> wakeup.
> - Core rail power-on stabilization timer
> - OSC clock stabilization timer after SOC rail power is stabilized.
> - Core power off time is the minimum wake delay to keep the system
>   in deep sleep state irrespective of any quick wake event.
> 
> These values depends on the discharge time of regulators and turn OFF
> time of the PMIC to allow the complete system to finish entering into
> deep sleep state.
> 
> These values vary based on the platform design and are specified
> through the device tree.
> 
> This patch has implementation to configure these timings which are must
> to have for proper deep sleep and wakeup operations.
> 
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
> ---
>  drivers/soc/tegra/pmc.c | 14 +++++++++++++-
>  1 file changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index 53ed70773872..710969043668 100644
> --- a/drivers/soc/tegra/pmc.c
> +++ b/drivers/soc/tegra/pmc.c
> @@ -88,6 +88,8 @@
>  
>  #define PMC_CPUPWRGOOD_TIMER		0xc8
>  #define PMC_CPUPWROFF_TIMER		0xcc
> +#define PMC_COREPWRGOOD_TIMER		0x3c
> +#define PMC_COREPWROFF_TIMER		0xe0
>  
>  #define PMC_PWR_DET_VALUE		0xe4
>  
> @@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs tegra20_pmc_regs = {
>  
>  static void tegra20_pmc_init(struct tegra_pmc *pmc)
>  {
> -	u32 value;
> +	u32 value, osc, pmu, off;
>  
>  	/* Always enable CPU power request */
>  	value = tegra_pmc_readl(pmc, PMC_CNTRL);
> @@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
>  	value = tegra_pmc_readl(pmc, PMC_CNTRL);
>  	value |= PMC_CNTRL_SYSCLK_OE;
>  	tegra_pmc_writel(pmc, value, PMC_CNTRL);
> +
> +	/* program core timings which are applicable only for suspend state */
> +	if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
> +		osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
> +		pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
> +		off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
> +		tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
> +				 PMC_COREPWRGOOD_TIMER);
> +		tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
> +	}
>  }
>  
>  static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
> 

In the previous version of this patch there were checks for zero values
of the timers with intention to skip programming of the timers if value
is zero. I'm a bit puzzled by the new version, given that SUSPEND_NONE
means that suspending isn't available at all and thus PMC timers won't
be utilized, hence it shouldn't matter what values are programmed for
the counters, isn't it?

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

* Re: [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings
  2019-08-19 16:48   ` Dmitry Osipenko
@ 2019-08-19 18:20     ` Sowjanya Komatineni
  2019-08-19 19:07       ` Sowjanya Komatineni
  0 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-19 18:20 UTC (permalink / raw)
  To: Dmitry Osipenko, thierry.reding, jonathanh, tglx, jason,
	marc.zyngier, linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
	robh+dt, devicetree, rjw, viresh.kumar, linux-pm


On 8/19/19 9:48 AM, Dmitry Osipenko wrote:
> 16.08.2019 22:42, Sowjanya Komatineni пишет:
>> Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
>> timings which are platform specific that should be configured before
>> entering into deep sleep.
>>
>> Below are the timing specific configurations for deep sleep entry and
>> wakeup.
>> - Core rail power-on stabilization timer
>> - OSC clock stabilization timer after SOC rail power is stabilized.
>> - Core power off time is the minimum wake delay to keep the system
>>    in deep sleep state irrespective of any quick wake event.
>>
>> These values depends on the discharge time of regulators and turn OFF
>> time of the PMIC to allow the complete system to finish entering into
>> deep sleep state.
>>
>> These values vary based on the platform design and are specified
>> through the device tree.
>>
>> This patch has implementation to configure these timings which are must
>> to have for proper deep sleep and wakeup operations.
>>
>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>> ---
>>   drivers/soc/tegra/pmc.c | 14 +++++++++++++-
>>   1 file changed, 13 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
>> index 53ed70773872..710969043668 100644
>> --- a/drivers/soc/tegra/pmc.c
>> +++ b/drivers/soc/tegra/pmc.c
>> @@ -88,6 +88,8 @@
>>   
>>   #define PMC_CPUPWRGOOD_TIMER		0xc8
>>   #define PMC_CPUPWROFF_TIMER		0xcc
>> +#define PMC_COREPWRGOOD_TIMER		0x3c
>> +#define PMC_COREPWROFF_TIMER		0xe0
>>   
>>   #define PMC_PWR_DET_VALUE		0xe4
>>   
>> @@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs tegra20_pmc_regs = {
>>   
>>   static void tegra20_pmc_init(struct tegra_pmc *pmc)
>>   {
>> -	u32 value;
>> +	u32 value, osc, pmu, off;
>>   
>>   	/* Always enable CPU power request */
>>   	value = tegra_pmc_readl(pmc, PMC_CNTRL);
>> @@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc *pmc)
>>   	value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>   	value |= PMC_CNTRL_SYSCLK_OE;
>>   	tegra_pmc_writel(pmc, value, PMC_CNTRL);
>> +
>> +	/* program core timings which are applicable only for suspend state */
>> +	if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
>> +		osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
>> +		pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
>> +		off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
>> +		tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
>> +				 PMC_COREPWRGOOD_TIMER);
>> +		tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
>> +	}
>>   }
>>   
>>   static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
>>
> In the previous version of this patch there were checks for zero values
> of the timers with intention to skip programming of the timers if value
> is zero. I'm a bit puzzled by the new version, given that SUSPEND_NONE
> means that suspending isn't available at all and thus PMC timers won't
> be utilized, hence it shouldn't matter what values are programmed for
> the counters, isn't it?

Yes, as I see in documentation we already specify all these timings are 
required properties when suspend mode is used, I updated in this version 
to program core timings only when suspend mode is enabled.



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

* Re: [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings
  2019-08-19 18:20     ` Sowjanya Komatineni
@ 2019-08-19 19:07       ` Sowjanya Komatineni
  2019-08-19 19:33         ` Dmitry Osipenko
  0 siblings, 1 reply; 41+ messages in thread
From: Sowjanya Komatineni @ 2019-08-19 19:07 UTC (permalink / raw)
  To: Dmitry Osipenko, thierry.reding, jonathanh, tglx, jason,
	marc.zyngier, linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
	robh+dt, devicetree, rjw, viresh.kumar, linux-pm


On 8/19/19 11:20 AM, Sowjanya Komatineni wrote:
>
> On 8/19/19 9:48 AM, Dmitry Osipenko wrote:
>> 16.08.2019 22:42, Sowjanya Komatineni пишет:
>>> Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
>>> timings which are platform specific that should be configured before
>>> entering into deep sleep.
>>>
>>> Below are the timing specific configurations for deep sleep entry and
>>> wakeup.
>>> - Core rail power-on stabilization timer
>>> - OSC clock stabilization timer after SOC rail power is stabilized.
>>> - Core power off time is the minimum wake delay to keep the system
>>>    in deep sleep state irrespective of any quick wake event.
>>>
>>> These values depends on the discharge time of regulators and turn OFF
>>> time of the PMIC to allow the complete system to finish entering into
>>> deep sleep state.
>>>
>>> These values vary based on the platform design and are specified
>>> through the device tree.
>>>
>>> This patch has implementation to configure these timings which are must
>>> to have for proper deep sleep and wakeup operations.
>>>
>>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>>> ---
>>>   drivers/soc/tegra/pmc.c | 14 +++++++++++++-
>>>   1 file changed, 13 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
>>> index 53ed70773872..710969043668 100644
>>> --- a/drivers/soc/tegra/pmc.c
>>> +++ b/drivers/soc/tegra/pmc.c
>>> @@ -88,6 +88,8 @@
>>>     #define PMC_CPUPWRGOOD_TIMER        0xc8
>>>   #define PMC_CPUPWROFF_TIMER        0xcc
>>> +#define PMC_COREPWRGOOD_TIMER        0x3c
>>> +#define PMC_COREPWROFF_TIMER        0xe0
>>>     #define PMC_PWR_DET_VALUE        0xe4
>>>   @@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs 
>>> tegra20_pmc_regs = {
>>>     static void tegra20_pmc_init(struct tegra_pmc *pmc)
>>>   {
>>> -    u32 value;
>>> +    u32 value, osc, pmu, off;
>>>         /* Always enable CPU power request */
>>>       value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>> @@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc 
>>> *pmc)
>>>       value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>>       value |= PMC_CNTRL_SYSCLK_OE;
>>>       tegra_pmc_writel(pmc, value, PMC_CNTRL);
>>> +
>>> +    /* program core timings which are applicable only for suspend 
>>> state */
>>> +    if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
>>> +        osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
>>> +        pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
>>> +        off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
>>> +        tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
>>> +                 PMC_COREPWRGOOD_TIMER);
>>> +        tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
>>> +    }
>>>   }
>>>     static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
>>>
>> In the previous version of this patch there were checks for zero values
>> of the timers with intention to skip programming of the timers if value
>> is zero. I'm a bit puzzled by the new version, given that SUSPEND_NONE
>> means that suspending isn't available at all and thus PMC timers won't
>> be utilized, hence it shouldn't matter what values are programmed for
>> the counters, isn't it?
>
> Yes, as I see in documentation we already specify all these timings 
> are required properties when suspend mode is used, I updated in this 
> version to program core timings only when suspend mode is enabled.
>
In other words, core timings are for SC7 entry only. So when SC7/suspend 
mode is not used, these timings doesn't matter.

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

* Re: [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings
  2019-08-19 19:07       ` Sowjanya Komatineni
@ 2019-08-19 19:33         ` Dmitry Osipenko
  0 siblings, 0 replies; 41+ messages in thread
From: Dmitry Osipenko @ 2019-08-19 19:33 UTC (permalink / raw)
  To: Sowjanya Komatineni, thierry.reding, jonathanh, tglx, jason,
	marc.zyngier, linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, linux-tegra, linux-kernel, mperttunen, spatra,
	robh+dt, devicetree, rjw, viresh.kumar, linux-pm

19.08.2019 22:07, Sowjanya Komatineni пишет:
> 
> On 8/19/19 11:20 AM, Sowjanya Komatineni wrote:
>>
>> On 8/19/19 9:48 AM, Dmitry Osipenko wrote:
>>> 16.08.2019 22:42, Sowjanya Komatineni пишет:
>>>> Tegra210 and prior Tegra chips have deep sleep entry and wakeup related
>>>> timings which are platform specific that should be configured before
>>>> entering into deep sleep.
>>>>
>>>> Below are the timing specific configurations for deep sleep entry and
>>>> wakeup.
>>>> - Core rail power-on stabilization timer
>>>> - OSC clock stabilization timer after SOC rail power is stabilized.
>>>> - Core power off time is the minimum wake delay to keep the system
>>>>    in deep sleep state irrespective of any quick wake event.
>>>>
>>>> These values depends on the discharge time of regulators and turn OFF
>>>> time of the PMIC to allow the complete system to finish entering into
>>>> deep sleep state.
>>>>
>>>> These values vary based on the platform design and are specified
>>>> through the device tree.
>>>>
>>>> This patch has implementation to configure these timings which are must
>>>> to have for proper deep sleep and wakeup operations.
>>>>
>>>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>>>> ---
>>>>   drivers/soc/tegra/pmc.c | 14 +++++++++++++-
>>>>   1 file changed, 13 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
>>>> index 53ed70773872..710969043668 100644
>>>> --- a/drivers/soc/tegra/pmc.c
>>>> +++ b/drivers/soc/tegra/pmc.c
>>>> @@ -88,6 +88,8 @@
>>>>     #define PMC_CPUPWRGOOD_TIMER        0xc8
>>>>   #define PMC_CPUPWROFF_TIMER        0xcc
>>>> +#define PMC_COREPWRGOOD_TIMER        0x3c
>>>> +#define PMC_COREPWROFF_TIMER        0xe0
>>>>     #define PMC_PWR_DET_VALUE        0xe4
>>>>   @@ -2277,7 +2279,7 @@ static const struct tegra_pmc_regs
>>>> tegra20_pmc_regs = {
>>>>     static void tegra20_pmc_init(struct tegra_pmc *pmc)
>>>>   {
>>>> -    u32 value;
>>>> +    u32 value, osc, pmu, off;
>>>>         /* Always enable CPU power request */
>>>>       value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>>> @@ -2303,6 +2305,16 @@ static void tegra20_pmc_init(struct tegra_pmc
>>>> *pmc)
>>>>       value = tegra_pmc_readl(pmc, PMC_CNTRL);
>>>>       value |= PMC_CNTRL_SYSCLK_OE;
>>>>       tegra_pmc_writel(pmc, value, PMC_CNTRL);
>>>> +
>>>> +    /* program core timings which are applicable only for suspend
>>>> state */
>>>> +    if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
>>>> +        osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
>>>> +        pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
>>>> +        off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
>>>> +        tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
>>>> +                 PMC_COREPWRGOOD_TIMER);
>>>> +        tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
>>>> +    }
>>>>   }
>>>>     static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
>>>>
>>> In the previous version of this patch there were checks for zero values
>>> of the timers with intention to skip programming of the timers if value
>>> is zero. I'm a bit puzzled by the new version, given that SUSPEND_NONE
>>> means that suspending isn't available at all and thus PMC timers won't
>>> be utilized, hence it shouldn't matter what values are programmed for
>>> the counters, isn't it?
>>
>> Yes, as I see in documentation we already specify all these timings
>> are required properties when suspend mode is used, I updated in this
>> version to program core timings only when suspend mode is enabled.
>>
> In other words, core timings are for SC7 entry only. So when SC7/suspend
> mode is not used, these timings doesn't matter.

In this case, it should be a bit more straightforward to always program
the timers unconditionally. But since device-tree binding requires all
the properties to be specified when suspend mode isn't NONE, then the
new variant also makes sense. Either way is good to me, thanks.

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>

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

* Re: [PATCH v9 12/22] cpufreq: tegra124: Add suspend and resume support
  2019-08-16 19:41 ` [PATCH v9 12/22] cpufreq: tegra124: " Sowjanya Komatineni
@ 2019-11-02 14:42   ` Thierry Reding
  0 siblings, 0 replies; 41+ messages in thread
From: Thierry Reding @ 2019-11-02 14:42 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Sowjanya Komatineni, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland, pdeschrijver, pgaikwad,
	sboyd, linux-clk, linux-gpio, jckuo, josephl, talho, linux-tegra,
	linux-kernel, mperttunen, spatra, robh+dt, digetx, devicetree,
	rjw, viresh.kumar, linux-pm

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

On Fri, Aug 16, 2019 at 12:41:57PM -0700, Sowjanya Komatineni wrote:
> This patch adds suspend and resume pm ops for cpufreq driver.
> 
> PLLP is the safe clock source for CPU during system suspend and
> resume as PLLP rate is below the CPU Fmax at Vmin.
> 
> CPUFreq driver suspend switches the CPU clock source to PLLP and
> disables the DFLL clock.
> 
> During system resume, warmboot code powers up the CPU with PLLP
> clock source. So CPUFreq driver resume enabled DFLL clock and
> switches CPU back to DFLL clock source.
> 
> Acked-by: Thierry Reding <treding@nvidia.com>
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
> ---
>  drivers/cpufreq/tegra124-cpufreq.c | 59 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 59 insertions(+)

Hi Rafael,

I was originally planning to pick this up into the Tegra tree with your
and Viresh's Acked-by, but I now realize that there aren't any
dependencies between this and the rest of the series, so this can also
go through your tree.

Do you have any preference on how to merge it? I've already Acked this
from the Tegra side, so feel free to pick it up if that's what you
prefer.

Thierry

> diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c
> index 4f0c637b3b49..7a1ea6fdcab6 100644
> --- a/drivers/cpufreq/tegra124-cpufreq.c
> +++ b/drivers/cpufreq/tegra124-cpufreq.c
> @@ -6,6 +6,7 @@
>  #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
>  
>  #include <linux/clk.h>
> +#include <linux/cpufreq.h>
>  #include <linux/err.h>
>  #include <linux/init.h>
>  #include <linux/kernel.h>
> @@ -128,8 +129,66 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
>  	return ret;
>  }
>  
> +static int __maybe_unused tegra124_cpufreq_suspend(struct device *dev)
> +{
> +	struct tegra124_cpufreq_priv *priv = dev_get_drvdata(dev);
> +	int err;
> +
> +	/*
> +	 * PLLP rate 408Mhz is below the CPU Fmax at Vmin and is safe to
> +	 * use during suspend and resume. So, switch the CPU clock source
> +	 * to PLLP and disable DFLL.
> +	 */
> +	err = clk_set_parent(priv->cpu_clk, priv->pllp_clk);
> +	if (err < 0) {
> +		dev_err(dev, "failed to reparent to PLLP: %d\n", err);
> +		return err;
> +	}
> +
> +	clk_disable_unprepare(priv->dfll_clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused tegra124_cpufreq_resume(struct device *dev)
> +{
> +	struct tegra124_cpufreq_priv *priv = dev_get_drvdata(dev);
> +	int err;
> +
> +	/*
> +	 * Warmboot code powers up the CPU with PLLP clock source.
> +	 * Enable DFLL clock and switch CPU clock source back to DFLL.
> +	 */
> +	err = clk_prepare_enable(priv->dfll_clk);
> +	if (err < 0) {
> +		dev_err(dev, "failed to enable DFLL clock for CPU: %d\n", err);
> +		goto disable_cpufreq;
> +	}
> +
> +	err = clk_set_parent(priv->cpu_clk, priv->dfll_clk);
> +	if (err < 0) {
> +		dev_err(dev, "failed to reparent to DFLL clock: %d\n", err);
> +		goto disable_dfll;
> +	}
> +
> +	return 0;
> +
> +disable_dfll:
> +	clk_disable_unprepare(priv->dfll_clk);
> +disable_cpufreq:
> +	disable_cpufreq();
> +
> +	return err;
> +}
> +
> +static const struct dev_pm_ops tegra124_cpufreq_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(tegra124_cpufreq_suspend,
> +				tegra124_cpufreq_resume)
> +};
> +
>  static struct platform_driver tegra124_cpufreq_platdrv = {
>  	.driver.name	= "cpufreq-tegra124",
> +	.driver.pm	= &tegra124_cpufreq_pm_ops,
>  	.probe		= tegra124_cpufreq_probe,
>  };
>  
> -- 
> 2.7.4
> 

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

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

* Re: [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-08-16 19:41 ` [PATCH v9 07/22] clk: Add API to get index of the clock parent Sowjanya Komatineni
@ 2019-11-06 23:10   ` Stephen Boyd
  2019-11-07  0:54     ` Dmitry Osipenko
  0 siblings, 1 reply; 41+ messages in thread
From: Stephen Boyd @ 2019-11-06 23:10 UTC (permalink / raw)
  To: Sowjanya Komatineni, jason, jonathanh, linus.walleij,
	marc.zyngier, mark.rutland, stefan, tglx, thierry.reding
  Cc: pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, skomatineni, linux-tegra, linux-kernel, mperttunen,
	spatra, robh+dt, digetx, devicetree, rjw, viresh.kumar, linux-pm

Quoting Sowjanya Komatineni (2019-08-16 12:41:52)
> This patch adds an API clk_hw_get_parent_index to get index of the
> clock parent to use during the clock restore operations on system
> resume.

Is there a reason we can't save the clk hw index at suspend time by
reading the hardware to understand the current parent? The parent index
typically doesn't matter unless we're trying to communicate something
from the framework to the provider driver. Put another way, I would
think the provider driver can figure out the index itself without having
to go through the framework to do so.

> 
> Reviewed-by: Thierry Reding <treding@nvidia.com>
> Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index cbcc333aec84..12ad0e9b8591 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1645,6 +1645,23 @@ static int clk_fetch_parent_index(struct clk_core *core,
>         return i;
>  }
>  
> +/**
> + * clk_hw_get_parent_index - return the index of parent clock
> + * @hw: clk_hw associated with the clk being consumed
> + * @parent_hw: clk_hw associated with the parent of clk
> + *
> + * Fetches and returns the index of parent clock.
> + * If hw or parent_hw is NULL, returns -EINVAL.
> + */
> +int clk_hw_get_parent_index(struct clk_hw *hw, struct clk_hw *parent_hw)
> +{
> +       if (!hw || !parent_hw)
> +               return -EINVAL;

The caller should be ashamed if they call this with NULL arguments.
I'd prefer we skip this check and we get an oops.

> +
> +       return clk_fetch_parent_index(hw->core, parent_hw->core);
> +}
> +EXPORT_SYMBOL_GPL(clk_hw_get_parent_index);
> +
>  /*
>   * Update the orphan status of @core and all its children.
>   */

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

* Re: [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-11-06 23:10   ` Stephen Boyd
@ 2019-11-07  0:54     ` Dmitry Osipenko
  2019-11-07 15:21       ` Thierry Reding
  0 siblings, 1 reply; 41+ messages in thread
From: Dmitry Osipenko @ 2019-11-07  0:54 UTC (permalink / raw)
  To: Stephen Boyd, Sowjanya Komatineni, jason, jonathanh,
	linus.walleij, marc.zyngier, mark.rutland, stefan, tglx,
	thierry.reding
  Cc: pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, linux-tegra, linux-kernel, mperttunen, spatra, robh+dt,
	devicetree, rjw, viresh.kumar, linux-pm

07.11.2019 02:10, Stephen Boyd пишет:
> Quoting Sowjanya Komatineni (2019-08-16 12:41:52)
>> This patch adds an API clk_hw_get_parent_index to get index of the
>> clock parent to use during the clock restore operations on system
>> resume.
>  
> Is there a reason we can't save the clk hw index at suspend time by
> reading the hardware to understand the current parent? The parent index
> typically doesn't matter unless we're trying to communicate something
> from the framework to the provider driver. Put another way, I would
> think the provider driver can figure out the index itself without having
> to go through the framework to do so.

Isn't it a bit wasteful to duplicate information about the parent within
a provider if framework already has that info? The whole point of this
new API is to allow providers to avoid that unnecessary duplication.

Please note that clk_hw_get_parent_index is getting used only at the
resume time and not at suspend.

[snip]

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

* Re: [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-11-07  0:54     ` Dmitry Osipenko
@ 2019-11-07 15:21       ` Thierry Reding
  2019-11-07 19:19         ` Stephen Boyd
  0 siblings, 1 reply; 41+ messages in thread
From: Thierry Reding @ 2019-11-07 15:21 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Stephen Boyd, Sowjanya Komatineni, jason, jonathanh,
	linus.walleij, marc.zyngier, mark.rutland, stefan, tglx,
	pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, linux-tegra, linux-kernel, mperttunen, spatra, robh+dt,
	devicetree, rjw, viresh.kumar, linux-pm

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

On Thu, Nov 07, 2019 at 03:54:03AM +0300, Dmitry Osipenko wrote:
> 07.11.2019 02:10, Stephen Boyd пишет:
> > Quoting Sowjanya Komatineni (2019-08-16 12:41:52)
> >> This patch adds an API clk_hw_get_parent_index to get index of the
> >> clock parent to use during the clock restore operations on system
> >> resume.
> >  
> > Is there a reason we can't save the clk hw index at suspend time by
> > reading the hardware to understand the current parent? The parent index
> > typically doesn't matter unless we're trying to communicate something
> > from the framework to the provider driver. Put another way, I would
> > think the provider driver can figure out the index itself without having
> > to go through the framework to do so.
> 
> Isn't it a bit wasteful to duplicate information about the parent within
> a provider if framework already has that info? The whole point of this
> new API is to allow providers to avoid that unnecessary duplication.
> 
> Please note that clk_hw_get_parent_index is getting used only at the
> resume time and not at suspend.

I agree with this. All of the information that we need is already cached
in the framework. Doing this in the driver would mean essentially adding
a "saved parent" field along with code to read the value at suspend time
to the three types of clocks that currently use this core helper.

That's certainly something that we *can* do, but it doesn't sound like a
better option than simply querying the framework for the value that we
need.

Thierry

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

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

* Re: [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-11-07 15:21       ` Thierry Reding
@ 2019-11-07 19:19         ` Stephen Boyd
  2019-11-08 10:11           ` Thierry Reding
  0 siblings, 1 reply; 41+ messages in thread
From: Stephen Boyd @ 2019-11-07 19:19 UTC (permalink / raw)
  To: Dmitry Osipenko, Thierry Reding
  Cc: Sowjanya Komatineni, jason, jonathanh, linus.walleij,
	marc.zyngier, mark.rutland, stefan, tglx, pdeschrijver, pgaikwad,
	linux-clk, linux-gpio, jckuo, josephl, talho, linux-tegra,
	linux-kernel, mperttunen, spatra, robh+dt, devicetree, rjw,
	viresh.kumar, linux-pm

Quoting Thierry Reding (2019-11-07 07:21:15)
> On Thu, Nov 07, 2019 at 03:54:03AM +0300, Dmitry Osipenko wrote:
> > 07.11.2019 02:10, Stephen Boyd пишет:
> > > Quoting Sowjanya Komatineni (2019-08-16 12:41:52)
> > >> This patch adds an API clk_hw_get_parent_index to get index of the
> > >> clock parent to use during the clock restore operations on system
> > >> resume.
> > >  
> > > Is there a reason we can't save the clk hw index at suspend time by
> > > reading the hardware to understand the current parent? The parent index
> > > typically doesn't matter unless we're trying to communicate something
> > > from the framework to the provider driver. Put another way, I would
> > > think the provider driver can figure out the index itself without having
> > > to go through the framework to do so.
> > 
> > Isn't it a bit wasteful to duplicate information about the parent within
> > a provider if framework already has that info? The whole point of this
> > new API is to allow providers to avoid that unnecessary duplication.
> > 
> > Please note that clk_hw_get_parent_index is getting used only at the
> > resume time and not at suspend.
> 
> I agree with this. All of the information that we need is already cached
> in the framework. Doing this in the driver would mean essentially adding
> a "saved parent" field along with code to read the value at suspend time
> to the three types of clocks that currently use this core helper.

Don't we already have a "saved parent" field by storing the pointer to
the clk_hw?

> 
> That's certainly something that we *can* do, but it doesn't sound like a
> better option than simply querying the framework for the value that we
> need.
> 

Let me say this another way. Why does this driver want to know the index
that the framework uses for some clk_hw pointer? Perhaps it happens to
align with the same value that hardware uses, but I still don't
understand why the driver wants to know what the framework has decided
is the index for some clk_hw pointer.

Or is this something like "give me the index for the parent that the
framework thinks I currently have but in reality don't have anymore
because the register contents were wiped and we need to reparent it"? A
generic API to get any index for this question is overkill and we should
consider adding some sort of API like clk_hw_get_current_parent_index(),
or a framework flag that tells the framework this parent is incorrect
and we need to call the .set_parent() op again to reconfigure it.


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

* Re: [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-11-07 19:19         ` Stephen Boyd
@ 2019-11-08 10:11           ` Thierry Reding
  2019-11-08 18:12             ` Stephen Boyd
  0 siblings, 1 reply; 41+ messages in thread
From: Thierry Reding @ 2019-11-08 10:11 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Dmitry Osipenko, Sowjanya Komatineni, jason, jonathanh,
	linus.walleij, marc.zyngier, mark.rutland, stefan, tglx,
	pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, linux-tegra, linux-kernel, mperttunen, spatra, robh+dt,
	devicetree, rjw, viresh.kumar, linux-pm

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

On Thu, Nov 07, 2019 at 11:19:32AM -0800, Stephen Boyd wrote:
> Quoting Thierry Reding (2019-11-07 07:21:15)
> > On Thu, Nov 07, 2019 at 03:54:03AM +0300, Dmitry Osipenko wrote:
> > > 07.11.2019 02:10, Stephen Boyd пишет:
> > > > Quoting Sowjanya Komatineni (2019-08-16 12:41:52)
> > > >> This patch adds an API clk_hw_get_parent_index to get index of the
> > > >> clock parent to use during the clock restore operations on system
> > > >> resume.
> > > >  
> > > > Is there a reason we can't save the clk hw index at suspend time by
> > > > reading the hardware to understand the current parent? The parent index
> > > > typically doesn't matter unless we're trying to communicate something
> > > > from the framework to the provider driver. Put another way, I would
> > > > think the provider driver can figure out the index itself without having
> > > > to go through the framework to do so.
> > > 
> > > Isn't it a bit wasteful to duplicate information about the parent within
> > > a provider if framework already has that info? The whole point of this
> > > new API is to allow providers to avoid that unnecessary duplication.
> > > 
> > > Please note that clk_hw_get_parent_index is getting used only at the
> > > resume time and not at suspend.
> > 
> > I agree with this. All of the information that we need is already cached
> > in the framework. Doing this in the driver would mean essentially adding
> > a "saved parent" field along with code to read the value at suspend time
> > to the three types of clocks that currently use this core helper.
> 
> Don't we already have a "saved parent" field by storing the pointer to
> the clk_hw?
> 
> > 
> > That's certainly something that we *can* do, but it doesn't sound like a
> > better option than simply querying the framework for the value that we
> > need.
> > 
> 
> Let me say this another way. Why does this driver want to know the index
> that the framework uses for some clk_hw pointer? Perhaps it happens to
> align with the same value that hardware uses, but I still don't
> understand why the driver wants to know what the framework has decided
> is the index for some clk_hw pointer.
> 
> Or is this something like "give me the index for the parent that the
> framework thinks I currently have but in reality don't have anymore
> because the register contents were wiped and we need to reparent it"?

Yeah, that's exactly what this is being used for. It's used to restore
the parent/child relationship during resume after the registers have
been wiped during supend.

> A generic API to get any index for this question is overkill and we should
> consider adding some sort of API like clk_hw_get_current_parent_index(),
> or a framework flag that tells the framework this parent is incorrect
> and we need to call the .set_parent() op again to reconfigure it.

Okay, I think I see what you're saying. The current implementation does
carry a bit of a risk because users could be calling this function with
any arbitrary pair of struct clk_hw *, even completely unrelated ones.

How about we turn it into this instead:

	/**
	 * clk_hw_get_parent_index - return the index of the parent clock
	 * @hw: clk_hw associated with the clk being consumed
	 *
	 * Fetches and returns the index of parent clock. Returns -EINVAL if the given
	 * clock does not have a current parent.
	 */
	int clk_hw_get_parent_index(struct clk_hw *hw)
	{
		struct clk_hw *parent = clk_hw_get_parent(hw);

		if (!parent)
			return -EINVAL;

		return clk_fetch_parent_index(hw->core, parent->core);
	}
	EXPORT_SYMBOL_GPL(clk_hw_get_parent_index);

I think that has the advantage that we can't pass it a parent that's not
really a parent. There's still the slightly weird case where the clock
doesn't have a current parent, but hopefully that's something we are not
going to encounter much. After all this only makes sense to be called on
mux clocks and they always do have a parent by definition.

Perhaps we should be more explicit and wrap that !parent conditional in
a WARN_ON()? In my local patches I do that at the call sites because
they are all functions returning void, so we'd be silently ignoring the
cases, but I think it may make sense to have it in the core.

Any thoughts?

Thierry

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

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

* Re: [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-11-08 10:11           ` Thierry Reding
@ 2019-11-08 18:12             ` Stephen Boyd
  2019-11-08 18:55               ` Thierry Reding
  0 siblings, 1 reply; 41+ messages in thread
From: Stephen Boyd @ 2019-11-08 18:12 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Dmitry Osipenko, Sowjanya Komatineni, jason, jonathanh,
	linus.walleij, marc.zyngier, mark.rutland, stefan, tglx,
	pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, linux-tegra, linux-kernel, mperttunen, spatra, robh+dt,
	devicetree, rjw, viresh.kumar, linux-pm

Quoting Thierry Reding (2019-11-08 02:11:16)
> On Thu, Nov 07, 2019 at 11:19:32AM -0800, Stephen Boyd wrote:
> > Quoting Thierry Reding (2019-11-07 07:21:15)
> > > On Thu, Nov 07, 2019 at 03:54:03AM +0300, Dmitry Osipenko wrote:
> > > > 07.11.2019 02:10, Stephen Boyd пишет:
> > > > > Quoting Sowjanya Komatineni (2019-08-16 12:41:52)
> > > > >> This patch adds an API clk_hw_get_parent_index to get index of the
> > > > >> clock parent to use during the clock restore operations on system
> > > > >> resume.
> > > > >  
> > > > > Is there a reason we can't save the clk hw index at suspend time by
> > > > > reading the hardware to understand the current parent? The parent index
> > > > > typically doesn't matter unless we're trying to communicate something
> > > > > from the framework to the provider driver. Put another way, I would
> > > > > think the provider driver can figure out the index itself without having
> > > > > to go through the framework to do so.
> > > > 
> > > > Isn't it a bit wasteful to duplicate information about the parent within
> > > > a provider if framework already has that info? The whole point of this
> > > > new API is to allow providers to avoid that unnecessary duplication.
> > > > 
> > > > Please note that clk_hw_get_parent_index is getting used only at the
> > > > resume time and not at suspend.
> > > 
> > > I agree with this. All of the information that we need is already cached
> > > in the framework. Doing this in the driver would mean essentially adding
> > > a "saved parent" field along with code to read the value at suspend time
> > > to the three types of clocks that currently use this core helper.
> > 
> > Don't we already have a "saved parent" field by storing the pointer to
> > the clk_hw?
> > 
> > > 
> > > That's certainly something that we *can* do, but it doesn't sound like a
> > > better option than simply querying the framework for the value that we
> > > need.
> > > 
> > 
> > Let me say this another way. Why does this driver want to know the index
> > that the framework uses for some clk_hw pointer? Perhaps it happens to
> > align with the same value that hardware uses, but I still don't
> > understand why the driver wants to know what the framework has decided
> > is the index for some clk_hw pointer.
> > 
> > Or is this something like "give me the index for the parent that the
> > framework thinks I currently have but in reality don't have anymore
> > because the register contents were wiped and we need to reparent it"?
> 
> Yeah, that's exactly what this is being used for. It's used to restore
> the parent/child relationship during resume after the registers have
> been wiped during supend.

Ok cool. Our whole suspend/resume and save/restore story hasn't really
been well thought out so we may want to pull all this logic into the
core one day. For now it's OK to do the heavy lifting from provider
drivers until someone gets a better grasp on how this should all work.

> 
> > A generic API to get any index for this question is overkill and we should
> > consider adding some sort of API like clk_hw_get_current_parent_index(),
> > or a framework flag that tells the framework this parent is incorrect
> > and we need to call the .set_parent() op again to reconfigure it.
> 
> Okay, I think I see what you're saying. The current implementation does
> carry a bit of a risk because users could be calling this function with
> any arbitrary pair of struct clk_hw *, even completely unrelated ones.
> 
> How about we turn it into this instead:
> 
>         /**
>          * clk_hw_get_parent_index - return the index of the parent clock
>          * @hw: clk_hw associated with the clk being consumed
>          *
>          * Fetches and returns the index of parent clock. Returns -EINVAL if the given
>          * clock does not have a current parent.
>          */
>         int clk_hw_get_parent_index(struct clk_hw *hw)
>         {
>                 struct clk_hw *parent = clk_hw_get_parent(hw);
> 
>                 if (!parent)
>                         return -EINVAL;
> 
>                 return clk_fetch_parent_index(hw->core, parent->core);
>         }
>         EXPORT_SYMBOL_GPL(clk_hw_get_parent_index);
> 
> I think that has the advantage that we can't pass it a parent that's not
> really a parent. There's still the slightly weird case where the clock
> doesn't have a current parent, but hopefully that's something we are not
> going to encounter much. After all this only makes sense to be called on
> mux clocks and they always do have a parent by definition.

Right.

> 
> Perhaps we should be more explicit and wrap that !parent conditional in
> a WARN_ON()? In my local patches I do that at the call sites because
> they are all functions returning void, so we'd be silently ignoring the
> cases, but I think it may make sense to have it in the core.
> 

Sure a WARN_ON() sounds fair. That will not take the whole task down
and makes sure that drivers aren't doing something incorrect. Otherwise,
this looks good and we can optimize by caching the parent index later if
we really need to.


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

* Re: [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-11-08 18:12             ` Stephen Boyd
@ 2019-11-08 18:55               ` Thierry Reding
  2019-11-08 21:15                 ` Stephen Boyd
  0 siblings, 1 reply; 41+ messages in thread
From: Thierry Reding @ 2019-11-08 18:55 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Dmitry Osipenko, Sowjanya Komatineni, jason, jonathanh,
	linus.walleij, marc.zyngier, mark.rutland, stefan, tglx,
	pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, linux-tegra, linux-kernel, mperttunen, spatra, robh+dt,
	devicetree, rjw, viresh.kumar, linux-pm

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

On Fri, Nov 08, 2019 at 10:12:49AM -0800, Stephen Boyd wrote:
> Quoting Thierry Reding (2019-11-08 02:11:16)
> > On Thu, Nov 07, 2019 at 11:19:32AM -0800, Stephen Boyd wrote:
> > > Quoting Thierry Reding (2019-11-07 07:21:15)
> > > > On Thu, Nov 07, 2019 at 03:54:03AM +0300, Dmitry Osipenko wrote:
> > > > > 07.11.2019 02:10, Stephen Boyd пишет:
> > > > > > Quoting Sowjanya Komatineni (2019-08-16 12:41:52)
> > > > > >> This patch adds an API clk_hw_get_parent_index to get index of the
> > > > > >> clock parent to use during the clock restore operations on system
> > > > > >> resume.
> > > > > >  
> > > > > > Is there a reason we can't save the clk hw index at suspend time by
> > > > > > reading the hardware to understand the current parent? The parent index
> > > > > > typically doesn't matter unless we're trying to communicate something
> > > > > > from the framework to the provider driver. Put another way, I would
> > > > > > think the provider driver can figure out the index itself without having
> > > > > > to go through the framework to do so.
> > > > > 
> > > > > Isn't it a bit wasteful to duplicate information about the parent within
> > > > > a provider if framework already has that info? The whole point of this
> > > > > new API is to allow providers to avoid that unnecessary duplication.
> > > > > 
> > > > > Please note that clk_hw_get_parent_index is getting used only at the
> > > > > resume time and not at suspend.
> > > > 
> > > > I agree with this. All of the information that we need is already cached
> > > > in the framework. Doing this in the driver would mean essentially adding
> > > > a "saved parent" field along with code to read the value at suspend time
> > > > to the three types of clocks that currently use this core helper.
> > > 
> > > Don't we already have a "saved parent" field by storing the pointer to
> > > the clk_hw?
> > > 
> > > > 
> > > > That's certainly something that we *can* do, but it doesn't sound like a
> > > > better option than simply querying the framework for the value that we
> > > > need.
> > > > 
> > > 
> > > Let me say this another way. Why does this driver want to know the index
> > > that the framework uses for some clk_hw pointer? Perhaps it happens to
> > > align with the same value that hardware uses, but I still don't
> > > understand why the driver wants to know what the framework has decided
> > > is the index for some clk_hw pointer.
> > > 
> > > Or is this something like "give me the index for the parent that the
> > > framework thinks I currently have but in reality don't have anymore
> > > because the register contents were wiped and we need to reparent it"?
> > 
> > Yeah, that's exactly what this is being used for. It's used to restore
> > the parent/child relationship during resume after the registers have
> > been wiped during supend.
> 
> Ok cool. Our whole suspend/resume and save/restore story hasn't really
> been well thought out so we may want to pull all this logic into the
> core one day. For now it's OK to do the heavy lifting from provider
> drivers until someone gets a better grasp on how this should all work.

Ah, that would explain why I was scratching my head trying to understand
how exactly this was supposed to work. It did feel like there was some
infrastructure there, but looking around there wasn't a very consistent
usage pattern that I could find.

I think suspend/resume is always a little tricky. For example the clocks
may required a slightly different logical sequences between SoCs. Maybe
even different types of clocks have different needs. We seem to have a
bit of that on Tegra alone already. Without having delved into this too
much, it seems to me like the core can't do a whole lot without stepping
(potentially) on drivers' toes.

The current save_context/restore_context seems to be mostly that,
though, so I think it's a good starting point. You're right that we may
eventually see clearer patterns appear.

> > > A generic API to get any index for this question is overkill and we should
> > > consider adding some sort of API like clk_hw_get_current_parent_index(),
> > > or a framework flag that tells the framework this parent is incorrect
> > > and we need to call the .set_parent() op again to reconfigure it.
> > 
> > Okay, I think I see what you're saying. The current implementation does
> > carry a bit of a risk because users could be calling this function with
> > any arbitrary pair of struct clk_hw *, even completely unrelated ones.
> > 
> > How about we turn it into this instead:
> > 
> >         /**
> >          * clk_hw_get_parent_index - return the index of the parent clock
> >          * @hw: clk_hw associated with the clk being consumed
> >          *
> >          * Fetches and returns the index of parent clock. Returns -EINVAL if the given
> >          * clock does not have a current parent.
> >          */
> >         int clk_hw_get_parent_index(struct clk_hw *hw)
> >         {
> >                 struct clk_hw *parent = clk_hw_get_parent(hw);
> > 
> >                 if (!parent)
> >                         return -EINVAL;
> > 
> >                 return clk_fetch_parent_index(hw->core, parent->core);
> >         }
> >         EXPORT_SYMBOL_GPL(clk_hw_get_parent_index);
> > 
> > I think that has the advantage that we can't pass it a parent that's not
> > really a parent. There's still the slightly weird case where the clock
> > doesn't have a current parent, but hopefully that's something we are not
> > going to encounter much. After all this only makes sense to be called on
> > mux clocks and they always do have a parent by definition.
> 
> Right.
> 
> > 
> > Perhaps we should be more explicit and wrap that !parent conditional in
> > a WARN_ON()? In my local patches I do that at the call sites because
> > they are all functions returning void, so we'd be silently ignoring the
> > cases, but I think it may make sense to have it in the core.
> > 
> 
> Sure a WARN_ON() sounds fair. That will not take the whole task down
> and makes sure that drivers aren't doing something incorrect. Otherwise,
> this looks good and we can optimize by caching the parent index later if
> we really need to.

Okay, great. I'll go replace the above patch in the branch that I have.
I'm not sure if you saw it, but I had sent this in a pull request for
v5.5-rc1 about a week ago because I've got Tegra clock driver patches
that depend on this. I can replace this patch with the above proposal
and update the Tegra clock driver branch and then resend the two pull
requests.

Does that sound like a plan?

Thierry

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

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

* Re: [PATCH v9 07/22] clk: Add API to get index of the clock parent
  2019-11-08 18:55               ` Thierry Reding
@ 2019-11-08 21:15                 ` Stephen Boyd
  0 siblings, 0 replies; 41+ messages in thread
From: Stephen Boyd @ 2019-11-08 21:15 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Dmitry Osipenko, Sowjanya Komatineni, jason, jonathanh,
	linus.walleij, marc.zyngier, mark.rutland, stefan, tglx,
	pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, linux-tegra, linux-kernel, mperttunen, spatra, robh+dt,
	devicetree, rjw, viresh.kumar, linux-pm

Quoting Thierry Reding (2019-11-08 10:55:03)
> On Fri, Nov 08, 2019 at 10:12:49AM -0800, Stephen Boyd wrote:
> > 
> > Sure a WARN_ON() sounds fair. That will not take the whole task down
> > and makes sure that drivers aren't doing something incorrect. Otherwise,
> > this looks good and we can optimize by caching the parent index later if
> > we really need to.
> 
> Okay, great. I'll go replace the above patch in the branch that I have.
> I'm not sure if you saw it, but I had sent this in a pull request for
> v5.5-rc1 about a week ago because I've got Tegra clock driver patches
> that depend on this. I can replace this patch with the above proposal
> and update the Tegra clock driver branch and then resend the two pull
> requests.
> 
> Does that sound like a plan?
> 

Yes please refresh the PRs. I don't think anything else is concerning
but I'll go do a sweep over the Tegra patches right now.


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

* Re: [PATCH v9 11/22] clk: tegra: clk-dfll: Add suspend and resume support
  2019-08-16 19:41 ` [PATCH v9 11/22] clk: tegra: clk-dfll: Add suspend and resume support Sowjanya Komatineni
@ 2019-11-08 21:20   ` Stephen Boyd
  2019-11-08 23:38     ` Dmitry Osipenko
  0 siblings, 1 reply; 41+ messages in thread
From: Stephen Boyd @ 2019-11-08 21:20 UTC (permalink / raw)
  To: Sowjanya Komatineni, jason, jonathanh, linus.walleij,
	marc.zyngier, mark.rutland, stefan, tglx, thierry.reding
  Cc: pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, skomatineni, linux-tegra, linux-kernel, mperttunen,
	spatra, robh+dt, digetx, devicetree, rjw, viresh.kumar, linux-pm

Quoting Sowjanya Komatineni (2019-08-16 12:41:56)
> diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
> index f8688c2ddf1a..c051d92c2bbf 100644
> --- a/drivers/clk/tegra/clk-dfll.c
> +++ b/drivers/clk/tegra/clk-dfll.c
> @@ -1487,6 +1487,7 @@ static int dfll_init(struct tegra_dfll *td)
>         td->last_unrounded_rate = 0;
>  
>         pm_runtime_enable(td->dev);
> +       pm_runtime_irq_safe(td->dev);

Why irq_safe? It would be good to mention it in the commit text or
something.

>         pm_runtime_get_sync(td->dev);
>  
>         dfll_set_mode(td, DFLL_DISABLED);
> @@ -1513,6 +1514,61 @@ static int dfll_init(struct tegra_dfll *td)
>         return ret;
>  }
>  
> +/**
> + * tegra_dfll_suspend - check DFLL is disabled
> + * @dev: DFLL device *
> + *
> + * DFLL clock should be disabled by the CPUFreq driver. So, make
> + * sure it is disabled and disable all clocks needed by the DFLL.
> + */
> +int tegra_dfll_suspend(struct device *dev)
> +{
> +       struct tegra_dfll *td = dev_get_drvdata(dev);
> +
> +       if (dfll_is_running(td)) {
> +               dev_err(td->dev, "DFLL still enabled while suspending\n");
> +               return -EBUSY;
> +       }
> +
> +       reset_control_assert(td->dvco_rst);
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(tegra_dfll_suspend);
> +
> +/**
> + * tegra_dfll_resume - reinitialize DFLL on resume
> + * @dev: DFLL instance

I prefer this description for tegra_dfll_suspend's 'dev' argument.

> + *
> + * DFLL is disabled and reset during suspend and resume.
> + * So, reinitialize the DFLL IP block back for use.
> + * DFLL clock is enabled later in closed loop mode by CPUFreq
> + * driver before switching its clock source to DFLL output.
> + */
> +int tegra_dfll_resume(struct device *dev)
> +{
> +       struct tegra_dfll *td = dev_get_drvdata(dev);
> +
> +       reset_control_deassert(td->dvco_rst);
> +
> +       pm_runtime_get_sync(td->dev);
> +
> +       dfll_set_mode(td, DFLL_DISABLED);
> +       dfll_set_default_params(td);

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

* Re: [PATCH v9 11/22] clk: tegra: clk-dfll: Add suspend and resume support
  2019-11-08 21:20   ` Stephen Boyd
@ 2019-11-08 23:38     ` Dmitry Osipenko
  0 siblings, 0 replies; 41+ messages in thread
From: Dmitry Osipenko @ 2019-11-08 23:38 UTC (permalink / raw)
  To: Stephen Boyd, Sowjanya Komatineni, jason, jonathanh,
	linus.walleij, marc.zyngier, mark.rutland, stefan, tglx,
	thierry.reding
  Cc: pdeschrijver, pgaikwad, linux-clk, linux-gpio, jckuo, josephl,
	talho, linux-tegra, linux-kernel, mperttunen, spatra, robh+dt,
	devicetree, rjw, viresh.kumar, linux-pm

09.11.2019 00:20, Stephen Boyd пишет:
> Quoting Sowjanya Komatineni (2019-08-16 12:41:56)
>> diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
>> index f8688c2ddf1a..c051d92c2bbf 100644
>> --- a/drivers/clk/tegra/clk-dfll.c
>> +++ b/drivers/clk/tegra/clk-dfll.c
>> @@ -1487,6 +1487,7 @@ static int dfll_init(struct tegra_dfll *td)
>>         td->last_unrounded_rate = 0;
>>  
>>         pm_runtime_enable(td->dev);
>> +       pm_runtime_irq_safe(td->dev);
> 
> Why irq_safe? It would be good to mention it in the commit text or
> something.

That's a good catch. It was somewhat relevant for some older version of
this patch, but should be irrelevant now.

[snip]

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

end of thread, other threads:[~2019-11-08 23:38 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-16 19:41 [PATCH v9 00/22] SC7 entry and exit support for Tegra210 Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 01/22] pinctrl: tegra: Fix write barrier placement in pmx_writel Sowjanya Komatineni
2019-08-18 22:20   ` Linus Walleij
2019-08-16 19:41 ` [PATCH v9 02/22] pinctrl: tegra: Flush pinctrl writes during resume Sowjanya Komatineni
2019-08-18 22:20   ` Linus Walleij
2019-08-16 19:41 ` [PATCH v9 03/22] clk: tegra: divider: Save and restore divider rate Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 04/22] clk: tegra: pllout: Save and restore pllout context Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 05/22] clk: tegra: pll: Save and restore pll context Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 06/22] clk: tegra: Support for OSC context save and restore Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 07/22] clk: Add API to get index of the clock parent Sowjanya Komatineni
2019-11-06 23:10   ` Stephen Boyd
2019-11-07  0:54     ` Dmitry Osipenko
2019-11-07 15:21       ` Thierry Reding
2019-11-07 19:19         ` Stephen Boyd
2019-11-08 10:11           ` Thierry Reding
2019-11-08 18:12             ` Stephen Boyd
2019-11-08 18:55               ` Thierry Reding
2019-11-08 21:15                 ` Stephen Boyd
2019-08-16 19:41 ` [PATCH v9 08/22] clk: tegra: periph: Add restore_context support Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 09/22] clk: tegra: clk-super: Fix to enable PLLP branches to CPU Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 10/22] clk: tegra: clk-super: Add restore-context support Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 11/22] clk: tegra: clk-dfll: Add suspend and resume support Sowjanya Komatineni
2019-11-08 21:20   ` Stephen Boyd
2019-11-08 23:38     ` Dmitry Osipenko
2019-08-16 19:41 ` [PATCH v9 12/22] cpufreq: tegra124: " Sowjanya Komatineni
2019-11-02 14:42   ` Thierry Reding
2019-08-16 19:41 ` [PATCH v9 13/22] clk: tegra210: Use fence_udelay during PLLU init Sowjanya Komatineni
2019-08-16 19:41 ` [PATCH v9 14/22] clk: tegra: Share clk and rst register defines with Tegra clock driver Sowjanya Komatineni
2019-08-16 19:42 ` [PATCH v9 15/22] clk: tegra210: Add suspend and resume support Sowjanya Komatineni
2019-08-19 16:47   ` Dmitry Osipenko
2019-08-16 19:42 ` [PATCH v9 16/22] soc/tegra: pmc: Allow to support more tegras wake Sowjanya Komatineni
2019-08-16 19:42 ` [PATCH v9 17/22] soc/tegra: pmc: Add pmc wake support for tegra210 Sowjanya Komatineni
2019-08-16 19:42 ` [PATCH v9 18/22] arm64: tegra: Enable wake from deep sleep on RTC alarm Sowjanya Komatineni
2019-08-16 19:42 ` [PATCH v9 19/22] soc/tegra: pmc: Configure core power request polarity Sowjanya Komatineni
2019-08-16 19:42 ` [PATCH v9 20/22] soc/tegra: pmc: Configure deep sleep control settings Sowjanya Komatineni
2019-08-19 16:48   ` Dmitry Osipenko
2019-08-19 18:20     ` Sowjanya Komatineni
2019-08-19 19:07       ` Sowjanya Komatineni
2019-08-19 19:33         ` Dmitry Osipenko
2019-08-16 19:42 ` [PATCH v9 21/22] arm64: dts: tegra210-p2180: Jetson TX1 SC7 timings Sowjanya Komatineni
2019-08-16 19:42 ` [PATCH v9 22/22] arm64: dts: tegra210-p3450: Jetson Nano " Sowjanya Komatineni

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).