summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/cmd_dek.c1
-rw-r--r--arch/arm/mach-imx/cpu.c2
-rw-r--r--arch/arm/mach-imx/imx8/Kconfig7
-rw-r--r--arch/arm/mach-imx/imx8/cpu.c18
-rw-r--r--arch/arm/mach-imx/imx8m/Kconfig44
-rw-r--r--arch/arm/mach-imx/imx8m/clock_imx8mm.c1
-rw-r--r--arch/arm/mach-imx/imx8m/soc.c361
-rw-r--r--arch/arm/mach-imx/imx8ulp/Kconfig7
-rw-r--r--arch/arm/mach-imx/imx8ulp/cgc.c106
-rw-r--r--arch/arm/mach-imx/imx8ulp/clock.c95
-rw-r--r--arch/arm/mach-imx/imx8ulp/pcc.c1
-rw-r--r--arch/arm/mach-imx/imx8ulp/soc.c197
-rw-r--r--arch/arm/mach-imx/mx6/Kconfig10
-rw-r--r--arch/arm/mach-imx/mx6/ddr.c13
-rw-r--r--arch/arm/mach-imx/mx6/soc.c13
-rw-r--r--arch/arm/mach-imx/mx7/Kconfig1
-rw-r--r--arch/arm/mach-imx/mx7/soc.c12
-rw-r--r--arch/arm/mach-imx/mx7ulp/Kconfig2
-rw-r--r--arch/arm/mach-imx/mx7ulp/soc.c18
-rw-r--r--arch/arm/mach-imx/parse-container.c4
-rw-r--r--arch/arm/mach-imx/spl_imx_romapi.c10
21 files changed, 765 insertions, 158 deletions
diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c
index 89da89c51d5..04c4b20a84b 100644
--- a/arch/arm/mach-imx/cmd_dek.c
+++ b/arch/arm/mach-imx/cmd_dek.c
@@ -9,6 +9,7 @@
#include <command.h>
#include <log.h>
#include <malloc.h>
+#include <memalign.h>
#include <asm/byteorder.h>
#include <linux/compiler.h>
#include <fsl_sec.h>
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index 8eb05c8dd67..ba386c24b4a 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -106,6 +106,8 @@ const char *get_imx_type(u32 imxtype)
return "8MP Lite[4]"; /* Quad-core Lite version of the imx8mp */
case MXC_CPU_IMX8MP6:
return "8MP[6]"; /* Quad-core version of the imx8mp, NPU fused */
+ case MXC_CPU_IMX8MPUL:
+ return "8MP UltraLite"; /* Quad-core UltraLite version of the imx8mp */
case MXC_CPU_IMX8MN:
return "8MNano Quad"; /* Quad-core version */
case MXC_CPU_IMX8MND:
diff --git a/arch/arm/mach-imx/imx8/Kconfig b/arch/arm/mach-imx/imx8/Kconfig
index b43739e5c64..f969833baba 100644
--- a/arch/arm/mach-imx/imx8/Kconfig
+++ b/arch/arm/mach-imx/imx8/Kconfig
@@ -8,6 +8,7 @@ config AHAB_BOOT
config IMX8
bool
+ select HAS_CAAM
config MU_BASE_SPL
hex "MU base address used in SPL"
@@ -72,6 +73,9 @@ config TARGET_IMX8QM_MEK
bool "Support i.MX8QM MEK board"
select BOARD_LATE_INIT
select IMX8QM
+ select FSL_CAAM
+ select ARCH_MISC_INIT
+ select SPL_CRYPTO if SPL
config TARGET_CONGA_QMX8
bool "Support congatec conga-QMX8 board"
@@ -89,6 +93,9 @@ config TARGET_IMX8QXP_MEK
bool "Support i.MX8QXP MEK board"
select BOARD_LATE_INIT
select IMX8QXP
+ select FSL_CAAM
+ select ARCH_MISC_INIT
+ select SPL_CRYPTO if SPL
endchoice
diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c
index 359f8c796eb..0858ea5f057 100644
--- a/arch/arm/mach-imx/imx8/cpu.c
+++ b/arch/arm/mach-imx/imx8/cpu.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright 2018 NXP
+ * Copyright 2018, 2021 NXP
*/
#include <common.h>
@@ -91,6 +91,22 @@ static int imx8_init_mu(void *ctx, struct event *event)
}
EVENT_SPY(EVT_DM_POST_INIT, imx8_init_mu);
+#if defined(CONFIG_ARCH_MISC_INIT)
+int arch_misc_init(void)
+{
+ 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;
+}
+#endif
+
int print_bootinfo(void)
{
enum boot_device bt_dev = get_boot_device();
diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig
index fae70499953..55db25062a9 100644
--- a/arch/arm/mach-imx/imx8m/Kconfig
+++ b/arch/arm/mach-imx/imx8m/Kconfig
@@ -39,6 +39,9 @@ config TARGET_IMX8MQ_EVK
select BINMAN
select IMX8MQ
select IMX8M_LPDDR4
+ select FSL_CAAM
+ select ARCH_MISC_INIT
+ select SPL_CRYPTO if SPL
config TARGET_IMX8MQ_PHANBELL
bool "imx8mq_phanbell"
@@ -46,12 +49,22 @@ config TARGET_IMX8MQ_PHANBELL
select IMX8MQ
select IMX8M_LPDDR4
+config TARGET_IMX8MM_DATA_MODUL_EDM_SBC
+ bool "Data Modul eDM SBC i.MX8M Mini"
+ select BINMAN
+ select IMX8MM
+ select IMX8M_LPDDR4
+ select SUPPORT_SPL
+
config TARGET_IMX8MM_EVK
bool "imx8mm LPDDR4 EVK board"
select BINMAN
select IMX8MM
select SUPPORT_SPL
select IMX8M_LPDDR4
+ select FSL_CAAM
+ select ARCH_MISC_INIT
+ select SPL_CRYPTO if SPL
config TARGET_IMX8MM_ICORE_MX8MM
bool "Engicam i.Core MX8M Mini SOM"
@@ -71,6 +84,13 @@ config TARGET_IMX8MM_ICORE_MX8MM
* i.Core MX8M Mini needs to mount on top of this Carrier board
for creating complete i.Core MX8M Mini C.TOUCH 2.0 board.
+config TARGET_IMX8MM_MX8MENLO
+ bool "Support i.MX8M Mini MX8Menlo board based on Toradex Verdin SoM"
+ select BINMAN
+ select IMX8MM
+ select SUPPORT_SPL
+ select IMX8M_LPDDR4
+
config TARGET_IMX8MM_VENICE
bool "Support Gateworks Venice iMX8M Mini module"
select BINMAN
@@ -85,12 +105,28 @@ config TARGET_KONTRON_MX8MM
select SUPPORT_SPL
select IMX8M_LPDDR4
+config TARGET_IMX8MN_BSH_SMM_S2
+ bool "imx8mn-bsh-smm-s2"
+ select BINMAN
+ select IMX8MN
+ select SUPPORT_SPL
+ select IMX8M_DDR3L
+
+config TARGET_IMX8MN_BSH_SMM_S2PRO
+ bool "imx8mn-bsh-smm-s2pro"
+ select BINMAN
+ select IMX8MN
+ select SUPPORT_SPL
+ select IMX8M_DDR3L
+
config TARGET_IMX8MN_EVK
bool "imx8mn LPDDR4 EVK board"
select BINMAN
select IMX8MN
select SUPPORT_SPL
select IMX8M_LPDDR4
+ select FSL_CAAM
+ select SPL_CRYPTO if SPL
config TARGET_IMX8MN_DDR4_EVK
bool "imx8mn DDR4 EVK board"
@@ -98,6 +134,8 @@ config TARGET_IMX8MN_DDR4_EVK
select IMX8MN
select SUPPORT_SPL
select IMX8M_DDR4
+ select FSL_CAAM
+ select SPL_CRYPTO if SPL
config TARGET_IMX8MN_VENICE
bool "Support Gateworks Venice iMX8M Nano module"
@@ -112,6 +150,9 @@ config TARGET_IMX8MP_EVK
select IMX8MP
select SUPPORT_SPL
select IMX8M_LPDDR4
+ select FSL_CAAM
+ select ARCH_MISC_INIT
+ select SPL_CRYPTO if SPL
config TARGET_PICO_IMX8MQ
bool "Support Technexion Pico iMX8MQ"
@@ -208,7 +249,9 @@ endchoice
source "board/advantech/imx8mp_rsb3720a1/Kconfig"
source "board/beacon/imx8mm/Kconfig"
source "board/beacon/imx8mn/Kconfig"
+source "board/bsh/imx8mn_smm_s2/Kconfig"
source "board/compulab/imx8mm-cl-iot-gate/Kconfig"
+source "board/data_modul/imx8mm_edm_sbc/Kconfig"
source "board/engicam/imx8mm/Kconfig"
source "board/freescale/imx8mq_evk/Kconfig"
source "board/freescale/imx8mm_evk/Kconfig"
@@ -218,6 +261,7 @@ source "board/gateworks/venice/Kconfig"
source "board/google/imx8mq_phanbell/Kconfig"
source "board/kontron/pitx_imx8m/Kconfig"
source "board/kontron/sl-mx8mm/Kconfig"
+source "board/menlo/mx8menlo/Kconfig"
source "board/phytec/phycore_imx8mm/Kconfig"
source "board/phytec/phycore_imx8mp/Kconfig"
source "board/ronetix/imx8mq-cm/Kconfig"
diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
index 76132defc21..4db55f86081 100644
--- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c
+++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
@@ -48,6 +48,7 @@ int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
#ifdef CONFIG_SPL_BUILD
static struct imx_int_pll_rate_table imx8mm_fracpll_tbl[] = {
PLL_1443X_RATE(1000000000U, 250, 3, 1, 0),
+ PLL_1443X_RATE(933000000U, 311, 4, 1, 0),
PLL_1443X_RATE(800000000U, 300, 9, 0, 0),
PLL_1443X_RATE(750000000U, 250, 8, 0, 0),
PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
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;
diff --git a/arch/arm/mach-imx/imx8ulp/Kconfig b/arch/arm/mach-imx/imx8ulp/Kconfig
index 963fc93d34f..bbdeaac07b3 100644
--- a/arch/arm/mach-imx/imx8ulp/Kconfig
+++ b/arch/arm/mach-imx/imx8ulp/Kconfig
@@ -2,11 +2,16 @@ if ARCH_IMX8ULP
config IMX8ULP
bool
- select ARMV8_SPL_EXCEPTION_VECTORS
config SYS_SOC
default "imx8ulp"
+config IMX8ULP_LD_MODE
+ bool
+
+config IMX8ULP_ND_MODE
+ bool "i.MX8ULP Low Driver Mode"
+
choice
prompt "i.MX8ULP board select"
optional
diff --git a/arch/arm/mach-imx/imx8ulp/cgc.c b/arch/arm/mach-imx/imx8ulp/cgc.c
index 38bcbb91e6e..d240abaee46 100644
--- a/arch/arm/mach-imx/imx8ulp/cgc.c
+++ b/arch/arm/mach-imx/imx8ulp/cgc.c
@@ -9,9 +9,11 @@
#include <errno.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/cgc.h>
+#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <asm/global_data.h>
#include <linux/delay.h>
+#include <hang.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -29,7 +31,7 @@ void cgc1_soscdiv_init(void)
clrbits_le32(&cgc1_regs->frodiv, BIT(7));
}
-void cgc1_pll2_init(void)
+void cgc1_pll2_init(ulong freq)
{
u32 reg;
@@ -44,8 +46,8 @@ void cgc1_pll2_init(void)
while ((readl(&cgc1_regs->pll2csr) & BIT(24)))
;
- /* Select SOSC as source, freq = 31 * 24 =744mhz */
- reg = 31 << 16;
+ /* Select SOSC as source */
+ reg = (freq / MHZ(24)) << 16;
writel(reg, &cgc1_regs->pll2cfg);
/* Enable PLL2 */
@@ -74,7 +76,7 @@ static void cgc1_set_a35_clk(u32 clk_src, u32 div_core)
;
}
-void cgc1_init_core_clk(void)
+void cgc1_init_core_clk(ulong freq)
{
u32 reg = readl(&cgc1_regs->ca35clk);
@@ -82,8 +84,7 @@ void cgc1_init_core_clk(void)
if (((reg >> 28) & 0x3) == 0x1)
cgc1_set_a35_clk(0, 1);
- /* Set pll2 to 750Mhz for 1V */
- cgc1_pll2_init();
+ cgc1_pll2_init(freq);
/* Set A35 clock to pll2 */
cgc1_set_a35_clk(1, 1);
@@ -94,7 +95,7 @@ void cgc1_enet_stamp_sel(u32 clk_src)
writel((clk_src & 0x7) << 24, &cgc1_regs->enetstamp);
}
-void cgc1_pll3_init(void)
+void cgc1_pll3_init(ulong freq)
{
/* Gate off VCO */
setbits_le32(&cgc1_regs->pll3div_vco, BIT(7));
@@ -115,11 +116,15 @@ void cgc1_pll3_init(void)
/* Select SOSC as source */
clrbits_le32(&cgc1_regs->pll3cfg, BIT(0));
- //setbits_le32(&cgc1_regs->pll3cfg, 22 << 16);
- writel(22 << 16, &cgc1_regs->pll3cfg);
-
- writel(578, &cgc1_regs->pll3num);
- writel(1000, &cgc1_regs->pll3denom);
+ switch (freq) {
+ case 540672000:
+ writel(0x16 << 16, &cgc1_regs->pll3cfg);
+ writel(0x16e3600, &cgc1_regs->pll3denom);
+ writel(0xc15c00, &cgc1_regs->pll3num);
+ break;
+ default:
+ hang();
+ }
/* Enable PLL3 */
setbits_le32(&cgc1_regs->pll3csr, BIT(0));
@@ -130,23 +135,30 @@ void cgc1_pll3_init(void)
/* Gate on VCO */
clrbits_le32(&cgc1_regs->pll3div_vco, BIT(7));
- /*
- * PFD0: 380MHz/396/396/328
- */
clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F);
- setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 0);
+
+ if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) {
+ setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 0);
+ clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(26, 21), 3 << 21); /* 195M */
+ } else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
+ setbits_le32(&cgc1_regs->pll3pfdcfg, 21 << 0);
+ clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(26, 21), 1 << 21); /* 231M */
+ } else {
+ setbits_le32(&cgc1_regs->pll3pfdcfg, 30 << 0); /* 324M */
+ }
+
clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(7));
while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(6)))
;
clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 8);
- setbits_le32(&cgc1_regs->pll3pfdcfg, 24 << 8);
+ setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 8);
clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(15));
while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(14)))
;
clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 16);
- setbits_le32(&cgc1_regs->pll3pfdcfg, 24 << 16);
+ setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 16);
clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(23));
while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(22)))
;
@@ -166,10 +178,25 @@ void cgc1_pll3_init(void)
clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(15));
clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(23));
clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(31));
+
+ if (!IS_ENABLED(CONFIG_IMX8ULP_LD_MODE) && !IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
+ /* nicclk select pll3 pfd0 */
+ clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(29, 28), BIT(28));
+ while (!(readl(&cgc1_regs->nicclk) & BIT(27)))
+ ;
+ }
}
-void cgc2_pll4_init(void)
+void cgc2_pll4_init(bool pll4_reset)
{
+ /* Check the NICLPAV first to ensure not from PLL4 PFD1 clock */
+ if ((readl(&cgc2_regs->niclpavclk) & GENMASK(29, 28)) == BIT(28)) {
+ /* switch to FRO 192 first */
+ clrbits_le32(&cgc2_regs->niclpavclk, GENMASK(29, 28));
+ while (!(readl(&cgc2_regs->niclpavclk) & BIT(27)))
+ ;
+ }
+
/* Disable PFD DIV and clear DIV */
writel(0x80808080, &cgc2_regs->pll4div_pfd0);
writel(0x80808080, &cgc2_regs->pll4div_pfd1);
@@ -177,22 +204,35 @@ void cgc2_pll4_init(void)
/* Gate off and clear PFD */
writel(0x80808080, &cgc2_regs->pll4pfdcfg);
- /* Disable PLL4 */
- writel(0x0, &cgc2_regs->pll4csr);
+ if (pll4_reset) {
+ /* Disable PLL4 */
+ writel(0x0, &cgc2_regs->pll4csr);
- /* Configure PLL4 to 528Mhz and clock source from SOSC */
- writel(22 << 16, &cgc2_regs->pll4cfg);
- writel(0x1, &cgc2_regs->pll4csr);
+ /* Configure PLL4 to 528Mhz and clock source from SOSC */
+ writel(22 << 16, &cgc2_regs->pll4cfg);
+ writel(0x1, &cgc2_regs->pll4csr);
- /* wait for PLL4 output valid */
- while (!(readl(&cgc2_regs->pll4csr) & BIT(24)))
- ;
+ /* wait for PLL4 output valid */
+ while (!(readl(&cgc2_regs->pll4csr) & BIT(24)))
+ ;
+ }
/* Enable all 4 PFDs */
- setbits_le32(&cgc2_regs->pll4pfdcfg, 18 << 0);
- setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 8); /* 316.8Mhz for NIC_LPAV */
- setbits_le32(&cgc2_regs->pll4pfdcfg, 12 << 16);
- setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 24);
+ setbits_le32(&cgc2_regs->pll4pfdcfg, 18 << 0); /* 528 */
+ if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) {
+ setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 8);
+ /* 99Mhz for NIC_LPAV */
+ clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21), 3 << 21);
+ } else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
+ setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 8);
+ /* 198Mhz for NIC_LPAV */
+ clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21), 1 << 21);
+ } else {
+ setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 8); /* 316.8Mhz for NIC_LPAV */
+ clrbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21));
+ }
+ setbits_le32(&cgc2_regs->pll4pfdcfg, 12 << 16); /* 792 */
+ setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 24); /* 396 */
clrbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) | BIT(15) | BIT(23) | BIT(31));
@@ -203,6 +243,10 @@ void cgc2_pll4_init(void)
/* Enable PFD DIV */
clrbits_le32(&cgc2_regs->pll4div_pfd0, BIT(7) | BIT(15) | BIT(23) | BIT(31));
clrbits_le32(&cgc2_regs->pll4div_pfd1, BIT(7) | BIT(15) | BIT(23) | BIT(31));
+
+ clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(29, 28), BIT(28));
+ while (!(readl(&cgc2_regs->niclpavclk) & BIT(27)))
+ ;
}
void cgc2_pll4_pfd_config(enum cgc_clk pllpfd, u32 pfd)
diff --git a/arch/arm/mach-imx/imx8ulp/clock.c b/arch/arm/mach-imx/imx8ulp/clock.c
index 91580b2c29c..3e71a4f6c3b 100644
--- a/arch/arm/mach-imx/imx8ulp/clock.c
+++ b/arch/arm/mach-imx/imx8ulp/clock.c
@@ -101,8 +101,8 @@ void init_clk_ddr(void)
writel(0xc0000000, PCC5_LPDDR4_ADDR);
/* enable pll4 and ddrclk*/
- cgc2_pll4_init();
- cgc2_ddrclk_config(1, 1);
+ cgc2_pll4_init(true);
+ cgc2_ddrclk_config(4, 1);
/* enable ddr pcc */
writel(0xd0000000, PCC5_LPDDR4_ADDR);
@@ -153,30 +153,69 @@ int set_ddr_clk(u32 phy_freq_mhz)
return 0;
}
-void clock_init(void)
+void clock_init_early(void)
{
cgc1_soscdiv_init();
- cgc1_init_core_clk();
init_clk_lpuart();
- pcc_clock_enable(4, SDHC0_PCC4_SLOT, false);
- pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD1_DIV2);
- pcc_clock_enable(4, SDHC0_PCC4_SLOT, true);
- pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false);
+ /* Enable upower mu1 clk */
+ pcc_clock_enable(3, UPOWER_PCC3_SLOT, true);
+}
- pcc_clock_enable(4, SDHC1_PCC4_SLOT, false);
- pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV1);
- pcc_clock_enable(4, SDHC1_PCC4_SLOT, true);
- pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false);
+/* This will be invoked after pmic voltage setting */
+void clock_init_late(void)
+{
- pcc_clock_enable(4, SDHC2_PCC4_SLOT, false);
- pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV1);
- pcc_clock_enable(4, SDHC2_PCC4_SLOT, true);
- pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false);
+ if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE))
+ cgc1_init_core_clk(MHZ(500));
+ else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE))
+ cgc1_init_core_clk(MHZ(750));
+ else
+ cgc1_init_core_clk(MHZ(960));
- /* Enable upower mu1 clk */
- pcc_clock_enable(3, UPOWER_PCC3_SLOT, true);
+ /*
+ * Audio use this frequency in kernel dts,
+ * however nic use pll3 pfd0, we have to
+ * make the freqency same as kernel to make nic
+ * not being disabled
+ */
+ cgc1_pll3_init(540672000);
+
+ if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE) || IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) {
+ pcc_clock_enable(4, SDHC0_PCC4_SLOT, false);
+ pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD2_DIV2);
+ pcc_clock_enable(4, SDHC0_PCC4_SLOT, true);
+ pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false);
+
+ pcc_clock_enable(4, SDHC1_PCC4_SLOT, false);
+ pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV2);
+ pcc_clock_enable(4, SDHC1_PCC4_SLOT, true);
+ pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false);
+
+ pcc_clock_enable(4, SDHC2_PCC4_SLOT, false);
+ pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV2);
+ pcc_clock_enable(4, SDHC2_PCC4_SLOT, true);
+ pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false);
+ } else {
+ pcc_clock_enable(4, SDHC0_PCC4_SLOT, false);
+ pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD1_DIV2);
+ pcc_clock_enable(4, SDHC0_PCC4_SLOT, true);
+ pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false);
+
+ pcc_clock_enable(4, SDHC1_PCC4_SLOT, false);
+ pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV1);
+ pcc_clock_enable(4, SDHC1_PCC4_SLOT, true);
+ pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false);
+
+ pcc_clock_enable(4, SDHC2_PCC4_SLOT, false);
+ pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV1);
+ pcc_clock_enable(4, SDHC2_PCC4_SLOT, true);
+ pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false);
+ }
+
+ /* enable MU0_MUB clock before access the register of MU0_MUB */
+ pcc_clock_enable(3, MU0_B_PCC3_SLOT, true);
/*
* Enable clock division
@@ -237,6 +276,26 @@ u32 imx_get_i2cclk(u32 i2c_num)
}
#endif
+#if IS_ENABLED(CONFIG_SYS_I2C_IMX_I3C)
+int enable_i3c_clk(unsigned char enable, u32 i3c_num)
+{
+ if (enable) {
+ pcc_clock_enable(3, I3C2_PCC3_SLOT, false);
+ pcc_clock_sel(3, I3C2_PCC3_SLOT, SOSC_DIV2);
+ pcc_clock_enable(3, I3C2_PCC3_SLOT, true);
+ pcc_reset_peripheral(3, I3C2_PCC3_SLOT, false);
+ } else {
+ pcc_clock_enable(3, I3C2_PCC3_SLOT, false);
+ }
+ return 0;
+}
+
+u32 imx_get_i3cclk(u32 i3c_num)
+{
+ return pcc_clock_get_rate(3, I3C2_PCC3_SLOT);
+}
+#endif
+
void enable_usboh3_clk(unsigned char enable)
{
if (enable) {
diff --git a/arch/arm/mach-imx/imx8ulp/pcc.c b/arch/arm/mach-imx/imx8ulp/pcc.c
index 7909d770afe..e3c6d6760be 100644
--- a/arch/arm/mach-imx/imx8ulp/pcc.c
+++ b/arch/arm/mach-imx/imx8ulp/pcc.c
@@ -135,6 +135,7 @@ static struct pcc_entry pcc3_arrays[] = {
{PCC3_RBASE, UPOWER_PCC3_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B},
{PCC3_RBASE, WDOG3_PCC3_SLOT, CLKSRC_PER_BUS, PCC_HAS_DIV, PCC_HAS_RST_B},
{PCC3_RBASE, WDOG4_PCC3_SLOT, CLKSRC_PER_BUS, PCC_HAS_DIV, PCC_HAS_RST_B},
+ {PCC3_RBASE, CAAM_PCC3_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_HAS_RST_B},
{PCC3_RBASE, XRDC_MGR_PCC3_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B},
{PCC3_RBASE, SEMA42_1_PCC3_SLOT, CLKSRC_PER_BUS, PCC_NO_DIV, PCC_NO_RST_B},
{PCC3_RBASE, ROMCP1_PCC3_SLOT, CLKSRC_NO_PCS, PCC_NO_DIV, PCC_NO_RST_B},
diff --git a/arch/arm/mach-imx/imx8ulp/soc.c b/arch/arm/mach-imx/imx8ulp/soc.c
index e6d417ed48b..35020c9714d 100644
--- a/arch/arm/mach-imx/imx8ulp/soc.c
+++ b/arch/arm/mach-imx/imx8ulp/soc.c
@@ -26,6 +26,9 @@
#include <dm/uclass-internal.h>
#include <fuse.h>
#include <thermal.h>
+#include <linux/iopoll.h>
+#include <env.h>
+#include <env_internal.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -137,6 +140,38 @@ enum bt_mode get_boot_mode(void)
return LOW_POWER_BOOT;
}
+bool m33_image_booted(void)
+{
+ u32 gp6;
+
+ /* DGO_GP6 */
+ gp6 = readl(SIM_SEC_BASE_ADDR + 0x28);
+ if (gp6 & BIT(5))
+ return true;
+
+ return false;
+}
+
+int m33_image_handshake(ulong timeout_ms)
+{
+ u32 fsr;
+ int ret;
+ ulong timeout_us = timeout_ms * 1000;
+
+ /* Notify m33 that it's ready to do init srtm(enable mu receive interrupt and so on) */
+ setbits_le32(MU0_B_BASE_ADDR + 0x100, BIT(0)); /* set FCR F0 flag of MU0_MUB */
+
+ /*
+ * Wait m33 to set FCR F0 flag of MU0_MUA
+ * Clear FCR F0 flag of MU0_MUB after m33 has set FCR F0 flag of MU0_MUA
+ */
+ ret = readl_poll_sleep_timeout(MU0_B_BASE_ADDR + 0x104, fsr, fsr & BIT(0), 10, timeout_us);
+ if (!ret)
+ clrbits_le32(MU0_B_BASE_ADDR + 0x100, BIT(0));
+
+ return ret;
+}
+
#define CMC_SRS_TAMPER BIT(31)
#define CMC_SRS_SECURITY BIT(30)
#define CMC_SRS_TZWDG BIT(29)
@@ -380,6 +415,17 @@ static struct mm_region imx8ulp_arm64_mem_map[] = {
struct mm_region *mem_map = imx8ulp_arm64_mem_map;
+static unsigned int imx8ulp_find_dram_entry_in_mem_map(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(imx8ulp_arm64_mem_map); i++)
+ if (imx8ulp_arm64_mem_map[i].phys == CONFIG_SYS_SDRAM_BASE)
+ return i;
+
+ hang(); /* Entry not found, this must never happen. */
+}
+
/* simplify the page table size to enhance boot speed */
#define MAX_PTE_ENTRIES 512
#define MAX_MEM_MAP_REGIONS 16
@@ -411,19 +457,106 @@ u64 get_page_table_size(void)
void enable_caches(void)
{
- /* TODO: add TEE memmap region */
+ /* 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;
+ int entry = imx8ulp_find_dram_entry_in_mem_map();
+ u64 attrs = imx8ulp_arm64_mem_map[entry].attrs;
+
+ while (i < CONFIG_NR_DRAM_BANKS &&
+ entry < ARRAY_SIZE(imx8ulp_arm64_mem_map)) {
+ if (gd->bd->bi_dram[i].start == 0)
+ break;
+ imx8ulp_arm64_mem_map[entry].phys = gd->bd->bi_dram[i].start;
+ imx8ulp_arm64_mem_map[entry].virt = gd->bd->bi_dram[i].start;
+ imx8ulp_arm64_mem_map[entry].size = gd->bd->bi_dram[i].size;
+ imx8ulp_arm64_mem_map[entry].attrs = attrs;
+ debug("Added memory mapping (%d): %llx %llx\n", entry,
+ imx8ulp_arm64_mem_map[entry].phys, imx8ulp_arm64_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;
+ return 0;
+}
+
int dram_init(void)
{
- gd->ram_size = PHYS_SDRAM_SIZE;
+ unsigned int entry = imx8ulp_find_dram_entry_in_mem_map();
+ 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;
+ /* also update the SDRAM size in the mem_map used externally */
+ imx8ulp_arm64_mem_map[entry].size = sdram_size;
return 0;
}
+int dram_init_banksize(void)
+{
+ int bank = 0;
+ int ret;
+ phys_size_t sdram_size;
+
+ ret = board_phys_sdram_size(&sdram_size);
+ if (ret)
+ return ret;
+
+ 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 (++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_size - gd->bd->bi_dram[bank].start;
+ }
+ } else {
+ gd->bd->bi_dram[bank].size = sdram_size;
+ }
+
+ 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);
+
+ return gd->ram_size;
+}
+
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
void get_board_serial(struct tag_serialnr *serialnr)
{
@@ -491,10 +624,10 @@ static int trdc_set_access(void)
return 0;
}
-void lpav_configure(void)
+void lpav_configure(bool lpav_to_m33)
{
- /* LPAV to APD */
- setbits_le32(SIM_SEC_BASE_ADDR + 0x44, BIT(7));
+ if (!lpav_to_m33)
+ setbits_le32(SIM_SEC_BASE_ADDR + 0x44, BIT(7)); /* LPAV to APD */
/* PXP/GPU 2D/3D/DCNANO/MIPI_DSI/EPDC/HIFI4 to APD */
setbits_le32(SIM_SEC_BASE_ADDR + 0x4c, 0x7F);
@@ -538,6 +671,19 @@ int arch_cpu_init(void)
int ret;
bool rdc_en = true; /* Default assume DBD_EN is set */
+ /* Enable System Reset Interrupt using WDOG_AD */
+ setbits_le32(CMC1_BASE_ADDR + 0x8C, BIT(13));
+ /* Clear AD_PERIPH Power switch domain out of reset interrupt flag */
+ setbits_le32(CMC1_BASE_ADDR + 0x70, BIT(4));
+
+ if (readl(CMC1_BASE_ADDR + 0x90) & BIT(13)) {
+ /* Clear System Reset Interrupt Flag Register of WDOG_AD */
+ setbits_le32(CMC1_BASE_ADDR + 0x90, BIT(13));
+ /* Reset WDOG to clear reset request */
+ pcc_reset_peripheral(3, WDOG3_PCC3_SLOT, true);
+ pcc_reset_peripheral(3, WDOG3_PCC3_SLOT, false);
+ }
+
/* Disable wdog */
init_wdog();
@@ -551,8 +697,9 @@ int arch_cpu_init(void)
release_rdc(RDC_TRDC);
trdc_set_access();
-
- lpav_configure();
+ lpav_configure(false);
+ } else {
+ lpav_configure(true);
}
/* Release xrdc, then allow A35 to write SRAM2 */
@@ -561,7 +708,7 @@ int arch_cpu_init(void)
xrdc_mrc_region_set_access(2, CONFIG_SPL_TEXT_BASE, 0xE00);
- clock_init();
+ clock_init_early();
} else {
/* reconfigure core0 reset vector to ROM */
set_core0_reset_vector(0x1000);
@@ -642,3 +789,37 @@ u32 spl_arch_boot_image_offset(u32 image_offset, u32 rom_bt_dev)
return image_offset;
}
+
+enum env_location env_get_location(enum env_operation op, int prio)
+{
+ enum boot_device dev = get_boot_device();
+ enum env_location env_loc = ENVL_UNKNOWN;
+
+ if (prio)
+ return env_loc;
+
+ switch (dev) {
+#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
+ case QSPI_BOOT:
+ env_loc = ENVL_SPI_FLASH;
+ break;
+#endif
+#ifdef CONFIG_ENV_IS_IN_MMC
+ case SD1_BOOT:
+ case SD2_BOOT:
+ case SD3_BOOT:
+ case MMC1_BOOT:
+ case MMC2_BOOT:
+ case MMC3_BOOT:
+ env_loc = ENVL_MMC;
+ break;
+#endif
+ default:
+#if defined(CONFIG_ENV_IS_NOWHERE)
+ env_loc = ENVL_NOWHERE;
+#endif
+ break;
+ }
+
+ return env_loc;
+}
diff --git a/arch/arm/mach-imx/mx6/Kconfig b/arch/arm/mach-imx/mx6/Kconfig
index 98df4d4e428..3d675fcd73e 100644
--- a/arch/arm/mach-imx/mx6/Kconfig
+++ b/arch/arm/mach-imx/mx6/Kconfig
@@ -354,6 +354,8 @@ config TARGET_MX6SABREAUTO
select DM_THERMAL
select SUPPORT_SPL
imply CMD_DM
+ select FSL_CAAM
+ select ARCH_MISC_INIT
config TARGET_MX6SABRESD
bool "mx6sabresd"
@@ -364,6 +366,8 @@ config TARGET_MX6SABRESD
select DM_THERMAL
select SUPPORT_SPL
imply CMD_DM
+ select FSL_CAAM
+ select ARCH_MISC_INIT
config TARGET_MX6SLEVK
bool "mx6slevk"
@@ -386,6 +390,8 @@ config TARGET_MX6SXSABRESD
select DM
select DM_THERMAL
select SUPPORT_SPL
+ select FSL_CAAM
+ select ARCH_MISC_INIT
config TARGET_MX6SXSABREAUTO
bool "mx6sxsabreauto"
@@ -404,6 +410,8 @@ config TARGET_MX6UL_9X9_EVK
select DM_THERMAL
select SUPPORT_SPL
imply CMD_DM
+ select FSL_CAAM
+ select ARCH_MISC_INIT
config TARGET_MX6UL_14X14_EVK
bool "mx6ul_14x14_evk"
@@ -413,6 +421,8 @@ config TARGET_MX6UL_14X14_EVK
select DM_THERMAL
select SUPPORT_SPL
imply CMD_DM
+ select FSL_CAAM
+ select ARCH_MISC_INIT
config TARGET_MX6UL_ENGICAM
bool "Support Engicam GEAM6UL/Is.IoT"
diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index f872bfdab31..73a637c42d6 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -108,7 +108,7 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
{
struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;
- u32 esdmisc_val, zq_val;
+ u32 esdmisc_val, zq_val, mdmisc_val;
u32 errors = 0;
u32 ldectrl[4] = {0};
u32 ddr_mr1 = 0x4;
@@ -131,6 +131,9 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
/* disable Adopt power down timer */
setbits_le32(&mmdc0->mapsr, 0x1);
+ /* Save old RALAT and WALAT values */
+ mdmisc_val = readl(&mmdc0->mdmisc);
+
debug("Starting write leveling calibration.\n");
/*
@@ -217,6 +220,9 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
writel(esdmisc_val, &mmdc0->mdref);
writel(zq_val, &mmdc0->mpzqhwctrl);
+ /* restore WALAT/RALAT */
+ writel(mdmisc_val, &mmdc0->mdmisc);
+
debug("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08x\n",
readl(&mmdc0->mpwldectrl0));
debug("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08x\n",
@@ -1520,6 +1526,11 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
/* Step 8: Write Mode Registers to Init DDR3 devices */
+ mdelay(1); /* Wait before issuing the first MRS command.
+ * Minimum wait time is (tXPR + 500us),
+ * with max tXPR value 360ns, and 500us wait required after
+ * RESET_n is de-asserted.
+ */
for (cs = 0; cs < sysinfo->ncs; cs++) {
/* MR2 */
val = (sysinfo->rtt_wr & 3) << 9 | (ddr3_cfg->SRT & 1) << 7 |
diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c
index 03d6b8c1ce9..2434bcfa987 100644
--- a/arch/arm/mach-imx/mx6/soc.c
+++ b/arch/arm/mach-imx/mx6/soc.c
@@ -4,6 +4,7 @@
* Sascha Hauer, Pengutronix
*
* (C) Copyright 2009 Freescale Semiconductor, Inc.
+ * Copyright 2021 NXP
*/
#include <common.h>
@@ -23,7 +24,6 @@
#include <asm/arch/mxc_hdmi.h>
#include <asm/arch/crm_regs.h>
#include <dm.h>
-#include <fsl_sec.h>
#include <imx_thermal.h>
#include <mmc.h>
@@ -738,9 +738,14 @@ static void setup_serial_number(void)
int arch_misc_init(void)
{
-#ifdef CONFIG_FSL_CAAM
- sec_init();
-#endif
+ 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);
+ }
setup_serial_number();
return 0;
}
diff --git a/arch/arm/mach-imx/mx7/Kconfig b/arch/arm/mach-imx/mx7/Kconfig
index 0cad825287c..4f9f51c9b05 100644
--- a/arch/arm/mach-imx/mx7/Kconfig
+++ b/arch/arm/mach-imx/mx7/Kconfig
@@ -68,6 +68,7 @@ config TARGET_MX7DSABRESD
select DM_THERMAL
select MX7D
imply CMD_DM
+ select FSL_CAAM
config TARGET_PICO_IMX7D
bool "pico-imx7d"
diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c
index f6aec5a3aa2..dc9ac31eb0f 100644
--- a/arch/arm/mach-imx/mx7/soc.c
+++ b/arch/arm/mach-imx/mx7/soc.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright 2021 NXP
*/
#include <common.h>
@@ -20,7 +21,6 @@
#include <dm.h>
#include <env.h>
#include <imx_thermal.h>
-#include <fsl_sec.h>
#include <asm/setup.h>
#include <linux/delay.h>
@@ -356,9 +356,13 @@ int arch_misc_init(void)
env_set("serial#", serial_string);
#endif
-#ifdef CONFIG_FSL_CAAM
- sec_init();
-#endif
+ 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;
}
diff --git a/arch/arm/mach-imx/mx7ulp/Kconfig b/arch/arm/mach-imx/mx7ulp/Kconfig
index 15c3ab6dae0..615d75bdd0b 100644
--- a/arch/arm/mach-imx/mx7ulp/Kconfig
+++ b/arch/arm/mach-imx/mx7ulp/Kconfig
@@ -40,6 +40,8 @@ config TARGET_MX7ULP_EVK
bool "Support mx7ulp EVK board"
select MX7ULP
select SYS_ARCH_TIMER
+ select FSL_CAAM
+ select ARCH_MISC_INIT
endchoice
diff --git a/arch/arm/mach-imx/mx7ulp/soc.c b/arch/arm/mach-imx/mx7ulp/soc.c
index bc41cbc6871..08bdc0c4af5 100644
--- a/arch/arm/mach-imx/mx7ulp/soc.c
+++ b/arch/arm/mach-imx/mx7ulp/soc.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2021 NXP
*/
#include <common.h>
@@ -16,6 +17,7 @@
#include <asm/mach-imx/sys_proto.h>
#include <asm/setup.h>
#include <linux/bitops.h>
+#include <dm.h>
#define PMC0_BASE_ADDR 0x410a1000
#define PMC0_CTRL 0x28
@@ -82,6 +84,22 @@ int arch_cpu_init(void)
return 0;
}
+#if defined(CONFIG_ARCH_MISC_INIT)
+int arch_misc_init(void)
+{
+ 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;
+}
+#endif
+
#ifdef CONFIG_BOARD_POSTCLK_INIT
int board_postclk_init(void)
{
diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c
index 039a4c73035..a4214d53768 100644
--- a/arch/arm/mach-imx/parse-container.c
+++ b/arch/arm/mach-imx/parse-container.c
@@ -142,12 +142,12 @@ static int read_auth_container(struct spl_image_info *spl_image,
return -EIO;
if (container->tag != 0x87 && container->version != 0x0) {
- printf("Wrong container header");
+ printf("Wrong container header\n");
return -ENOENT;
}
if (!container->num_images) {
- printf("Wrong container, no image found");
+ printf("Wrong container, no image found\n");
return -ENOENT;
}
diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c
index d827de375a6..c47f5a6bdb4 100644
--- a/arch/arm/mach-imx/spl_imx_romapi.c
+++ b/arch/arm/mach-imx/spl_imx_romapi.c
@@ -38,14 +38,8 @@ ulong spl_romapi_raw_seekable_read(u32 offset, u32 size, void *buf)
ulong __weak spl_romapi_get_uboot_base(u32 image_offset, u32 rom_bt_dev)
{
- u32 offset;
-
- if (((rom_bt_dev >> 16) & 0xff) == BT_DEV_TYPE_FLEXSPINOR)
- offset = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512;
- else
- offset = image_offset + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512 - 0x8000;
-
- return offset;
+ return image_offset +
+ (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512 - 0x8000);
}
static int is_boot_from_stream_device(u32 boot)