[v3,6/8] clk: tegra20: Turn EMC clock gate into divider

Message ID 20180617145539.4758-7-digetx@gmail.com
State New
Headers show
Series
  • Tegra20 External Memory Controller driver
Related show

Commit Message

Dmitry Osipenko June 17, 2018, 2:55 p.m.
Kernel should never gate the EMC clock as it causes immediate lockup, so
removing clk-gate functionality doesn't affect anything. Turning EMC clk
gate into divider allows to implement glitch-less EMC scaling, avoiding
reparenting to a backup clock.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/clk-tegra20.c | 36 ++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 10 deletions(-)

Comments

Stephen Boyd July 9, 2018, midnight | #1
Quoting Dmitry Osipenko (2018-06-17 07:55:37)
> Kernel should never gate the EMC clock as it causes immediate lockup, so
> removing clk-gate functionality doesn't affect anything. Turning EMC clk
> gate into divider allows to implement glitch-less EMC scaling, avoiding
> reparenting to a backup clock.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---

Who's supposed to apply this? Me? Thierry? The "To:" line is not
useful when every maintainer is there.

> diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
> index cc857d4d4a86..2bd35418716a 100644
> --- a/drivers/clk/tegra/clk-tegra20.c
> +++ b/drivers/clk/tegra/clk-tegra20.c
> @@ -799,6 +798,31 @@ static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
>         TEGRA_INIT_DATA_NODIV("disp2",  mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26,  0, TEGRA20_CLK_DISP2),
>  };
>  
> +static void __init tegra20_emc_clk_init(void)
> +{
> +       struct clk *clk;
> +
> +       clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
> +                              ARRAY_SIZE(mux_pllmcp_clkm),
> +                              CLK_SET_RATE_NO_REPARENT,
> +                              clk_base + CLK_SOURCE_EMC,
> +                              30, 2, 0, &emc_lock);
> +
> +       clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
> +                                   &emc_lock);
> +       clks[TEGRA20_CLK_MC] = clk;
> +
> +       /*
> +        * Note that 'emc_mux' source and 'emc' rate shouldn't be changed at
> +        * the same time due to a HW bug, this won't happen because we're
> +        * defining 'emc_mux' and 'emc' as a distinct clocks.

s/ a//

--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Dmitry Osipenko July 9, 2018, 11:52 a.m. | #2
On Monday, 9 July 2018 03:00:17 MSK Stephen Boyd wrote:
> Quoting Dmitry Osipenko (2018-06-17 07:55:37)
> 
> > Kernel should never gate the EMC clock as it causes immediate lockup, so
> > removing clk-gate functionality doesn't affect anything. Turning EMC clk
> > gate into divider allows to implement glitch-less EMC scaling, avoiding
> > reparenting to a backup clock.
> > 
> > Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> > Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> > ---
> 
> Who's supposed to apply this? Me? Thierry? The "To:" line is not
> useful when every maintainer is there.

That's up to you and Thierry to decide. Perhaps it would be less churning if 
you'll give your ack on the 'clk:' patches and Thierry will handle the whole 
series on his own.

> > diff --git a/drivers/clk/tegra/clk-tegra20.c
> > b/drivers/clk/tegra/clk-tegra20.c index cc857d4d4a86..2bd35418716a 100644
> > --- a/drivers/clk/tegra/clk-tegra20.c
> > +++ b/drivers/clk/tegra/clk-tegra20.c
> > @@ -799,6 +798,31 @@ static struct tegra_periph_init_data
> > tegra_periph_nodiv_clk_list[] = {> 
> >         TEGRA_INIT_DATA_NODIV("disp2",  mux_pllpdc_clkm, CLK_SOURCE_DISP2,
> >         30, 2, 26,  0, TEGRA20_CLK_DISP2),>  
> >  };
> > 
> > +static void __init tegra20_emc_clk_init(void)
> > +{
> > +       struct clk *clk;
> > +
> > +       clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
> > +                              ARRAY_SIZE(mux_pllmcp_clkm),
> > +                              CLK_SET_RATE_NO_REPARENT,
> > +                              clk_base + CLK_SOURCE_EMC,
> > +                              30, 2, 0, &emc_lock);
> > +
> > +       clk = tegra_clk_register_mc("mc", "emc_mux", clk_base +
> > CLK_SOURCE_EMC, +                                   &emc_lock);
> > +       clks[TEGRA20_CLK_MC] = clk;
> > +
> > +       /*
> > +        * Note that 'emc_mux' source and 'emc' rate shouldn't be changed
> > at +        * the same time due to a HW bug, this won't happen because
> > we're +        * defining 'emc_mux' and 'emc' as a distinct clocks.
> 
> s/ a//

I can adjust the comment and re-spin the series if something more important 
will pop up, otherwise that could addressed while applying the patch. 



--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index cc857d4d4a86..2bd35418716a 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -578,7 +578,6 @@  static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true },
 	[tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true },
 	[tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true },
-	[tegra_clk_emc] = { .dt_id = TEGRA20_CLK_EMC, .present = true },
 };
 
 static unsigned long tegra20_clk_measure_input_freq(void)
@@ -799,6 +798,31 @@  static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
 	TEGRA_INIT_DATA_NODIV("disp2",	mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26,  0, TEGRA20_CLK_DISP2),
 };
 
+static void __init tegra20_emc_clk_init(void)
+{
+	struct clk *clk;
+
+	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
+			       ARRAY_SIZE(mux_pllmcp_clkm),
+			       CLK_SET_RATE_NO_REPARENT,
+			       clk_base + CLK_SOURCE_EMC,
+			       30, 2, 0, &emc_lock);
+
+	clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+				    &emc_lock);
+	clks[TEGRA20_CLK_MC] = clk;
+
+	/*
+	 * Note that 'emc_mux' source and 'emc' rate shouldn't be changed at
+	 * the same time due to a HW bug, this won't happen because we're
+	 * defining 'emc_mux' and 'emc' as a distinct clocks.
+	 */
+	clk = clk_register_divider(NULL, "emc", "emc_mux", CLK_IS_CRITICAL,
+				   clk_base + CLK_SOURCE_EMC, 0, 7,
+				   0, &emc_lock);
+	clks[TEGRA20_CLK_EMC] = clk;
+}
+
 static void __init tegra20_periph_clk_init(void)
 {
 	struct tegra_periph_init_data *data;
@@ -812,15 +836,7 @@  static void __init tegra20_periph_clk_init(void)
 	clks[TEGRA20_CLK_AC97] = clk;
 
 	/* emc */
-	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
-			       ARRAY_SIZE(mux_pllmcp_clkm),
-			       CLK_SET_RATE_NO_REPARENT,
-			       clk_base + CLK_SOURCE_EMC,
-			       30, 2, 0, &emc_lock);
-
-	clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
-				    &emc_lock);
-	clks[TEGRA20_CLK_MC] = clk;
+	tegra20_emc_clk_init();
 
 	/* dsi */
 	clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,