2019-06-18 07:49:29

by Sowjanya Komatineni

[permalink] [raw]
Subject: [PATCH V3 00/17] SC7 entry and exit support for Tegra210

This patch series includes Tegra210 deepsleep 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.

[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 (17):
irqchip: tegra: do not disable COP IRQ during suspend
pinctrl: tegra: add suspend and resume support
gpio: tegra: use resume_noirq for tegra gpio resume
clk: tegra: save and restore divider rate
clk: tegra: pllout: save and restore pllout context
clk: tegra: pll: save and restore pll context
clk: tegra: save and restore CPU and System clocks context
clk: tegra: add support for peripheral clock suspend and resume
clk: tegra: support for saving and restoring OSC clock context
clk: tegra: add suspend resume support for DFLL
clk: tegra210: support for Tegra210 clocks suspend and resume
soc/tegra: pmc: allow support for more tegra 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

arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi | 7 +
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 5 +-
drivers/clk/tegra/clk-dfll.c | 78 +++++++++
drivers/clk/tegra/clk-dfll.h | 2 +
drivers/clk/tegra/clk-divider.c | 23 +++
drivers/clk/tegra/clk-pll-out.c | 28 ++++
drivers/clk/tegra/clk-pll.c | 115 +++++++++----
drivers/clk/tegra/clk-tegra-fixed.c | 14 ++
drivers/clk/tegra/clk-tegra-super-gen4.c | 4 -
drivers/clk/tegra/clk-tegra210.c | 218 ++++++++++++++++++++++++-
drivers/clk/tegra/clk.c | 150 ++++++++++++++++-
drivers/clk/tegra/clk.h | 29 +++-
drivers/gpio/gpio-tegra.c | 17 +-
drivers/irqchip/irq-tegra.c | 21 ++-
drivers/pinctrl/tegra/pinctrl-tegra.c | 62 +++++++
drivers/pinctrl/tegra/pinctrl-tegra.h | 5 +
drivers/pinctrl/tegra/pinctrl-tegra114.c | 1 +
drivers/pinctrl/tegra/pinctrl-tegra124.c | 1 +
drivers/pinctrl/tegra/pinctrl-tegra20.c | 1 +
drivers/pinctrl/tegra/pinctrl-tegra210.c | 13 ++
drivers/pinctrl/tegra/pinctrl-tegra30.c | 1 +
drivers/soc/tegra/pmc.c | 143 +++++++++++++++-
22 files changed, 880 insertions(+), 58 deletions(-)

--
2.7.4


2019-06-18 07:49:41

by Sowjanya Komatineni

[permalink] [raw]
Subject: [PATCH V3 12/17] soc/tegra: pmc: allow support for more tegra wake

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.

Signed-off-by: Sowjanya Komatineni <[email protected]>
---
drivers/soc/tegra/pmc.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index edd4fe06810f..e87f29a35fcf 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;
@@ -1919,7 +1921,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;
@@ -1951,7 +1953,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;
@@ -2005,8 +2007,10 @@ 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;
+ if (pmc->soc->irq_set_type)
+ pmc->irq.irq_set_type = pmc->soc->irq_set_type;
+ if (pmc->soc->irq_set_wake)
+ 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);
@@ -2679,6 +2683,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

2019-06-18 07:50:04

by Sowjanya Komatineni

[permalink] [raw]
Subject: [PATCH V3 04/17] clk: tegra: save and restore divider rate

This patch implements context save and restore for clock divider.

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

So during suspend entry the context of clock divider is saved and
on resume context is restored back for normal operation.

Signed-off-by: Sowjanya Komatineni <[email protected]>
---
drivers/clk/tegra/clk-divider.c | 23 +++++++++++++++++++++++
drivers/clk/tegra/clk.h | 2 ++
2 files changed, 25 insertions(+)

diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
index e76731fb7d69..ecb7ff9ce97e 100644
--- a/drivers/clk/tegra/clk-divider.c
+++ b/drivers/clk/tegra/clk-divider.c
@@ -109,10 +109,33 @@ static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}

+static int clk_divider_save_context(struct clk_hw *hw)
+{
+ struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+ struct clk_hw *parent = clk_hw_get_parent(hw);
+ unsigned long parent_rate = clk_hw_get_rate(parent);
+
+ divider->rate = clk_frac_div_recalc_rate(hw, parent_rate);
+
+ return 0;
+}
+
+static void clk_divider_restore_context(struct clk_hw *hw)
+{
+ struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+ struct clk_hw *parent = clk_hw_get_parent(hw);
+ unsigned long parent_rate = clk_hw_get_rate(parent);
+
+ if (clk_frac_div_set_rate(hw, divider->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,
+ .save_context = clk_divider_save_context,
+ .restore_context = clk_divider_restore_context,
};

struct clk *tegra_clk_register_divider(const char *name,
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 905bf1096558..83623f5f55f3 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -42,6 +42,7 @@ struct clk *tegra_clk_register_sync_source(const char *name,
* @width: width of the divider bit field
* @frac_width: width of the fractional bit field
* @lock: register lock
+ * @rate: rate during suspend and resume
*
* Flags:
* TEGRA_DIVIDER_ROUND_UP - This flags indicates to round up the divider value.
@@ -62,6 +63,7 @@ struct tegra_clk_frac_div {
u8 width;
u8 frac_width;
spinlock_t *lock;
+ unsigned long rate;
};

#define to_clk_frac_div(_hw) container_of(_hw, struct tegra_clk_frac_div, hw)
--
2.7.4

2019-06-18 09:27:06

by Marc Zyngier

[permalink] [raw]
Subject: Re: [PATCH V3 12/17] soc/tegra: pmc: allow support for more tegra wake

On 18/06/2019 08:46, Sowjanya Komatineni wrote:
> 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.
>
> Signed-off-by: Sowjanya Komatineni <[email protected]>
> ---
> drivers/soc/tegra/pmc.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index edd4fe06810f..e87f29a35fcf 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;
> @@ -1919,7 +1921,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;
> @@ -1951,7 +1953,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;
> @@ -2005,8 +2007,10 @@ 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;
> + if (pmc->soc->irq_set_type)
> + pmc->irq.irq_set_type = pmc->soc->irq_set_type;
> + if (pmc->soc->irq_set_wake)
> + pmc->irq.irq_set_wake = pmc->soc->irq_set_wake;

Two cases: either the value is non NULL, and we assign it, or it is
NULL, and we leave it to what it was, presumably NULL. I guess you can
drop the both ifs.

>
> pmc->domain = irq_domain_add_hierarchy(parent, 0, 96, pmc->dev->of_node,
> &tegra_pmc_irq_domain_ops, pmc);
> @@ -2679,6 +2683,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,
>

Thanks,

M.
--
Jazz is not dead. It just smells funny...

2019-06-18 11:41:20

by Thierry Reding

[permalink] [raw]
Subject: Re: [PATCH V3 04/17] clk: tegra: save and restore divider rate

On Tue, Jun 18, 2019 at 12:46:18AM -0700, Sowjanya Komatineni wrote:
> This patch implements context save and restore for clock divider.
>
> During system suspend, core power goes off and looses the settings
> of the Tegra CAR controller registers.
>
> So during suspend entry the context of clock divider is saved and
> on resume context is restored back for normal operation.
>
> Signed-off-by: Sowjanya Komatineni <[email protected]>
> ---
> drivers/clk/tegra/clk-divider.c | 23 +++++++++++++++++++++++
> drivers/clk/tegra/clk.h | 2 ++
> 2 files changed, 25 insertions(+)

Acked-by: Thierry Reding <[email protected]>


Attachments:
(No filename) (658.00 B)
signature.asc (849.00 B)
Download all attachments