summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2022-10-12 18:06:29 +0800
committerYe Li <ye.li@nxp.com>2022-10-14 17:43:10 +0800
commit032fab5e1275422559b81bb79af44218c3faa3c2 (patch)
treeff990c413f80af254982119261f1bd15b0346726 /arch
parent53689e4f7db578fc6e476a3af9a123f7dd3806c3 (diff)
LFU-421 imx93_evk: Add imx93 low drive mode support on 11x11 EVK
Add a static u-boot config for i.MX93 low drive mode support. When low drive mode is enabled, VDD_SOC is set to 0.75V. Bus clocks, A55 core clock (900Mhz), DDR clock (1866MTS), and some peripherals clocks (USDHC/FLEXSPI/PDM/DISP_PIX/CAM_PIX) must decrease to meet max frequencies in low drive mode. The patch also updates kernel's DTB for the media AXI clock and USDHC root clocks. Signed-off-by: Ye Li <ye.li@nxp.com> Reviewed-by: Peng Fan <peng.fan@nxp.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/imx9/Kconfig5
-rw-r--r--arch/arm/mach-imx/imx9/clock.c65
-rw-r--r--arch/arm/mach-imx/imx9/soc.c87
3 files changed, 150 insertions, 7 deletions
diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig
index d4dca5fd95..f4fc1ac5ce 100644
--- a/arch/arm/mach-imx/imx9/Kconfig
+++ b/arch/arm/mach-imx/imx9/Kconfig
@@ -5,6 +5,11 @@ config AHAB_BOOT
help
This option enables the support for AHAB secure boot.
+config IMX9_LOW_DRIVE_MODE
+ bool "Configure to i.MX9 low drive mode"
+ help
+ This option enables the settings for iMX9 low drive mode.
+
config IMX9
bool
select ARCH_EARLY_INIT_R
diff --git a/arch/arm/mach-imx/imx9/clock.c b/arch/arm/mach-imx/imx9/clock.c
index 62f2f1b93b..909a770e1c 100644
--- a/arch/arm/mach-imx/imx9/clock.c
+++ b/arch/arm/mach-imx/imx9/clock.c
@@ -553,6 +553,13 @@ void set_arm_core_max_clk(void)
ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_PLL);
}
+void set_arm_core_low_drive_clk(void)
+{
+ ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_CCM);
+ configure_intpll(ARM_PLL_CLK, 900000000);
+ ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_PLL);
+}
+
unsigned int mxc_get_clock(enum mxc_clock clk)
{
switch (clk) {
@@ -625,21 +632,26 @@ void init_uart_clk(u32 index)
void init_clk_usdhc(u32 index)
{
- /* 400 Mhz */
+ u32 div;
+ if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE))
+ div = 3; /* 266.67 Mhz */
+ else
+ div = 2; /* 400 Mhz */
+
switch (index) {
case 0:
ccm_lpcg_on(CCGR_USDHC1, 0);
- ccm_clk_root_cfg(USDHC1_CLK_ROOT, SYS_PLL_PFD1, 2);
+ ccm_clk_root_cfg(USDHC1_CLK_ROOT, SYS_PLL_PFD1, div);
ccm_lpcg_on(CCGR_USDHC1, 1);
break;
case 1:
ccm_lpcg_on(CCGR_USDHC2, 0);
- ccm_clk_root_cfg(USDHC2_CLK_ROOT, SYS_PLL_PFD1, 2);
+ ccm_clk_root_cfg(USDHC2_CLK_ROOT, SYS_PLL_PFD1, div);
ccm_lpcg_on(CCGR_USDHC2, 1);
break;
case 2:
ccm_lpcg_on(CCGR_USDHC3, 0);
- ccm_clk_root_cfg(USDHC3_CLK_ROOT, SYS_PLL_PFD1, 2);
+ ccm_clk_root_cfg(USDHC3_CLK_ROOT, SYS_PLL_PFD1, div);
ccm_lpcg_on(CCGR_USDHC3, 1);
break;
default:
@@ -698,7 +710,36 @@ void dram_disable_bypass(void)
}
#endif
-int clock_init(void)
+void bus_clock_init_low_drive(void)
+{
+ /* Set A55 clk to 500M */
+ ccm_clk_root_cfg(ARM_A55_CLK_ROOT, SYS_PLL_PFD0, 2);
+ /* Set A55 periphal to 200M */
+ ccm_clk_root_cfg(ARM_A55_PERIPH_CLK_ROOT, SYS_PLL_PFD1, 4);
+ /* Set A55 mtr bus to 133M */
+ ccm_clk_root_cfg(ARM_A55_MTR_BUS_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+
+ /* Sentinel to 133M */
+ ccm_clk_root_cfg(SENTINEL_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+ /* Bus_wakeup to 133M */
+ ccm_clk_root_cfg(BUS_WAKEUP_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+ /* Bus_AON to 133M */
+ ccm_clk_root_cfg(BUS_AON_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+ /* M33 to 133M */
+ ccm_clk_root_cfg(M33_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+ /* WAKEUP_AXI to 200M */
+ ccm_clk_root_cfg(WAKEUP_AXI_CLK_ROOT, SYS_PLL_PFD1, 4);
+ /* SWO TRACE to 133M */
+ ccm_clk_root_cfg(SWO_TRACE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+ /* M33 systetick to 24M */
+ ccm_clk_root_cfg(M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1);
+ /* NIC to 250M */
+ ccm_clk_root_cfg(NIC_CLK_ROOT, SYS_PLL_PFD0, 4);
+ /* NIC_APB to 133M */
+ ccm_clk_root_cfg(NIC_APB_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+}
+
+void bus_clock_init(void)
{
/* Set A55 periphal to 333M */
ccm_clk_root_cfg(ARM_A55_PERIPH_CLK_ROOT, SYS_PLL_PFD0, 3);
@@ -717,12 +758,22 @@ int clock_init(void)
ccm_clk_root_cfg(WAKEUP_AXI_CLK_ROOT, SYS_PLL_PFD2, 2);
/* SWO TRACE to 133M */
ccm_clk_root_cfg(SWO_TRACE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
- /* M33 systetick to 133M */
- ccm_clk_root_cfg(M33_SYSTICK_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+ /* M33 systetick to 24M */
+ ccm_clk_root_cfg(M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1);
/* NIC to 400M */
ccm_clk_root_cfg(NIC_CLK_ROOT, SYS_PLL_PFD1, 2);
/* NIC_APB to 133M */
ccm_clk_root_cfg(NIC_APB_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3);
+}
+
+int clock_init(void)
+{
+ if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)){
+ bus_clock_init_low_drive();
+ set_arm_core_low_drive_clk();
+ } else {
+ bus_clock_init();
+ }
/* allow for non-secure access */
int i;
diff --git a/arch/arm/mach-imx/imx9/soc.c b/arch/arm/mach-imx/imx9/soc.c
index 11220799ae..6f2613d5bf 100644
--- a/arch/arm/mach-imx/imx9/soc.c
+++ b/arch/arm/mach-imx/imx9/soc.c
@@ -726,6 +726,91 @@ static int disable_cpu_nodes(void *blob, u32 disabled_cores)
return 0;
}
+struct low_drive_freq_entry {
+ const char *node_path;
+ u32 clk;
+ u32 new_rate;
+};
+
+static int low_drive_fdt_fix_clock(void *fdt, int node_off, u32 clk_index, u32 new_rate)
+{
+#define MAX_ASSIGNED_CLKS 8
+ int cnt, j;
+ u32 assignedclks[MAX_ASSIGNED_CLKS]; /* max 8 clocks*/
+
+ cnt = fdtdec_get_int_array_count(fdt, node_off, "assigned-clock-rates",
+ assignedclks, MAX_ASSIGNED_CLKS);
+ if (cnt > 0) {
+ if (cnt <= clk_index)
+ return -ENOENT;
+
+ if (assignedclks[clk_index] <= new_rate)
+ return 0;
+
+ assignedclks[clk_index] = new_rate;
+ for (j = 0; j < cnt; j++)
+ assignedclks[j] = cpu_to_fdt32(assignedclks[j]);
+
+ return fdt_setprop(fdt, node_off, "assigned-clock-rates", &assignedclks, cnt * sizeof(u32));
+ }
+
+ return -ENOENT;
+}
+
+static int low_drive_freq_update(void *blob)
+{
+ int nodeoff, ret;
+ int i;
+
+ /* Update kernel dtb clocks for low drive mode */
+ struct low_drive_freq_entry table[] = {
+ {"/soc@0/lcd-controller@4ae30000", 2, 200000000},
+ {"/soc@0/bus@42800000/camera/isi@4ae40000", 0, 200000000},
+ {"/soc@0/bus@42800000/mmc@42850000", 0, 266666667},
+ {"/soc@0/bus@42800000/mmc@42860000", 0, 266666667},
+ {"/soc@0/bus@42800000/mmc@428b0000", 0, 266666667},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(table); i++) {
+ nodeoff = fdt_path_offset(blob, table[i].node_path);
+ if (nodeoff >= 0) {
+ ret = low_drive_fdt_fix_clock(blob, nodeoff, table[i].clk, table[i].new_rate);
+ if (!ret)
+ printf("%s freq updated\n", table[i].node_path);
+ }
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OF_BOARD_FIXUP
+#ifndef CONFIG_SPL_BUILD
+int board_fix_fdt(void *fdt)
+{
+ /* Update u-boot dtb clocks for low drive mode */
+ if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)){
+ int nodeoff;
+ int i;
+
+ struct low_drive_freq_entry table[] = {
+ {"/soc@0/lcd-controller@4ae30000", 0, 200000000},
+ {"/soc@0/bus@42800000/mmc@42850000", 0, 266666667},
+ {"/soc@0/bus@42800000/mmc@42860000", 0, 266666667},
+ {"/soc@0/bus@42800000/mmc@428b0000", 0, 266666667},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(table); i++) {
+ nodeoff = fdt_path_offset(fdt, table[i].node_path);
+ if (nodeoff >= 0)
+ low_drive_fdt_fix_clock(fdt, nodeoff, table[i].clk, table[i].new_rate);
+ }
+ }
+
+ return 0;
+}
+#endif
+#endif
+
int ft_system_setup(void *blob, struct bd_info *bd)
{
if (is_imx9351() || is_imx9331() || is_imx9321() || is_imx9311())
@@ -734,6 +819,8 @@ int ft_system_setup(void *blob, struct bd_info *bd)
if (is_imx9332() || is_imx9331() || is_imx9312() || is_imx9311())
disable_npu_nodes(blob);
+ if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE))
+ low_drive_freq_update(blob);
return ft_add_optee_node(blob, bd);
}