diff options
Diffstat (limited to 'arch/arm/mach-imx/imx8m/soc.c')
-rw-r--r-- | arch/arm/mach-imx/imx8m/soc.c | 361 |
1 files changed, 281 insertions, 80 deletions
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 7397b99a1ee..8171631db10 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2017-2019 NXP + * Copyright 2017-2019, 2021 NXP * * Peng Fan <peng.fan@nxp.com> */ @@ -21,6 +21,7 @@ #include <asm/ptrace.h> #include <asm/armv8/mmu.h> #include <dm/uclass.h> +#include <dm/device.h> #include <efi_loader.h> #include <env.h> #include <env_internal.h> @@ -28,7 +29,6 @@ #include <fdt_support.h> #include <fsl_wdog.h> #include <imx_sip.h> -#include <linux/arm-smccc.h> #include <linux/bitops.h> DECLARE_GLOBAL_DATA_PTR; @@ -72,7 +72,7 @@ void enable_tzc380(void) * According to TRM, TZASC_ID_SWAP_BYPASS should be set in * order to avoid AXI Bus errors when GPU is in use */ - if (is_imx8mm() || is_imx8mn() || is_imx8mp()) + if (is_imx8mq() || is_imx8mm() || is_imx8mn() || is_imx8mp()) setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS); /* @@ -188,32 +188,29 @@ static unsigned int imx8m_find_dram_entry_in_mem_map(void) void enable_caches(void) { - /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch */ - if (rom_pointer[1]) { - /* - * TEE are loaded, So the ddr bank structures - * have been modified update mmu table accordingly - */ - int i = 0; - /* - * please make sure that entry initial value matches - * imx8m_mem_map for DRAM1 - */ - int entry = imx8m_find_dram_entry_in_mem_map(); - u64 attrs = imx8m_mem_map[entry].attrs; - - while (i < CONFIG_NR_DRAM_BANKS && - entry < ARRAY_SIZE(imx8m_mem_map)) { - if (gd->bd->bi_dram[i].start == 0) - break; - imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start; - imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start; - imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size; - imx8m_mem_map[entry].attrs = attrs; - debug("Added memory mapping (%d): %llx %llx\n", entry, - imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size); - i++; entry++; - } + /* 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 + * imx8m_mem_map for DRAM1 + */ + int entry = imx8m_find_dram_entry_in_mem_map(); + u64 attrs = imx8m_mem_map[entry].attrs; + + while (i < CONFIG_NR_DRAM_BANKS && + entry < ARRAY_SIZE(imx8m_mem_map)) { + if (gd->bd->bi_dram[i].start == 0) + break; + imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start; + imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start; + imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size; + imx8m_mem_map[entry].attrs = attrs; + debug("Added memory mapping (%d): %llx %llx\n", entry, + imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size); + i++; entry++; } icache_enable(); @@ -226,12 +223,15 @@ __weak int board_phys_sdram_size(phys_size_t *size) return -EINVAL; *size = PHYS_SDRAM_SIZE; + +#ifdef PHYS_SDRAM_2_SIZE + *size += PHYS_SDRAM_2_SIZE; +#endif return 0; } int dram_init(void) { - unsigned int entry = imx8m_find_dram_entry_in_mem_map(); phys_size_t sdram_size; int ret; @@ -245,13 +245,6 @@ int dram_init(void) else gd->ram_size = sdram_size; - /* also update the SDRAM size in the mem_map used externally */ - imx8m_mem_map[entry].size = sdram_size; - -#ifdef PHYS_SDRAM_2_SIZE - gd->ram_size += PHYS_SDRAM_2_SIZE; -#endif - return 0; } @@ -260,18 +253,28 @@ 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 > 0xc0000000) { + sdram_b1_size = 0xc0000000; + sdram_b2_size = sdram_size - 0xc0000000; + } 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_size)) { + 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; @@ -279,35 +282,51 @@ int dram_init_banksize(void) gd->bd->bi_dram[bank].start = optee_start + optee_size; gd->bd->bi_dram[bank].size = PHYS_SDRAM + - sdram_size - gd->bd->bi_dram[bank].start; + sdram_b1_size - gd->bd->bi_dram[bank].start; } } else { - gd->bd->bi_dram[bank].size = sdram_size; + gd->bd->bi_dram[bank].size = sdram_b1_size; } -#ifdef PHYS_SDRAM_2_SIZE - if (++bank >= CONFIG_NR_DRAM_BANKS) { - puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n"); - return -1; + 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; } - gd->bd->bi_dram[bank].start = PHYS_SDRAM_2; - gd->bd->bi_dram[bank].size = PHYS_SDRAM_2_SIZE; -#endif return 0; } phys_size_t get_effective_memsize(void) { - /* return the first bank as effective memory */ - if (rom_pointer[1]) - return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM); + 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 > 0xc0000000) { + sdram_b1_size = 0xc0000000; + } else { + sdram_b1_size = sdram_size; + } -#ifdef PHYS_SDRAM_2_SIZE - return gd->ram_size - PHYS_SDRAM_2_SIZE; -#else - return gd->ram_size; -#endif + 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; + } } ulong board_get_usable_ram_top(ulong total_size) @@ -408,13 +427,27 @@ static u32 get_cpu_variant_type(u32 type) /* npu disabled*/ if ((value & 0x8) == 0x8) - flag |= (1 << 1); + flag |= BIT(1); /* isp disabled */ if ((value & 0x3) == 0x3) - flag |= (1 << 2); + flag |= BIT(2); + + /* gpu disabled */ + if ((value & 0xc0) == 0xc0) + flag |= BIT(3); + + /* lvds disabled */ + if ((value & 0x180000) == 0x180000) + flag |= BIT(4); + + /* mipi dsi disabled */ + if ((value & 0x60000) == 0x60000) + flag |= BIT(5); switch (flag) { + case 0x3f: + return MXC_CPU_IMX8MPUL; case 7: return MXC_CPU_IMX8MPL; case 2: @@ -517,6 +550,11 @@ EVENT_SPY(EVT_DM_POST_INIT, imx8m_check_clock); int arch_cpu_init(void) { struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + +#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) + icache_enable(); +#endif + /* * ROM might disable clock for SCTR, * enable the clock before timer_init. @@ -599,6 +637,9 @@ enum boot_device get_boot_device(void) case BT_DEV_TYPE_FLEXSPINOR: boot_dev = QSPI_BOOT; break; + case BT_DEV_TYPE_SPI_NOR: + boot_dev = SPI_NOR_BOOT; + break; case BT_DEV_TYPE_USB: boot_dev = USB_BOOT; break; @@ -893,6 +934,90 @@ static int low_drive_gpu_freq(void *blob) } #endif +static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2) +{ + int lookup_node; + int nodeoff; + + nodeoff = fdt_path_offset(blob, ep1); + if (nodeoff) { + lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint"); + nodeoff = fdt_path_offset(blob, ep2); + + if (nodeoff > 0 && nodeoff == lookup_node) + return true; + } + + return false; +} + +int disable_dsi_lcdif_nodes(void *blob) +{ + int ret; + + static const char * const dsi_path_8mp[] = { + "/soc@0/bus@32c00000/mipi_dsi@32e60000" + }; + + static const char * const lcdif_path_8mp[] = { + "/soc@0/bus@32c00000/lcd-controller@32e80000" + }; + + static const char * const lcdif_ep_path_8mp[] = { + "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint" + }; + static const char * const dsi_ep_path_8mp[] = { + "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint" + }; + + ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp)); + if (ret) + return ret; + + if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) { + /* Disable lcdif node */ + return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp)); + } + + return 0; +} + +int disable_lvds_lcdif_nodes(void *blob) +{ + int ret, i; + + static const char * const ldb_path_8mp[] = { + "/soc@0/bus@32c00000/ldb@32ec005c", + "/soc@0/bus@32c00000/phy@32ec0128" + }; + + static const char * const lcdif_path_8mp[] = { + "/soc@0/bus@32c00000/lcd-controller@32e90000" + }; + + static const char * const lcdif_ep_path_8mp[] = { + "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0", + "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1" + }; + static const char * const ldb_ep_path_8mp[] = { + "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint", + "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint" + }; + + ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp)); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) { + if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) { + /* Disable lcdif node */ + return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp)); + } + } + + return 0; +} + int disable_gpu_nodes(void *blob) { static const char * const nodes_path_8mn[] = { @@ -900,7 +1025,15 @@ int disable_gpu_nodes(void *blob) "/soc@/gpu@38000000" }; - return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn)); + static const char * const nodes_path_8mp[] = { + "/gpu3d@38000000", + "/gpu2d@38008000" + }; + + if (is_imx8mp()) + return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp)); + else + return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn)); } int disable_npu_nodes(void *blob) @@ -1042,6 +1175,37 @@ static int disable_cpu_nodes(void *blob, u32 disabled_cores) return 0; } +static int cleanup_nodes_for_efi(void *blob) +{ + static const char * const path[][2] = { + { "/soc@0/bus@32c00000/usb@32e40000", "extcon" }, + { "/soc@0/bus@32c00000/usb@32e50000", "extcon" }, + { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" }, + { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" } + }; + int nodeoff, i, rc; + + for (i = 0; i < ARRAY_SIZE(path); i++) { + nodeoff = fdt_path_offset(blob, path[i][0]); + if (nodeoff < 0) + continue; /* Not found, skip it */ + debug("Found %s node\n", path[i][0]); + + rc = fdt_delprop(blob, nodeoff, path[i][1]); + if (rc == -FDT_ERR_NOTFOUND) + continue; + if (rc) { + printf("Unable to update property %s:%s, err=%s\n", + path[i][0], path[i][1], fdt_strerror(rc)); + return rc; + } + + printf("Remove %s:%s\n", path[i][0], path[i][1]); + } + + return 0; +} + int ft_system_setup(void *blob, struct bd_info *bd) { #ifdef CONFIG_IMX8MQ @@ -1156,26 +1320,72 @@ usb_modify_speed: disable_cpu_nodes(blob, 3); #elif defined(CONFIG_IMX8MP) - if (is_imx8mpl()) + if (is_imx8mpul()) { + /* Disable GPU */ + disable_gpu_nodes(blob); + + /* Disable DSI */ + disable_dsi_lcdif_nodes(blob); + + /* Disable LVDS */ + disable_lvds_lcdif_nodes(blob); + } + + if (is_imx8mpul() || is_imx8mpl()) disable_vpu_nodes(blob); - if (is_imx8mpl() || is_imx8mp6()) + if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6()) disable_npu_nodes(blob); - if (is_imx8mpl()) + if (is_imx8mpul() || is_imx8mpl()) disable_isp_nodes(blob); - if (is_imx8mpl() || is_imx8mp6()) + if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6()) disable_dsp_nodes(blob); if (is_imx8mpd()) disable_cpu_nodes(blob, 2); #endif + cleanup_nodes_for_efi(blob); return 0; } #endif +#ifdef CONFIG_OF_BOARD_FIXUP +#ifndef CONFIG_SPL_BUILD +int board_fix_fdt(void *fdt) +{ + if (is_imx8mpul()) { + int i = 0; + int nodeoff, ret; + const char *status = "disabled"; + static const char * const dsi_nodes[] = { + "/soc@0/bus@32c00000/mipi_dsi@32e60000", + "/soc@0/bus@32c00000/lcd-controller@32e80000", + "/dsi-host" + }; + + for (i = 0; i < ARRAY_SIZE(dsi_nodes); i++) { + nodeoff = fdt_path_offset(fdt, dsi_nodes[i]); + if (nodeoff > 0) { +set_status: + ret = fdt_setprop(fdt, nodeoff, "status", status, + strlen(status) + 1); + if (ret == -FDT_ERR_NOSPACE) { + ret = fdt_increase_size(fdt, 512); + if (!ret) + goto set_status; + } + } + } + } + + return 0; +} +#endif +#endif + #if !CONFIG_IS_ENABLED(SYSRESET) void reset_cpu(void) { @@ -1193,26 +1403,16 @@ void reset_cpu(void) #endif #if defined(CONFIG_ARCH_MISC_INIT) -static void acquire_buildinfo(void) -{ - u64 atf_commit = 0; - struct arm_smccc_res res; - - /* Get ARM Trusted Firmware commit id */ - arm_smccc_smc(IMX_SIP_BUILDINFO, IMX_SIP_BUILDINFO_GET_COMMITHASH, - 0, 0, 0, 0, 0, 0, &res); - atf_commit = res.a0; - if (atf_commit == 0xffffffff) { - debug("ATF does not support build info\n"); - atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */ - } - - printf("\n BuildInfo:\n - ATF %s\n\n", (char *)&atf_commit); -} - int arch_misc_init(void) { - acquire_buildinfo(); + if (IS_ENABLED(CONFIG_FSL_CAAM)) { + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev); + if (ret) + printf("Failed to initialize %s: %d\n", dev->name, ret); + } return 0; } @@ -1337,6 +1537,7 @@ enum env_location env_get_location(enum env_operation op, int prio) switch (dev) { case QSPI_BOOT: + case SPI_NOR_BOOT: if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)) return ENVL_SPI_FLASH; return ENVL_NOWHERE; |