diff options
author | Max Krummenacher <max.krummenacher@toradex.com> | 2024-02-19 13:51:39 +0100 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2024-02-19 17:12:43 +0100 |
commit | 04dddde7d4d7eb28ce29ff0555b281a670db2cd6 (patch) | |
tree | c2d73eb2c3a62ddf291454aeedd6cad2d7f9c3d3 /arch/arm/mach-imx/imx9/soc.c | |
parent | ef90b0f339f2bcd576f0d7898b5896c6d9c0f93f (diff) | |
parent | 181859317bfafef1da79c59a4498650168ad9df6 (diff) |
Merge tag 'lf-5.15.71-2.2.2' into toradex_imx_lf_v2022.04
This pulls in the following commits:
git log --oneline --no-merges ^HEAD lf-5.15.71-2.2.2
14b6c8f3e3b MA-20886 imx8ulp: Boot from recovery mode when pressing key
62ad7799b6c LF-7602: Device tree fixup based on compatible string
b35420da607 crypto: fsl_hash: Remove unnecessary alignment check in caam_hash()
918dbf78bbb MA-20872 Revert "MA-18775 system will hang about 3s when boot up kernel"
ed2c3cbd6ac MA-20814 add fastboot command to erase u-boot env
a6762e28bf0 LF-6627: nand drvier fixups in sdboot on ls1043ardb-pd
d23cfa09767 LFU-426: qspihdr: Coverity Issue: unchecked return value
413b08f841f MLK-25850: imx8dxl_ddr3l_evk: change the default fdt file name
e91a047f54f LF-7382: fastboot: improve emmc write speed
205680f9f4b LFU-428 imx8ulp: Add warning for CAAM non-secure state failure
f405551dcc1 LF-7369-2 clk: imx93: update LPCG control API
676831be672 LF-7369-1 clk: imx: implement a clock gate driver for i.MX93
94c5bb2eb83 MA-20507-7 trusty: fix dereference null return value
6933487b4df LFU-427 imx93: Print ELE FW version
15b1ebb00cc LFU-393 imx93: Add reset cause print
f3b75e3317d LF-7332 imx8/ahab: sha256: enable image verification using ARMv8 crypto extention
330e2634143 LFU-423: usb: cdns3: gadget: Avoid using usb_ss after null check
58ba744cbad MLK-26034 imx6: Disable LCDIF clock before jumping to kernel
ae396d343a3 LF-6627: nand drvier fixups in nandboot on ls1043ardb-pd
0a99627b60e LFU-422-2 imx8ulp_evk: Enable the GD25LX256E support
c6c06de038f LFU-422-1 mtd: spi-nor: Add GigaDevice GD25LX256E NOR flash
032fab5e127 LFU-421 imx93_evk: Add imx93 low drive mode support on 11x11 EVK
d9f477625d3 LF-7332 armv8: SHA-256 using ARMv8 Crypto Extensions
53689e4f7db MA-20667 set metadata partition of type f2fs
f824cd01955 LFU-415 net: fec_mxc: Skip recv packet process when fec is halted
4e7c44e1f33 LFU-419 arm: dts: imx8mp: fix flexspi nand reg
957bdd9c925 LFU-418 imx8ulp: upower_hal: make code cleaner
361b23b98ed Revert "MLK-25478-1 efi: add Platform-Reset-Attack variables"
e1ed0611b5e Revert "MLK-25478-2 efi: clean memory and reset MemoryOverwriteRequestControl"
4998fef38a5 Revert "MLK-25478-3 workaround: disable verify time of signer and signee."
320096439b6 MA-20738 imx8ulp: bumps CONFIG_LMB_MAX_REGIONS
c244bdfd76c LFU-417-2 imx93_evk/qsb: Enable DDR inline ECC feature
026521c7d65 LFU-417-1 ddr: imx: imx9: Add DDR inline ECC support
a555a21be69 LFU-413 imx8ulp_evk: Remove CONFIG_BOOTDELAY=0 from ND defconfig
aaead5a2b8d LFU-416 imx: cmd_dek: Fix build warning in blob_encap_dek
933a3b25fe3 LF-7234 enable CONFIG_CMD_CRC32 and CONFIG_CRC32_VERIFY
97fc905e7f7 LFU-409: imx8dxl: fix the i.MX8DXL ddr3l NAND DQS iomux setting
aa4ebb66199 LFU-414 imx8ulp: clock: Update clocks to meet max rate restrictions
63d0579f397 LFU-410 imx: ele_ahab: Add ahab_sec_fuse_prog command
266dddae454 LFU-412 configs: imx93_evk: shrink mem= for jailhouse
5703d3ae37e LFU-411 imx8ulp: Always enable MIPI_DSI power switch
32965eb52f7 LFU-392 imx8ulp: upower: replace magic number with macro
beb5e5e3303 MA-20677 imx8ulp: android: enable CONFIG_AHAB_BOOT by default
bb45dd592db LFU-408 imx93evk: config the pmic standby voltage for buck1
25e38cb4762 LFU-407-02 ddr: imx9: Change the saved ddr data base to 0x2051c000
a8fef10ab92 LFU-407-01 configs: imx93: Update spl stack & bss base address
8731024fe7e LFU-406 mx6ul/mx6ulz: Fix build break caused by RNG patch
a95afe08769 LF-7238 imx9: soc: Remove OPTEE memory from DRAM bank and MMU
19c3fdebf8d LFU-403-4 imx93_evk/qsb: Enable TMU sensor driver
e1703ec06a4 LFU-403-3 iMX93: soc: print current CPU temperature
050a94e6365 LFU-403-2 DTS: imx93: Update TMU node to sync with kernel
91e711a565c LFU-403-1 thermal: imx_tmu: Update TMU driver to support iMX93
78749666dd3 LFU-402-3 imx93_evk/qsb: Use API to set max ARM clock
401b9824f92 LFU-402-2 iMX93: clock: Add API to set max ARM core clock
e4722baa5af LFU-402-1 iMX93: soc: Get market segment and speed grading
432a4af9608 LFU-400 imx8ulp: clock: Clear dividers in PLL3DIV_PFD registers
53f06207782 LFU-399 imx8ulp: Reconfigure MRC3 for SRAM0 access
48a2221acc9 LFU-395 imx93: Add fused parts support
d8760a74793 LFU-398-7 imx93_9x9_qsb: Enable Flexspi NOR support
1f500a59670 LFU-398-6 imx93_qsb: Enable M.2 VPCIe_3V3 and deassert SD3_nRST
ba4f72198f5 LFU-398-5 DTS: imx93-9x9-qsb: Add flexspi NOR nodes and pinctrl
d9f563336f7 LFU-398-4 imx93_11x11_evk: Enable Flexspi NOR support
c56f2132d53 LFU-398-3 imx93_evk: Enable M.2 VPCIe_3V3 and deassert SD3_nRST
b6cbe6b1416 LFU-398-2 DTS: imx93-11x11-evk: Enable and update flexspi NOR
c45c4fb791b LFU-398-1 DTS: imx93: Update flexspi node in DTSi
fab973fe1df LFU-397 imx8m: clock: not configure reserved SRC register
4881ba99fa4 LFU-396-7 imx93_9x9_qsp_defconfig: support splash screen
60e0e629f99 LFU-396-6 arm: dts: add imx93 9x9 ontat panel dts
fffc330cf1a LFU-396-5 imx9: clock: add 300MHz fracn pll table
ef6a3d9cc38 LFU-396-4 video: nxp: imx: add Add i.MX93 parallel display format encoder driver
5f414738a5f LFU-396-3 video: nxp: imx_lcdifv3: support VSYNC/HSYNC active low
21eb66fe1f8 LFU-396-2 video: nxp: imx: dsi: force DISPLAY_FLAGS_HSYNC_HIGH & DISPLAY_FLAGS_VSYNC_HIGH
88132ed0b4e LFU-396-1 video: simple_panel: make backlight optional
65287dc074d LF-7055: video: imx: Add set_parent calls to LVDS initialization
167f65006fb MLK-26021 imx93: add 9x9 qsb lpddr4 board
0a6297a290e MA-20677 imx8ulp: android: enable CONFIG_AHAB_BOOT by default
8789f3ca3e4 PLATSEC-1781-2 MX6: Device tree fix-up
60555c4a445 PLATSEC-1781-1 mx6ull:Add config CONFIG_OF_SYSTEM_SETUP
48b1d6e34fd MA-20149 set fs type of android partitions
9710cc4840e LFOPTEE-177 imx93evk: enable cmd_dek command
f0721d67f03 LFOPTEE-177 imx8ulp: enable cmd_dek command
bf07f5166bf LFOPTEE-177 imx: cmd_dek: add ELE DEK Blob generation support
6de56c3f629 LFOPTEE-177 s400_api: add DEK Blob generation
Conflicts:
drivers/crypto/fsl/fsl_hash.c
commit 41b2182af73 ("crypto: fsl_hash: Remove unnecessary
alignment check in caam_hash()")
Both NXP and TXD branch did cherry-picking that commit, but NXP
additionally removed a debug print (not present in master)
while the TDX branch did not. Resolved by doing it the NXP way.
Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com>
Diffstat (limited to 'arch/arm/mach-imx/imx9/soc.c')
-rw-r--r-- | arch/arm/mach-imx/imx9/soc.c | 584 |
1 files changed, 578 insertions, 6 deletions
diff --git a/arch/arm/mach-imx/imx9/soc.c b/arch/arm/mach-imx/imx9/soc.c index 66200dbe3c..02edced9aa 100644 --- a/arch/arm/mach-imx/imx9/soc.c +++ b/arch/arm/mach-imx/imx9/soc.c @@ -32,6 +32,10 @@ #include <asm/mach-imx/optee.h> #include <linux/delay.h> #include <fuse.h> +#include <imx_thermal.h> +#include <thermal.h> +#include <imx_sip.h> +#include <linux/arm-smccc.h> DECLARE_GLOBAL_DATA_PTR; @@ -153,6 +157,56 @@ int board_usb_gadget_port_auto(void) } #endif +u32 get_cpu_speed_grade_hz(void) +{ + u32 speed, max_speed; + u32 grade; + u32 val = readl((ulong)FSB_BASE_ADDR + 0x8000 + (19 << 2)); + val >>= 6; + val &= 0xf; + + speed = 2300000000 - val * 100000000; + + if (is_imx93()) { + grade = get_cpu_temp_grade(NULL, NULL); + if (grade == TEMP_INDUSTRIAL) + max_speed = 1500000000; + else + max_speed = 1700000000; + + /* In case the fuse of speed grade not programmed */ + if (speed > max_speed) + speed = max_speed; + } + + return speed; +} + +u32 get_cpu_temp_grade(int *minc, int *maxc) +{ + u32 val = readl((ulong)FSB_BASE_ADDR + 0x8000 + (19 << 2)); + + val >>= 4; + val &= 0x3; + + if (minc && maxc) { + if (val == TEMP_AUTOMOTIVE) { + *minc = -40; + *maxc = 125; + } else if (val == TEMP_INDUSTRIAL) { + *minc = -40; + *maxc = 105; + } else if (val == TEMP_EXTCOMMERCIAL) { + *minc = -20; + *maxc = 105; + } else { + *minc = 0; + *maxc = 95; + } + } + return val; +} + static void set_cpu_info(struct sentinel_get_info_data *info) { gd->arch.soc_rev = info->soc; @@ -160,10 +214,33 @@ static void set_cpu_info(struct sentinel_get_info_data *info) memcpy((void *)&gd->arch.uid, &info->uid, 4 * sizeof(u32)); } +static u32 get_cpu_variant_type(u32 type) +{ + /* word 19 */ + u32 val = readl((ulong)FSB_BASE_ADDR + 0x8000 + (19 << 2)); + u32 val2 = readl((ulong)FSB_BASE_ADDR + 0x8000 + (20 << 2)); + bool npu_disable = !!(val & BIT(13)); + bool core1_disable = !!(val & BIT(15)); + u32 pack_9x9_fused = BIT(4) | BIT(17) | BIT(19) | BIT(24); + + if ((val2 & pack_9x9_fused) == pack_9x9_fused) + type = MXC_CPU_IMX9322; + + if (npu_disable && core1_disable) + return type + 3; + else if (npu_disable) + return type + 2; + else if (core1_disable) + return type + 1; + + return type; +} + u32 get_cpu_rev(void) { u32 rev = (gd->arch.soc_rev >> 24) - 0xa0; - return (MXC_CPU_IMX93 << 12) | (CHIP_REV_1_0 + rev); + return (get_cpu_variant_type(MXC_CPU_IMX93) << 12) | + (CHIP_REV_1_0 + rev); } #define UNLOCK_WORD 0xD928C520 /* unlock word */ @@ -262,13 +339,161 @@ static struct mm_region imx93_mem_map[] = { struct mm_region *mem_map = imx93_mem_map; +static unsigned int imx9_find_dram_entry_in_mem_map(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx93_mem_map); i++) + if (imx93_mem_map[i].phys == CONFIG_SYS_SDRAM_BASE) + return i; + + hang(); /* Entry not found, this must never happen. */ +} + +void enable_caches(void) +{ + /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch + * If OPTEE does not run, still update the MMU table according to dram banks structure + * to set correct dram size from board_phys_sdram_size + */ + int i = 0; + /* + * please make sure that entry initial value matches + * imx93_mem_map for DRAM1 + */ + int entry = imx9_find_dram_entry_in_mem_map(); + u64 attrs = imx93_mem_map[entry].attrs; + + while (i < CONFIG_NR_DRAM_BANKS && + entry < ARRAY_SIZE(imx93_mem_map)) { + if (gd->bd->bi_dram[i].start == 0) + break; + imx93_mem_map[entry].phys = gd->bd->bi_dram[i].start; + imx93_mem_map[entry].virt = gd->bd->bi_dram[i].start; + imx93_mem_map[entry].size = gd->bd->bi_dram[i].size; + imx93_mem_map[entry].attrs = attrs; + debug("Added memory mapping (%d): %llx %llx\n", entry, + imx93_mem_map[entry].phys, imx93_mem_map[entry].size); + i++; entry++; + } + + icache_enable(); + dcache_enable(); +} + +__weak int board_phys_sdram_size(phys_size_t *size) +{ + if (!size) + return -EINVAL; + + *size = PHYS_SDRAM_SIZE; + +#ifdef PHYS_SDRAM_2_SIZE + *size += PHYS_SDRAM_2_SIZE; +#endif + return 0; +} + int dram_init(void) { - gd->ram_size = PHYS_SDRAM_SIZE; + phys_size_t sdram_size; + int ret; + + ret = board_phys_sdram_size(&sdram_size); + if (ret) + return ret; + + /* rom_pointer[1] contains the size of TEE occupies */ + if (rom_pointer[1]) + gd->ram_size = sdram_size - rom_pointer[1]; + else + gd->ram_size = sdram_size; + + return 0; +} + +int dram_init_banksize(void) +{ + int bank = 0; + int ret; + phys_size_t sdram_size; + phys_size_t sdram_b1_size, sdram_b2_size; + + ret = board_phys_sdram_size(&sdram_size); + if (ret) + return ret; + + /* Bank 1 can't cross over 4GB space */ + if (sdram_size > 0x80000000) { + sdram_b1_size = 0x80000000; + sdram_b2_size = sdram_size - 0x80000000; + } else { + sdram_b1_size = sdram_size; + sdram_b2_size = 0; + } + + gd->bd->bi_dram[bank].start = PHYS_SDRAM; + if (rom_pointer[1]) { + phys_addr_t optee_start = (phys_addr_t)rom_pointer[0]; + phys_size_t optee_size = (size_t)rom_pointer[1]; + + gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start; + if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) { + if (++bank >= CONFIG_NR_DRAM_BANKS) { + puts("CONFIG_NR_DRAM_BANKS is not enough\n"); + return -1; + } + + gd->bd->bi_dram[bank].start = optee_start + optee_size; + gd->bd->bi_dram[bank].size = PHYS_SDRAM + + sdram_b1_size - gd->bd->bi_dram[bank].start; + } + } else { + gd->bd->bi_dram[bank].size = sdram_b1_size; + } + + if (sdram_b2_size) { + if (++bank >= CONFIG_NR_DRAM_BANKS) { + puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n"); + return -1; + } + gd->bd->bi_dram[bank].start = 0x100000000UL; + gd->bd->bi_dram[bank].size = sdram_b2_size; + } return 0; } +phys_size_t get_effective_memsize(void) +{ + int ret; + phys_size_t sdram_size; + phys_size_t sdram_b1_size; + ret = board_phys_sdram_size(&sdram_size); + if (!ret) { + /* Bank 1 can't cross over 4GB space */ + if (sdram_size > 0x80000000) { + sdram_b1_size = 0x80000000; + } else { + sdram_b1_size = sdram_size; + } + + if (rom_pointer[1]) { + /* We will relocate u-boot to Top of dram1. Tee position has two cases: + * 1. At the top of dram1, Then return the size removed optee size. + * 2. In the middle of dram1, return the size of dram1. + */ + if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size)) + return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM); + } + + return sdram_b1_size; + } else { + return PHYS_SDRAM_SIZE; + } +} + + void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) { u32 val[2] = {}; @@ -315,26 +540,370 @@ err: printf("%s: fuse read err: %d\n", __func__, ret); } +const char *get_imx_type(u32 imxtype) +{ + switch (imxtype) { + case MXC_CPU_IMX93: + return "93(52)";/* iMX93 Dual core with NPU */ + case MXC_CPU_IMX9351: + return "93(51)";/* iMX93 Single core with NPU */ + case MXC_CPU_IMX9332: + return "93(32)";/* iMX93 Dual core without NPU */ + case MXC_CPU_IMX9331: + return "93(31)";/* iMX93 Single core without NPU */ + case MXC_CPU_IMX9322: + return "93(22)";/* iMX93 9x9 Dual core */ + case MXC_CPU_IMX9321: + return "93(21)";/* iMX93 9x9 Single core */ + case MXC_CPU_IMX9312: + return "93(12)";/* iMX93 9x9 Dual core without NPU */ + case MXC_CPU_IMX9311: + return "93(11)";/* iMX93 9x9 Single core without NPU */ + default: + return "??"; + } +} + +#define SRC_SRSR_RESET_CAUSE_NUM 16 +const char *reset_cause[SRC_SRSR_RESET_CAUSE_NUM] = { + "POR ", + "JTAG ", + "IPP USER ", + "WDOG1 ", + "WDOG2 ", + "WDOG3 ", + "WDOG4 ", + "WDOG5 ", + "TEMPSENSE ", + "CSU ", + "JTAG_SW ", + "M33_REQ ", + "M33_LOCKUP " + "UNK ", + "UNK ", + "UNK ", +}; + +static void save_reset_cause(void) +{ + struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE; + u32 srsr = readl(&src->srsr); + writel(srsr, &src->srsr); /* clear srsr in sec mode */ + + /* Save value to GPR1 to pass to nonsecure */ + writel(srsr, &src->gpr[0]); +} + +static const char *get_reset_cause(u32 *srsr_ret) +{ + struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE; + u32 srsr; + u32 i; + + srsr = readl(&src->gpr[0]); + if (srsr_ret) + *srsr_ret = srsr; + + for (i = SRC_SRSR_RESET_CAUSE_NUM; i > 0; i--) { + if (srsr & (1 << (i - 1))) + return reset_cause[i - 1]; + } + + return "unknown reset"; +} + int print_cpuinfo(void) { - u32 cpurev; + u32 cpurev, max_freq; + int minc, maxc; + u32 ssrs_ret; cpurev = get_cpu_rev(); - printf("CPU: i.MX93 rev%d.%d at %d MHz\n", - (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0, - mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("CPU: i.MX%s rev%d.%d", + get_imx_type((cpurev & 0x1FF000) >> 12), + (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0); + + max_freq = get_cpu_speed_grade_hz(); + if (!max_freq || max_freq == mxc_get_clock(MXC_ARM_CLK)) { + printf(" at %dMHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + } else { + printf(" %d MHz (running at %d MHz)\n", max_freq / 1000000, + mxc_get_clock(MXC_ARM_CLK) / 1000000); + } + + puts("CPU: "); + switch (get_cpu_temp_grade(&minc, &maxc)) { + case TEMP_AUTOMOTIVE: + puts("Automotive temperature grade "); + break; + case TEMP_INDUSTRIAL: + puts("Industrial temperature grade "); + break; + case TEMP_EXTCOMMERCIAL: + puts("Extended Consumer temperature grade "); + break; + default: + puts("Consumer temperature grade "); + break; + } + printf("(%dC to %dC)", minc, maxc); + +#if defined(CONFIG_IMX_TMU) + struct udevice *udev; + int ret, temp; + + ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal", &udev); + if (!ret) { + ret = thermal_get_temp(udev, &temp); + + if (!ret) + printf(" at %dC", temp); + else + debug(" - invalid sensor data\n"); + } else { + debug(" - invalid sensor device\n"); + } +#endif + puts("\n"); + + printf("Reset cause: %s", get_reset_cause(&ssrs_ret)); + printf("(0x%x)\n", ssrs_ret); return 0; } +void build_info(void) +{ + u32 fw_version, sha1, res, status; + int ret; + + printf("\nBuildInfo:\n"); + + ret = ahab_get_fw_status(&status, &res); + if (ret) { + printf(" - ELE firmware status failed %d, 0x%x\n", ret, res); + } else if ((status & 0xff) == 1) { + ret = ahab_get_fw_version(&fw_version, &sha1, &res); + if (ret) { + printf(" - ELE firmware version failed %d, 0x%x\n", ret, res); + } else { + printf(" - ELE firmware version %u.%u.%u-%x", + (fw_version & (0x00ff0000)) >> 16, + (fw_version & (0x0000ff00)) >> 8, + (fw_version & (0x000000ff)), sha1); + ((fw_version & (0x80000000)) >> 31) == 1 ? puts("-dirty\n") : puts("\n"); + } + } else { + printf(" - ELE firmware not included\n"); + } + puts("\n"); +} + int arch_misc_init(void) { + build_info(); + return 0; +} + +static int delete_fdt_nodes(void *blob, const char *const nodes_path[], int size_array) +{ + int i = 0; + int rc; + int nodeoff; + + for (i = 0; i < size_array; i++) { + nodeoff = fdt_path_offset(blob, nodes_path[i]); + if (nodeoff < 0) + continue; /* Not found, skip it */ + + debug("Found %s node\n", nodes_path[i]); + + rc = fdt_del_node(blob, nodeoff); + if (rc < 0) { + printf("Unable to delete node %s, err=%s\n", + nodes_path[i], fdt_strerror(rc)); + } else { + printf("Delete node %s\n", nodes_path[i]); + } + } + + return 0; +} + +static int disable_npu_nodes(void *blob) +{ + static const char * const nodes_path_npu[] = { + "/ethosu", + "/reserved-memory/ethosu_region@C0000000" + }; + + return delete_fdt_nodes(blob, nodes_path_npu, ARRAY_SIZE(nodes_path_npu)); +} + +static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores) +{ + static const char * const thermal_path[] = { + "/thermal-zones/cpu-thermal/cooling-maps/map0" + }; + + int nodeoff, cnt, i, ret, j; + u32 cooling_dev[6]; + + for (i = 0; i < ARRAY_SIZE(thermal_path); i++) { + nodeoff = fdt_path_offset(blob, thermal_path[i]); + if (nodeoff < 0) + continue; /* Not found, skip it */ + + cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 6); + if (cnt < 0) + continue; + + if (cnt != 6) + printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt); + + for (j = 0; j < cnt; j++) + cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]); + + ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev, + sizeof(u32) * (6 - disabled_cores * 3)); + if (ret < 0) { + printf("Warning: %s, cooling-device setprop failed %d\n", + thermal_path[i], ret); + continue; + } + + printf("Update node %s, cooling-device prop\n", thermal_path[i]); + } +} + +static int disable_cpu_nodes(void *blob, u32 disabled_cores) +{ + u32 i = 0; + int rc; + int nodeoff; + char nodes_path[32]; + + for (i = 1; i <= disabled_cores; i++) { + + sprintf(nodes_path, "/cpus/cpu@%u00", i); + + nodeoff = fdt_path_offset(blob, nodes_path); + if (nodeoff < 0) + continue; /* Not found, skip it */ + + debug("Found %s node\n", nodes_path); + + rc = fdt_del_node(blob, nodeoff); + if (rc < 0) { + printf("Unable to delete node %s, err=%s\n", + nodes_path, fdt_strerror(rc)); + } else { + printf("Delete node %s\n", nodes_path); + } + } + + disable_thermal_cpu_nodes(blob, 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()) + disable_cpu_nodes(blob, 1); + + 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); } @@ -358,6 +927,9 @@ int arch_cpu_init(void) clock_init(); trdc_early_init(); + + /* Save SRC SRSR to GPR1 and clear it */ + save_reset_cause(); } return 0; |