12.08.2019 20:28, Sowjanya Komatineni ÐÐÑÐÑ:
On 8/12/19 9:25 AM, Dmitry Osipenko wrote:It looks to me that the tegra_clk_periph_force_on() could be made local to the
11.08.2019 22:15, Sowjanya Komatineni ÐÐÑÐÑ:yes all reserved bits of clk_enb register is 0. This should not be set to 1.
On 8/11/19 10:39 AM, Dmitry Osipenko wrote:Could you please check whether the reserved bits are RAZ (read as zero)?
09.08.2019 21:40, Sowjanya Komatineni ÐÐÑÐÑ:No, we cannot move to tegra_clk_periph_regs as its in tegra/clk.c and is common for all
On 8/9/19 11:18 AM, Dmitry Osipenko wrote:Okay.
09.08.2019 19:19, Sowjanya Komatineni ÐÐÑÐÑ:No its internal to design
On 8/9/19 6:56 AM, Dmitry Osipenko wrote:Okay, it should be explained in the comment.
09.08.2019 2:46, Sowjanya Komatineni ÐÐÑÐÑ:Will rename as valid_mask.
This patch adds support for clk: tegra210: suspend-resume.Should be more natural to have a "valid_mask" instead of "rsvd_mask".
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@xxxxxxxxxx>
---
ÂÂÂ drivers/clk/tegra/clk-tegra210.c | 103 +++++++++++++++++++++++++++++++++++++--
ÂÂÂ drivers/clk/tegra/clk.cÂÂÂÂÂÂÂÂÂ |Â 64 ++++++++++++++++++++++++
ÂÂÂ drivers/clk/tegra/clk.hÂÂÂÂÂÂÂÂÂ |ÂÂ 3 ++
ÂÂÂ 3 files changed, 166 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 998bf60b219a..8dd6f4f4debb 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;
ÂÂÂÂÂÂÂ }
@@ -3288,6 +3298,84 @@ static void tegra210_disable_cpu_clock(u32 cpu)
ÂÂÂ }
ÂÂÂ Â #ifdef CONFIG_PM_SLEEP
+/*
+ * This array lists mask values for each peripheral clk bank
+ * to mask out reserved bits during the clocks state restore
+ * on SC7 resume to prevent accidental writes to these reserved
+ * bits.
+ */
+static u32 periph_clk_rsvd_mask[TEGRA210_CAR_BANK_COUNT] = {
What's actually wrong with touching of the reserved bits? They must be NO-OP.. or the
reserved bits are actually some kind of "secret" bits? If those bits have some use-case
outside of Silicon HW (like FPGA simulation), then this doesn't matter for upstream
and you
have to keep the workaround locally in the downstream kernel or whatever.
some bits in these registers are undefined and is not good to write to these bits as
they
can cause pslverr.
Is it possible to disable trapping of changing the undefined bits?
Also, what about to move the valid_mask into struct tegra_clk_periph_regs?
tegra.
Reserved bits are different on tegra chips so should come from Tegra chip specific clock
driver like
clk-tegra210 for Tegra210.
[snip]
As I will be changing to variable name to valid_mask instead of reserved mask, will also
change values to valid mask so it can be used directly to write to clk_enb for enabling all
peripherals clks.
clk-tegra210.c and then the raw clk_enb values could be written directly instead of having
the clk_enb[] array, probably that will be a bit cleaner
.