aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx/busfreq-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-imx/busfreq-imx.c')
-rw-r--r--arch/arm/mach-imx/busfreq-imx.c152
1 files changed, 105 insertions, 47 deletions
diff --git a/arch/arm/mach-imx/busfreq-imx.c b/arch/arm/mach-imx/busfreq-imx.c
index b6aa072..5298af7 100644
--- a/arch/arm/mach-imx/busfreq-imx.c
+++ b/arch/arm/mach-imx/busfreq-imx.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2017 NXP.
+ * Copyright 2018 NXP.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -71,6 +72,9 @@ static int origin_arm_volt, origin_soc_volt;
extern unsigned long iram_tlb_phys_addr;
extern int unsigned long iram_tlb_base_addr;
+/*
+ * Bus frequency management by Linux
+ */
extern int init_mmdc_lpddr2_settings(struct platform_device *dev);
extern int init_mmdc_lpddr2_settings_mx6q(struct platform_device *dev);
extern int init_mmdc_ddr3_settings_imx6_up(struct platform_device *dev);
@@ -81,6 +85,23 @@ extern int update_ddr_freq_imx6_up(int ddr_rate);
extern int update_lpddr2_freq(int ddr_rate);
extern int update_lpddr2_freq_smp(int ddr_rate);
+#ifdef CONFIG_OPTEE
+/*
+ * Bus frequency management by OPTEE OS
+ */
+extern int update_freq_optee(int ddr_rate);
+extern int init_freq_optee(struct platform_device *busfreq_pdev);
+#endif
+
+/**
+ * @brief Functions to init and update the busfreq function of
+ * device and memory type
+ */
+static struct busfreq_func {
+ int (*init)(struct platform_device *dev);
+ int (*update)(int ddr_rate);
+} busfreq_func = {NULL, NULL};
+
DEFINE_MUTEX(bus_freq_mutex);
static struct clk *osc_clk;
@@ -239,10 +260,10 @@ static void enter_lpm_imx6_up(void)
/* Need to ensure that PLL2_PFD_400M is kept ON. */
clk_prepare_enable(pll2_400_clk);
if (ddr_type == IMX_DDR_TYPE_DDR3)
- update_ddr_freq_imx6_up(LOW_AUDIO_CLK);
+ busfreq_func.update(LOW_AUDIO_CLK);
else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
- update_lpddr2_freq(HIGH_AUDIO_CLK);
+ busfreq_func.update(HIGH_AUDIO_CLK);
clk_set_parent(periph2_clk2_sel_clk, pll3_clk);
clk_set_parent(periph2_pre_clk, pll2_400_clk);
clk_set_parent(periph2_clk, periph2_pre_clk);
@@ -270,11 +291,8 @@ static void enter_lpm_imx6_up(void)
low_bus_freq_mode = 0;
cur_bus_freq_mode = BUS_FREQ_AUDIO;
} else {
- if (ddr_type == IMX_DDR_TYPE_DDR3)
- update_ddr_freq_imx6_up(LPAPM_CLK);
- else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
- ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
- update_lpddr2_freq(LPAPM_CLK);
+ busfreq_func.update(LPAPM_CLK);
+
clk_set_parent(periph2_clk2_sel_clk, osc_clk);
clk_set_parent(periph2_clk, periph2_clk2_clk);
@@ -300,9 +318,9 @@ static void enter_lpm_imx6_smp(void)
/* Need to ensure that PLL2_PFD_400M is kept ON. */
clk_prepare_enable(pll2_400_clk);
if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
- update_ddr_freq_imx_smp(LOW_AUDIO_CLK);
+ busfreq_func.update(LOW_AUDIO_CLK);
else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
- update_lpddr2_freq_smp(HIGH_AUDIO_CLK);
+ busfreq_func.update(HIGH_AUDIO_CLK);
/* Make sure periph clk's parent also got updated */
clk_set_parent(periph_clk2_sel_clk, pll3_clk);
if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
@@ -329,10 +347,8 @@ static void enter_lpm_imx6_smp(void)
low_bus_freq_mode = 0;
cur_bus_freq_mode = BUS_FREQ_AUDIO;
} else {
- if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
- update_ddr_freq_imx_smp(LPAPM_CLK);
- else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
- update_lpddr2_freq_smp(LPAPM_CLK);
+ busfreq_func.update(LPAPM_CLK);
+
/* Make sure periph clk's parent also got updated */
clk_set_parent(periph_clk2_sel_clk, osc_clk);
/* Set periph_clk parent to OSC via periph_clk2_sel */
@@ -372,10 +388,8 @@ static void exit_lpm_imx6_up(void)
/* set periph_clk2 to pll3 */
clk_set_parent(periph_clk2_sel_clk, pll3_clk);
- if (ddr_type == IMX_DDR_TYPE_DDR3)
- update_ddr_freq_imx6_up(ddr_normal_rate);
- else if (ddr_type == IMX_DDR_TYPE_LPDDR2 || ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
- update_lpddr2_freq(ddr_normal_rate);
+ busfreq_func.update(ddr_normal_rate);
+
/* correct parent info after ddr freq change in asm code */
clk_set_parent(periph2_pre_clk, pll2_400_clk);
clk_set_parent(periph2_clk, periph2_pre_clk);
@@ -409,10 +423,9 @@ static void exit_lpm_imx6_smp(void)
periph_clk_parent = pll2_400_clk;
clk_prepare_enable(pll2_400_clk);
- if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
- update_ddr_freq_imx_smp(ddr_normal_rate);
- else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
- update_lpddr2_freq_smp(ddr_normal_rate);
+
+ busfreq_func.update(ddr_normal_rate);
+
/* Make sure periph clk's parent also got updated */
clk_set_parent(periph_clk2_sel_clk, pll3_clk);
clk_set_parent(periph_pre_clk, periph_clk_parent);
@@ -456,7 +469,7 @@ static void enter_lpm_imx6sl(void)
clk_set_rate(ahb_clk, LPAPM_CLK / 3);
/* Set up DDR to 100MHz. */
- update_lpddr2_freq(HIGH_AUDIO_CLK);
+ busfreq_func.update(HIGH_AUDIO_CLK);
/* Fix the clock tree in kernel */
clk_set_parent(periph2_pre_clk, pll2_200_clk);
@@ -552,8 +565,9 @@ static void enter_lpm_imx6sl(void)
* is requested sometime later, the change is ignored.
*/
clk_set_parent(step_clk, osc_clk);
+
/* Now set DDR to 24MHz. */
- update_lpddr2_freq(LPAPM_CLK);
+ busfreq_func.update(LPAPM_CLK);
/*
* Fix the clock tree in kernel.
@@ -581,7 +595,7 @@ static void enter_lpm_imx6sl(void)
static void exit_lpm_imx6sl(void)
{
/* Change DDR freq in IRAM. */
- update_lpddr2_freq(ddr_normal_rate);
+ busfreq_func.update(ddr_normal_rate);
/*
* Fix the clock tree in kernel.
@@ -630,7 +644,7 @@ static void enter_lpm_imx7d(void)
clk_prepare_enable(pfd2_270m);
if (audio_bus_count) {
clk_prepare_enable(pfd0_392m);
- update_ddr_freq_imx_smp(HIGH_AUDIO_CLK);
+ busfreq_func.update(HIGH_AUDIO_CLK);
clk_set_parent(dram_alt_sel, pfd0_392m);
clk_set_parent(dram_root, dram_alt_root);
@@ -644,7 +658,7 @@ static void enter_lpm_imx7d(void)
low_bus_freq_mode = 0;
cur_bus_freq_mode = BUS_FREQ_AUDIO;
} else {
- update_ddr_freq_imx_smp(LPAPM_CLK);
+ busfreq_func.update(LPAPM_CLK);
clk_set_parent(dram_alt_sel, osc_clk);
clk_set_parent(dram_root, dram_alt_root);
@@ -666,7 +680,7 @@ static void exit_lpm_imx7d(void)
clk_set_rate(ahb_clk, LPAPM_CLK / 2);
clk_set_parent(ahb_sel_clk, pfd2_270m);
- update_ddr_freq_imx_smp(ddr_normal_rate);
+ busfreq_func.update(ddr_normal_rate);
clk_set_parent(dram_root, pll_dram);
}
@@ -1106,6 +1120,10 @@ static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
static int busfreq_probe(struct platform_device *pdev)
{
u32 err;
+#ifdef CONFIG_OPTEE
+ struct device_node *node_optee = 0;
+ uint32_t busfreq_val;
+#endif
busfreq_dev = &pdev->dev;
@@ -1305,35 +1323,75 @@ static int busfreq_probe(struct platform_device *pdev)
ddr_normal_rate = 400000000;
pr_info("ddr3 normal rate changed to 400MHz for TO1.1.\n");
}
- err = init_ddrc_ddr_settings(pdev);
+ busfreq_func.init = &init_ddrc_ddr_settings;
+ busfreq_func.update = &update_ddr_freq_imx_smp;
} else if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull() ||
cpu_is_imx6sll()) {
ddr_type = imx_mmdc_get_ddr_type();
- if (ddr_type == IMX_DDR_TYPE_DDR3)
- err = init_mmdc_ddr3_settings_imx6_up(pdev);
- else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
- ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3)
- err = init_mmdc_lpddr2_settings(pdev);
+ if (ddr_type == IMX_DDR_TYPE_DDR3) {
+ busfreq_func.init = &init_mmdc_ddr3_settings_imx6_up;
+ busfreq_func.update = &update_ddr_freq_imx6_up;
+ } else if (ddr_type == IMX_DDR_TYPE_LPDDR2 ||
+ ddr_type == IMX_MMDC_DDR_TYPE_LPDDR3) {
+ busfreq_func.init = &init_mmdc_lpddr2_settings;
+ busfreq_func.update = &update_lpddr2_freq;
+ }
} else if (cpu_is_imx6q() || cpu_is_imx6dl()) {
ddr_type = imx_mmdc_get_ddr_type();
- if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
- err = init_mmdc_ddr3_settings_imx6_smp(pdev);
- else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
- err = init_mmdc_lpddr2_settings_mx6q(pdev);
+ if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3) {
+ busfreq_func.init = &init_mmdc_ddr3_settings_imx6_smp;
+ busfreq_func.update = &update_ddr_freq_imx_smp;
+ } else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2) {
+ busfreq_func.init = &init_mmdc_lpddr2_settings_mx6q;
+ busfreq_func.update = &update_lpddr2_freq_smp;
+ }
} else if (cpu_is_imx6sl()) {
- err = init_mmdc_lpddr2_settings(pdev);
+ busfreq_func.init = &init_mmdc_lpddr2_settings;
+ busfreq_func.update = &update_lpddr2_freq;
}
- if (cpu_is_imx6sx()) {
- /* if M4 is enabled and rate > 24MHz, add high bus count */
- if (imx_src_is_m4_enabled() &&
- (clk_get_rate(m4_clk) > LPAPM_CLK))
- high_bus_count++;
+#ifdef CONFIG_OPTEE
+ /*
+ * Find the OPTEE node in the DT and look for the
+ * busfreq property.
+ * If property present and set to 1, busfreq is done by
+ * calling the OPTEE OS
+ */
+ node_optee = of_find_compatible_node(NULL, NULL, "linaro,optee-tz");
+
+ if (node_optee) {
+ if (of_property_read_u32(node_optee, "busfreq",
+ &busfreq_val) == 0) {
+ pr_info("OPTEE busfreq %s",
+ (busfreq_val ? "Supported" : "Not Supported"));
+ if (busfreq_val) {
+ busfreq_func.init = &init_freq_optee;
+ busfreq_func.update = &update_freq_optee;
+ }
+ }
}
+#endif
- if (cpu_is_imx7d() && imx_src_is_m4_enabled()) {
- high_bus_count++;
- imx_mu_lpm_ready(true);
+ if (busfreq_func.init)
+ err = busfreq_func.init(pdev);
+ else
+ err = -EINVAL;
+
+ if (!err) {
+ if (cpu_is_imx6sx()) {
+ /*
+ * If M4 is enabled and rate > 24MHz,
+ * add high bus count
+ */
+ if (imx_src_is_m4_enabled() &&
+ (clk_get_rate(m4_clk) > LPAPM_CLK))
+ high_bus_count++;
+ }
+
+ if (cpu_is_imx7d() && imx_src_is_m4_enabled()) {
+ high_bus_count++;
+ imx_mu_lpm_ready(true);
+ }
}
if (err) {
@@ -1369,7 +1427,7 @@ static int __init busfreq_init(void)
if (platform_driver_register(&busfreq_driver) != 0)
return -ENODEV;
- printk(KERN_INFO "Bus freq driver module loaded\n");
+ pr_info("Bus freq driver module loaded\n");
#endif
return 0;
}