summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx/imx8m/soc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-imx/imx8m/soc.c')
-rw-r--r--arch/arm/mach-imx/imx8m/soc.c361
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;