MXSCM-240-1 arm: imx: set mmdc clk rate on high audio freq on i.mx6q lpddr2
authorJuan Gutierrez <juan.gutierrez@nxp.com>
Tue, 24 Jan 2017 15:59:22 +0000 (09:59 -0600)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:58:23 +0000 (14:58 -0500)
As periph_pre_clk's parent is not changed when going to high audio frequency,
the clk framework will not update its children's frequency. This cause
the the mmdc_ch0_axi clk_rate does not reflect the right frequency when
reading it from userspace like:

cat /sys/kernel/debug/clk/mmdc_ch0_axi/clk_rate

Since the mmdc_ch0_axi_podf is changed in the asm busfreq routine, then the
mmdc rate needs to be updated to make sure clk tree is right, although it
will not do any change to hardware.

To do this the clk_get_rate api is used to update the mmdc_clk which
needs to be dereferenced from the device tree. Since for other cases like
ddr3, the update of the rate of the mmdc clk is not needed, the absense of
this parameter (on the device tree) don't make throw an error, instead, NULL
checks are used to check if the mmdc clk needs to be updated or not.

Signed-off-by: Juan Gutierrez <juan.gutierrez@nxp.com>
arch/arm/mach-imx/busfreq-imx.c

index 35ff38b..1c297a0 100644 (file)
@@ -302,6 +302,21 @@ static void enter_lpm_imx6_smp(void)
                else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
                        clk_set_parent(periph_pre_clk, pll2_400_clk);
                clk_set_parent(periph_clk, periph_pre_clk);
+
+               /*
+                * As periph_pre_clk's parent is not changed from
+                * high mode to audio mode on lpddr2, the clk framework
+                * will not update its children's freq, but we
+                * change the mmdc_ch0_axi podf in asm code, so here
+                * need to update mmdc rate to make sure clk
+                * tree is right, although it will not do any
+                * change to hardware. Calling get_rate will only call
+                * the .rate_recalc which is all we need.
+                */
+               if (high_bus_freq_mode && mmdc_clk)
+                       if (ddr_type == IMX_DDR_TYPE_LPDDR2)
+                               clk_get_rate(mmdc_clk);
+
                audio_bus_freq_mode = 1;
                low_bus_freq_mode = 0;
                cur_bus_freq_mode = BUS_FREQ_AUDIO;
@@ -399,6 +414,20 @@ static void exit_lpm_imx6_smp(void)
                clk_set_parent(axi_alt_sel_clk, pll3_pfd1_540m_clk);
                clk_set_parent(axi_sel_clk, axi_alt_sel_clk);
        }
+       /*
+        * As periph_pre_clk's parent is not changed from
+        * high mode to audio mode on lpddr2, the clk framework
+        * will not update its children's freq, but we
+        * change the mmdc_ch0_axi podf in asm code, so here
+        * need to update mmdc rate to make sure clk
+        * tree is right, although it will not do any
+        * change to hardware. Calling get_rate will only call
+        * the .rate_recalc which is all we need.
+        */
+       if (audio_bus_freq_mode && mmdc_clk)
+               if (ddr_type == IMX_DDR_TYPE_LPDDR2)
+                       clk_get_rate(mmdc_clk);
+
        clk_disable_unprepare(pll2_400_clk);
        if (audio_bus_freq_mode)
                clk_disable_unprepare(pll2_400_clk);
@@ -1125,6 +1154,12 @@ static int busfreq_probe(struct platform_device *pdev)
                }
        }
 
+       if (cpu_is_imx6q())
+               mmdc_clk = devm_clk_get(&pdev->dev, "mmdc");
+               if (IS_ERR(mmdc_clk)) {
+                       mmdc_clk = NULL;
+               }
+
        if (cpu_is_imx6sx()) {
                m4_clk = devm_clk_get(&pdev->dev, "m4");
                if (IS_ERR(m4_clk)) {