diff options
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r-- | arch/arm/mach-imx/imx8/Kconfig | 11 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8/fdt.c | 132 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8m/soc.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx9/Kconfig | 15 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx9/clock.c | 37 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx9/container.cfg | 6 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx9/imximage.cfg | 6 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx9/soc.c | 49 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx9/trdc.c | 2 |
9 files changed, 230 insertions, 30 deletions
diff --git a/arch/arm/mach-imx/imx8/Kconfig b/arch/arm/mach-imx/imx8/Kconfig index 59d11b3179e..9a43beda6fa 100644 --- a/arch/arm/mach-imx/imx8/Kconfig +++ b/arch/arm/mach-imx/imx8/Kconfig @@ -54,15 +54,8 @@ config TARGET_COLIBRI_IMX8X select BOARD_LATE_INIT select IMX8QXP -config TARGET_DENEB - bool "Support i.MX8QXP Capricorn Deneb board" - select BINMAN - select BOARD_LATE_INIT - select FACTORYSET - select IMX8QXP - -config TARGET_GIEDI - bool "Support i.MX8QXP Capricorn Giedi board" +config TARGET_CAPRICORN + bool "Support i.MX8QXP Capricorn board" select BINMAN select BOARD_LATE_INIT select FACTORYSET diff --git a/arch/arm/mach-imx/imx8/fdt.c b/arch/arm/mach-imx/imx8/fdt.c index 6d0585f5cc6..ce78c8ce919 100644 --- a/arch/arm/mach-imx/imx8/fdt.c +++ b/arch/arm/mach-imx/imx8/fdt.c @@ -11,6 +11,8 @@ #include <fdt_support.h> #include <linux/libfdt.h> #include <linux/printk.h> +#include <cpu.h> +#include <dm.h> DECLARE_GLOBAL_DATA_PTR; @@ -279,6 +281,134 @@ static int ft_add_optee_node(void *fdt, struct bd_info *bd) return 0; } +static int delete_node(void *blob, const char *node) +{ + int nodeoffset; + int err; + + nodeoffset = fdt_path_offset(blob, node); + if (nodeoffset < 0) + return -ENXIO; + + err = fdt_del_node(blob, nodeoffset); + if (err) + return -EINVAL; + + return 0; +} + +static int change_property(void *blob, const char *node, const char *property, + const void *value, int len) +{ + int nodeoffset; + int err; + + nodeoffset = fdt_path_offset(blob, node); + if (nodeoffset < 0) + return -ENXIO; + + err = fdt_setprop(blob, nodeoffset, property, value, len); + if (err) + return -EINVAL; + + return 0; +} + +static void update_fdt_gpu_industrial_frequencies(void *blob) +{ + u32 gpu_opp_table[6]; + u32 gpu_assigned_clocks[2]; + int err; + + gpu_opp_table[0] = cpu_to_fdt32(625000); /* Normal Core Clock */ + gpu_opp_table[1] = cpu_to_fdt32(0); + gpu_opp_table[2] = cpu_to_fdt32(625000); /* Normal Shader Clock */ + gpu_opp_table[3] = cpu_to_fdt32(0); + gpu_opp_table[4] = cpu_to_fdt32(400000); /* Low Shader and Core Clock */ + gpu_opp_table[5] = cpu_to_fdt32(0); + + gpu_assigned_clocks[0] = cpu_to_fdt32(625000000); /* Core Clock */ + gpu_assigned_clocks[1] = cpu_to_fdt32(625000000); /* Shader Clock */ + + err = change_property(blob, "/bus@53100000/gpu@53100000", + "assigned-clock-rates", gpu_assigned_clocks, + sizeof(gpu_assigned_clocks)); + if (err && err != ENXIO) + printf("Failed to set assigned-clock-rates for GPU0: %s\n", + fdt_strerror(err)); + + err = change_property(blob, "/bus@54100000/gpu@54100000", + "assigned-clock-rates", gpu_assigned_clocks, + sizeof(gpu_assigned_clocks)); + if (err && err != ENXIO) + printf("Failed to set assigned-clock-rates for GPU1: %s\n", + fdt_strerror(err)); + + err = change_property(blob, "/bus@54100000/imx8_gpu1_ss@80000000", + "operating-points", &gpu_opp_table, + sizeof(gpu_opp_table)); + if (err && err != ENXIO) + printf("Failed to set operating-points for GPU: %s\n", + fdt_strerror(err)); +} + +static void update_fdt_cpu_industrial_frequencies(void *blob) +{ + int err; + + err = delete_node(blob, "/opp-table-0/opp-1200000000"); + if (err && err != -ENXIO) + printf("Failed to delete 1.2 GHz node on A53: %s\n", + fdt_strerror(err)); + + err = delete_node(blob, "/opp-table-1/opp-1596000000"); + if (err && err != -ENXIO) + printf("Failed to delete 1.596 GHz node on A72: %s\n", + fdt_strerror(err)); +} + +static void update_fdt_frequencies(void *blob) +{ + struct cpu_info cpu; + struct udevice *dev; + int err; + + uclass_first_device(UCLASS_CPU, &dev); + + err = cpu_get_info(dev, &cpu); + if (err) { + printf("Failed to get CPU info\n"); + return; + } + + /* + * Differentiate between the automotive and industrial variants of the + * i.MX8. The difference of these two CPUs is the maximum frequencies + * for the CPU and GPU. + * Core Automotive [max. MHz] Industrial [max. MHz] + * A53 1200 1104 + * A72 1596 1296 + * GPU Core 800 625 + * GPU Shader 1000 625 + * + * While the SCFW enforces these limits for the CPU, the OS cpufreq + * driver remains unaware, causing a mismatch between reported and + * actual frequencies. This is resolved by removing the unsupprted + * frequencies from the device tree. + * + * The GPU frequencies are not enforced by the SCFW, therefore without + * updating the device tree we overclock the GPU. + * + * Using the cpu_freq variable is the only know way to differentiate + * between the automotive and industrial variants of the i.MX8. + */ + if (cpu.cpu_freq != 1104000000) + return; + + update_fdt_cpu_industrial_frequencies(blob); + update_fdt_gpu_industrial_frequencies(blob); +} + int ft_system_setup(void *blob, struct bd_info *bd) { int ret; @@ -294,6 +424,8 @@ int ft_system_setup(void *blob, struct bd_info *bd) update_fdt_with_owned_resources(blob); + update_fdt_frequencies(blob); + if (is_imx8qm()) { ret = config_smmu_fdt(blob); if (ret) diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 9588b8b28bf..85dc8b51a14 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -362,7 +362,7 @@ phys_addr_t board_get_usable_ram_top(phys_size_t total_size) * space below the 4G address boundary (which is 3GiB big), * even when the effective available memory is bigger. */ - top_addr = clamp_val((u64)PHYS_SDRAM + gd->ram_size, 0, 0xffffffff); + top_addr = clamp_val((u64)PHYS_SDRAM + gd->ram_size, 0, SZ_4G); /* * rom_pointer[0] stores the TEE memory start address. diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig index 5c1054138fc..54c6b117fcf 100644 --- a/arch/arm/mach-imx/imx9/Kconfig +++ b/arch/arm/mach-imx/imx9/Kconfig @@ -16,6 +16,12 @@ config IMX93 select IMX9 select ARMV8_SPL_EXCEPTION_VECTORS +config IMX91 + bool + select IMX9 + select ARMV8_SPL_EXCEPTION_VECTORS + + config SYS_SOC default "imx9" @@ -23,6 +29,12 @@ choice prompt "NXP i.MX9 board select" optional +config TARGET_IMX91_11X11_EVK + bool "imx91_11x11_evk" + select OF_BOARD_FIXUP + select IMX91 + imply OF_UPSTREAM + config TARGET_IMX93_9X9_QSB bool "imx93_qsb" select OF_BOARD_FIXUP @@ -45,9 +57,12 @@ config TARGET_PHYCORE_IMX93 bool "phycore_imx93" select IMX93 select IMX9_LPDDR4X + select OF_BOARD_FIXUP + select OF_BOARD_SETUP endchoice +source "board/freescale/imx91_evk/Kconfig" source "board/freescale/imx93_evk/Kconfig" source "board/freescale/imx93_qsb/Kconfig" source "board/phytec/phycore_imx93/Kconfig" diff --git a/arch/arm/mach-imx/imx9/clock.c b/arch/arm/mach-imx/imx9/clock.c index c00be19c4fa..e65cabef2c9 100644 --- a/arch/arm/mach-imx/imx9/clock.c +++ b/arch/arm/mach-imx/imx9/clock.c @@ -30,6 +30,7 @@ static struct imx_intpll_rate_table imx9_intpll_tbl[] = { INT_PLL_RATE(1400000000U, 1, 175, 3), /* 1.4Ghz */ INT_PLL_RATE(1000000000U, 1, 166, 4), /* 1000Mhz */ INT_PLL_RATE(900000000U, 1, 150, 4), /* 900Mhz */ + INT_PLL_RATE(800000000U, 1, 200, 6), /* 800Mhz */ }; static struct imx_fracpll_rate_table imx9_fracpll_tbl[] = { @@ -37,12 +38,14 @@ static struct imx_fracpll_rate_table imx9_fracpll_tbl[] = { FRAC_PLL_RATE(933000000U, 1, 155, 4, 1, 2), /* 933Mhz */ FRAC_PLL_RATE(800000000U, 1, 200, 6, 0, 1), /* 800Mhz */ FRAC_PLL_RATE(700000000U, 1, 145, 5, 5, 6), /* 700Mhz */ + FRAC_PLL_RATE(600000000U, 1, 200, 8, 0, 1), /* 600Mhz */ FRAC_PLL_RATE(484000000U, 1, 121, 6, 0, 1), FRAC_PLL_RATE(445333333U, 1, 167, 9, 0, 1), FRAC_PLL_RATE(466000000U, 1, 155, 8, 1, 3), /* 466Mhz */ FRAC_PLL_RATE(400000000U, 1, 200, 12, 0, 1), /* 400Mhz */ FRAC_PLL_RATE(300000000U, 1, 150, 12, 0, 1), FRAC_PLL_RATE(233000000U, 1, 174, 18, 3, 4), /* 233Mhz */ + FRAC_PLL_RATE(200000000U, 1, 200, 24, 0, 1), /* 200Mhz */ }; /* return in khz */ @@ -723,7 +726,7 @@ struct imx_clk_setting imx_clk_ld_settings[] = { /* SWO TRACE to 133M */ {SWO_TRACE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, /* M33 systetick to 24M */ - {M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1}, + {M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1, CLK_SOC_IMX93}, /* NIC to 250M */ {NIC_CLK_ROOT, SYS_PLL_PFD0, 4}, /* NIC_APB to 133M */ @@ -753,13 +756,17 @@ struct imx_clk_setting imx_clk_settings[] = { * WAKEUP_AXI to 312.5M, because of FEC only can support to 320M for * generating MII clock at 2.5M */ - {WAKEUP_AXI_CLK_ROOT, SYS_PLL_PFD2, 2}, + {WAKEUP_AXI_CLK_ROOT, SYS_PLL_PFD2, 2, CLK_SOC_IMX93}, + /* Wakeup AXI 250M*/ + {WAKEUP_AXI_CLK_ROOT, SYS_PLL_PFD0, 4, CLK_SOC_IMX91}, /* SWO TRACE to 133M */ {SWO_TRACE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, /* M33 systetick to 24M */ - {M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1}, + {M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1, CLK_SOC_IMX93}, /* NIC to 400M */ - {NIC_CLK_ROOT, SYS_PLL_PFD1, 2}, + {NIC_CLK_ROOT, SYS_PLL_PFD1, 2, CLK_SOC_IMX93}, + /* NIC to 333M */ + {NIC_CLK_ROOT, SYS_PLL_PFD0, 3, CLK_SOC_IMX91}, /* NIC_APB to 133M */ {NIC_APB_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3} }; @@ -769,8 +776,12 @@ void bus_clock_init_low_drive(void) int i; for (i = 0; i < ARRAY_SIZE(imx_clk_ld_settings); i++) { - ccm_clk_root_cfg(imx_clk_ld_settings[i].clk_root, - imx_clk_ld_settings[i].src, imx_clk_ld_settings[i].div); + if (imx_clk_ld_settings[i].soc == CLK_SOC_ALL || + (is_imx91() && imx_clk_ld_settings[i].soc == CLK_SOC_IMX91) || + (is_imx93() && imx_clk_ld_settings[i].soc == CLK_SOC_IMX93)) { + ccm_clk_root_cfg(imx_clk_ld_settings[i].clk_root, + imx_clk_ld_settings[i].src, imx_clk_ld_settings[i].div); + } } } @@ -779,8 +790,12 @@ void bus_clock_init(void) int i; for (i = 0; i < ARRAY_SIZE(imx_clk_settings); i++) { - ccm_clk_root_cfg(imx_clk_settings[i].clk_root, - imx_clk_settings[i].src, imx_clk_settings[i].div); + if (imx_clk_settings[i].soc == CLK_SOC_ALL || + (is_imx91() && imx_clk_settings[i].soc == CLK_SOC_IMX91) || + (is_imx93() && imx_clk_settings[i].soc == CLK_SOC_IMX93)) { + ccm_clk_root_cfg(imx_clk_settings[i].clk_root, + imx_clk_settings[i].src, imx_clk_settings[i].div); + } } } @@ -857,7 +872,7 @@ u32 imx_get_fecclk(void) return ccm_clk_root_get_rate(WAKEUP_AXI_CLK_ROOT); } -#if defined(CONFIG_IMX93) && defined(CONFIG_DWC_ETH_QOS) +#if (CONFIG_IS_ENABLED(IMX93) || CONFIG_IS_ENABLED(IMX91)) && CONFIG_IS_ENABLED(DWC_ETH_QOS) static int imx93_eqos_interface_init(struct udevice *dev, phy_interface_t interface_type) { struct blk_ctrl_wakeupmix_regs *bctrl = @@ -901,12 +916,12 @@ static int imx93_eqos_interface_init(struct udevice *dev, phy_interface_t interf int board_interface_eth_init(struct udevice *dev, phy_interface_t interface_type) { - if (IS_ENABLED(CONFIG_IMX93) && + if ((IS_ENABLED(CONFIG_IMX93) || IS_ENABLED(CONFIG_IMX91)) && IS_ENABLED(CONFIG_DWC_ETH_QOS) && device_is_compatible(dev, "nxp,imx93-dwmac-eqos")) return imx93_eqos_interface_init(dev, interface_type); - if (IS_ENABLED(CONFIG_IMX93) && + if ((IS_ENABLED(CONFIG_IMX93) || IS_ENABLED(CONFIG_IMX91)) && IS_ENABLED(CONFIG_FEC_MXC) && device_is_compatible(dev, "fsl,imx93-fec")) return 0; diff --git a/arch/arm/mach-imx/imx9/container.cfg b/arch/arm/mach-imx/imx9/container.cfg index 72fe791eae6..91a973161d1 100644 --- a/arch/arm/mach-imx/imx9/container.cfg +++ b/arch/arm/mach-imx/imx9/container.cfg @@ -6,6 +6,10 @@ BOOT_FROM SD 0x400 SOC_TYPE IMX9 CONTAINER +#ifdef CONFIG_IMX91 +IMAGE A55 bl31.bin 0x204C0000 +#else IMAGE A55 bl31.bin 0x204E0000 +#endif IMAGE A55 u-boot.bin CONFIG_TEXT_BASE -IMAGE A55 tee.bin 0x96000000
\ No newline at end of file +IMAGE A55 tee.bin 0x96000000 diff --git a/arch/arm/mach-imx/imx9/imximage.cfg b/arch/arm/mach-imx/imx9/imximage.cfg index d327d6a6ef4..118dfb3ec79 100644 --- a/arch/arm/mach-imx/imx9/imximage.cfg +++ b/arch/arm/mach-imx/imx9/imximage.cfg @@ -5,6 +5,10 @@ BOOT_FROM SD 0x400 SOC_TYPE IMX9 +#ifdef CONFIG_IMX91 +APPEND mx91a0-ahab-container.img +#else APPEND mx93a1-ahab-container.img +#endif CONTAINER -IMAGE A55 u-boot-spl-ddr.bin 0x2049A000
\ No newline at end of file +IMAGE A55 u-boot-spl-ddr.bin CONFIG_SPL_TEXT_BASE diff --git a/arch/arm/mach-imx/imx9/soc.c b/arch/arm/mach-imx/imx9/soc.c index 21e0e7dd1e8..bb13ca742e3 100644 --- a/arch/arm/mach-imx/imx9/soc.c +++ b/arch/arm/mach-imx/imx9/soc.c @@ -118,6 +118,8 @@ u32 get_cpu_speed_grade_hz(void) if (is_imx93()) max_speed = MHZ(1700); + else if (is_imx91()) + max_speed = MHZ(1400); /* In case the fuse of speed grade not programmed */ if (speed > max_speed) @@ -195,7 +197,30 @@ static u32 get_cpu_variant_type(u32 type) bool npu_disable = !!(val & BIT(13)); bool core1_disable = !!(val & BIT(15)); - u32 pack_9x9_fused = BIT(4) | BIT(17) | BIT(19) | BIT(24); + u32 pack_9x9_fused = BIT(4) | BIT(5) | BIT(17) | BIT(19) | BIT(24); + u32 nxp_recog = (val & GENMASK(23, 16)) >> 16; + + /* For iMX91 */ + if (type == MXC_CPU_IMX91) { + switch (nxp_recog) { + case 0x9: + case 0xA: + type = MXC_CPU_IMX9111; + break; + case 0xD: + case 0xE: + type = MXC_CPU_IMX9121; + break; + case 0xF: + case 0x10: + type = MXC_CPU_IMX9101; + break; + default: + break; /* 9131 as default */ + } + + return type; + } /* Low performance 93 part */ if (((val >> 6) & 0x3F) == 0xE && npu_disable) @@ -217,8 +242,14 @@ static u32 get_cpu_variant_type(u32 type) u32 get_cpu_rev(void) { u32 rev = (gd->arch.soc_rev >> 24) - 0xa0; + u32 type; - return (get_cpu_variant_type(MXC_CPU_IMX93) << 12) | + if ((gd->arch.soc_rev & 0xFFFF) == 0x9300) + type = MXC_CPU_IMX93; + else + type = MXC_CPU_IMX91; + + return (get_cpu_variant_type(type) << 12) | (CHIP_REV_1_0 + rev); } @@ -539,7 +570,8 @@ int print_cpuinfo(void) cpurev = get_cpu_rev(); - printf("CPU: i.MX93 rev%d.%d\n", (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0); + printf("CPU: i.MX%s rev%d.%d\n", is_imx93() ? "93" : "91", + (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0); return 0; } @@ -634,7 +666,7 @@ static int low_drive_freq_update(void *blob) return 0; } -#ifdef CONFIG_OF_BOARD_FIXUP +#if defined(CONFIG_OF_BOARD_FIXUP) && !defined(CONFIG_TARGET_PHYCORE_IMX93) #ifndef CONFIG_XPL_BUILD int board_fix_fdt(void *fdt) { @@ -893,7 +925,9 @@ void disable_isolation(void) void soc_power_init(void) { mix_power_init(MIX_PD_MEDIAMIX); - mix_power_init(MIX_PD_MLMIX); + + if (is_imx93()) + mix_power_init(MIX_PD_MLMIX); disable_isolation(); } @@ -919,6 +953,9 @@ int m33_prepare(void) (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR; u32 val, i; + if (is_imx91()) + return -ENODEV; + if (m33_is_rom_kicked()) return -EPERM; @@ -1007,7 +1044,7 @@ enum imx9_soc_voltage_mode soc_target_voltage_mode(void) u32 speed = get_cpu_speed_grade_hz(); enum imx9_soc_voltage_mode voltage = VOLT_OVER_DRIVE; - if (is_imx93()) { + if (is_imx93() || is_imx91()) { if (speed == 1700000000) voltage = VOLT_OVER_DRIVE; else if (speed == 1400000000) diff --git a/arch/arm/mach-imx/imx9/trdc.c b/arch/arm/mach-imx/imx9/trdc.c index ef0f8b52a4d..d7593ec2718 100644 --- a/arch/arm/mach-imx/imx9/trdc.c +++ b/arch/arm/mach-imx/imx9/trdc.c @@ -484,7 +484,7 @@ void trdc_init(void) } } -#if DEBUG +#ifdef DEBUG int trdc_mbc_control_dump(ulong trdc_reg, u32 mbc_x, u32 glbac_id) { struct trdc_mbc *mbc_base = (struct trdc_mbc *)trdc_get_mbc_base(trdc_reg, mbc_x); |