diff options
author | Ye Li <ye.li@nxp.com> | 2022-10-12 18:06:29 +0800 |
---|---|---|
committer | Ye Li <ye.li@nxp.com> | 2022-10-14 17:43:10 +0800 |
commit | 032fab5e1275422559b81bb79af44218c3faa3c2 (patch) | |
tree | ff990c413f80af254982119261f1bd15b0346726 /arch | |
parent | 53689e4f7db578fc6e476a3af9a123f7dd3806c3 (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/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx9/clock.c | 65 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx9/soc.c | 87 |
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); } |