summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx/busfreq-imx.c
diff options
context:
space:
mode:
authorJuan Gutierrez <juan.gutierrez@nxp.com>2017-01-24 09:59:22 -0600
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:25:46 +0800
commitf3d1c3037ea790e7c51594b5ed0880f140c334df (patch)
treee68b594a152e6ecc3a5e81a8955ca885986b9924 /arch/arm/mach-imx/busfreq-imx.c
parent4f4d131dbf9900643c8ca0887c5a706fcdd41470 (diff)
MXSCM-240-1 arm: imx: set mmdc clk rate on high audio freq on i.mx6q lpddr2
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>
Diffstat (limited to 'arch/arm/mach-imx/busfreq-imx.c')
-rw-r--r--arch/arm/mach-imx/busfreq-imx.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/busfreq-imx.c b/arch/arm/mach-imx/busfreq-imx.c
index adc1a0e19a78..909a70dadf94 100644
--- a/arch/arm/mach-imx/busfreq-imx.c
+++ b/arch/arm/mach-imx/busfreq-imx.c
@@ -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,13 @@ 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)) {