[06/37] arm: imx: basic i.MX8ULP support

Message ID 20210412121306.11484-7-peng.fan@oss.nxp.com
State New
Headers show
Series
  • imx: add i.MX8ULP support
Related show

Commit Message

Peng Fan (OSS) April 12, 2021, 12:12 p.m.
From: Peng Fan <peng.fan@nxp.com>


Add basic i.MX8ULP support

For the MMU part, Using a simple way the calculate the MMU size to avoid
default heavy calcaulation. And align address and size in the table
settings to 2MB or 4GB as much as possible. So we can reduce the 4K page
allocations in MMU table which will spends much time in create the
page table

Signed-off-by: Ye Li <ye.li@nxp.com>

Signed-off-by: Peng Fan <peng.fan@nxp.com>

---
 arch/arm/Makefile                             |   4 +-
 arch/arm/include/asm/arch-imx8ulp/clock.h     |  34 ++++
 arch/arm/include/asm/arch-imx8ulp/ddr.h       |  38 +++++
 arch/arm/include/asm/arch-imx8ulp/gpio.h      |  20 +++
 arch/arm/include/asm/arch-imx8ulp/imx-regs.h  | 131 +++++++++++++++
 .../include/asm/arch-imx8ulp/imx8ulp-pins.h   |  60 +++++++
 arch/arm/mach-imx/Makefile                    |   1 +
 arch/arm/mach-imx/imx8ulp/Makefile            |   7 +
 arch/arm/mach-imx/imx8ulp/clock.c             |  27 ++++
 arch/arm/mach-imx/imx8ulp/iomux.c             |   4 +
 arch/arm/mach-imx/imx8ulp/lowlevel_init.S     |  32 ++++
 arch/arm/mach-imx/imx8ulp/soc.c               | 151 +++++++++++++++++-
 12 files changed, 505 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-imx8ulp/clock.h
 create mode 100644 arch/arm/include/asm/arch-imx8ulp/ddr.h
 create mode 100644 arch/arm/include/asm/arch-imx8ulp/gpio.h
 create mode 100644 arch/arm/include/asm/arch-imx8ulp/imx-regs.h
 create mode 100644 arch/arm/include/asm/arch-imx8ulp/imx8ulp-pins.h
 create mode 100644 arch/arm/mach-imx/imx8ulp/Makefile
 create mode 100644 arch/arm/mach-imx/imx8ulp/clock.c
 create mode 100644 arch/arm/mach-imx/imx8ulp/iomux.c
 create mode 100644 arch/arm/mach-imx/imx8ulp/lowlevel_init.S

-- 
2.30.0

Patch

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 28b523b37c..c68e598a67 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -107,11 +107,11 @@  libs-y += arch/arm/cpu/
 libs-y += arch/arm/lib/
 
 ifeq ($(CONFIG_SPL_BUILD),y)
-ifneq (,$(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_MX35)$(filter $(SOC), mx25 mx5 mx6 mx7 mx35 imx8m imx8 imxrt))
+ifneq (,$(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_MX35)$(filter $(SOC), mx25 mx5 mx6 mx7 mx35 imx8m imx8 imx8ulp imxrt))
 libs-y += arch/arm/mach-imx/
 endif
 else
-ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx7ulp mx31 mx35 mxs imx8m imx8 imxrt vf610))
+ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx7ulp mx31 mx35 mxs imx8m imx8 imx8ulp imxrt vf610))
 libs-y += arch/arm/mach-imx/
 endif
 endif
diff --git a/arch/arm/include/asm/arch-imx8ulp/clock.h b/arch/arm/include/asm/arch-imx8ulp/clock.h
new file mode 100644
index 0000000000..e145c33f01
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8ulp/clock.h
@@ -0,0 +1,34 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ */
+
+#ifndef _ASM_ARCH_IMX8ULP_CLOCK_H
+#define _ASM_ARCH_IMX8ULP_CLOCK_H
+
+/* Mainly for compatible to imx common code. */
+enum mxc_clock {
+	MXC_ARM_CLK = 0,
+	MXC_AHB_CLK,
+	MXC_IPG_CLK,
+	MXC_UART_CLK,
+	MXC_CSPI_CLK,
+	MXC_AXI_CLK,
+	MXC_DDR_CLK,
+	MXC_ESDHC_CLK,
+	MXC_ESDHC2_CLK,
+	MXC_I2C_CLK,
+};
+
+u32 mxc_get_clock(enum mxc_clock clk);
+u32 get_lpuart_clk(void);
+#ifdef CONFIG_SYS_I2C_IMX_LPI2C
+int enable_i2c_clk(unsigned char enable, unsigned int i2c_num);
+u32 imx_get_i2cclk(unsigned int i2c_num);
+#endif
+#ifdef CONFIG_MXC_OCOTP
+void enable_ocotp_clk(unsigned char enable);
+#endif
+void init_clk_usdhc(u32 index);
+void clock_init(void);
+#endif
diff --git a/arch/arm/include/asm/arch-imx8ulp/ddr.h b/arch/arm/include/asm/arch-imx8ulp/ddr.h
new file mode 100644
index 0000000000..4544431b05
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8ulp/ddr.h
@@ -0,0 +1,38 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ */
+
+#ifndef __ASM_ARCH_IMX8ULP_DDR_H
+#define __ASM_ARCH_IMX8ULP_DDR_H
+
+#include <asm/io.h>
+#include <asm/types.h>
+
+struct dram_cfg_param {
+	unsigned int reg;
+	unsigned int val;
+};
+
+struct dram_timing_info2 {
+	/* ddr controller config */
+	struct dram_cfg_param *ctl_cfg;
+	unsigned int ctl_cfg_num;
+	/* pi config */
+	struct dram_cfg_param *pi_cfg;
+	unsigned int pi_cfg_num;
+	/* phy freq1 config */
+	struct dram_cfg_param *phy_f1_cfg;
+	unsigned int phy_f1_cfg_num;
+	/* phy freq2 config */
+	struct dram_cfg_param *phy_f2_cfg;
+	unsigned int phy_f2_cfg_num;
+	/* initialized drate table */
+	unsigned int fsp_table[3];
+};
+
+extern struct dram_timing_info2 dram_timing;
+
+int ddr_init(struct dram_timing_info2 *dram_timing);
+
+#endif
diff --git a/arch/arm/include/asm/arch-imx8ulp/gpio.h b/arch/arm/include/asm/arch-imx8ulp/gpio.h
new file mode 100644
index 0000000000..b7563bb401
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8ulp/gpio.h
@@ -0,0 +1,20 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ */
+
+#ifndef __ASM_ARCH_IMX8ULP_GPIO_H
+#define __ASM_ARCH_IMX8ULP_GPIO_H
+
+struct gpio_regs {
+	u32 gpio_pdor;
+	u32 gpio_psor;
+	u32 gpio_pcor;
+	u32 gpio_ptor;
+	u32 gpio_pdir;
+	u32 gpio_pddr;
+	u32 gpio_pidr;
+	u8 gpio_pxdr[32];
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-imx8ulp/imx-regs.h b/arch/arm/include/asm/arch-imx8ulp/imx-regs.h
new file mode 100644
index 0000000000..52831d7262
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8ulp/imx-regs.h
@@ -0,0 +1,131 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ */
+
+#ifndef _IMX8ULP_REGS_H_
+#define _IMX8ULP_REGS_H_
+#define ARCH_MXC
+
+#include <linux/sizes.h>
+
+#define PBRIDGE0_BASE		0x28000000
+
+#define CMC0_RBASE		0x28025000
+
+#define CMC1_BASE_ADDR		0x29240000
+
+#define SIM1_BASE_ADDR		0x29290000
+
+#define WDG3_RBASE		0x292a0000UL
+
+#define CGC1_SOSCDIV_ADDR	0x292C0108
+#define CGC1_FRODIV_ADDR	0x292C0208
+
+#define CFG1_PLL2CSR_ADDR	0x292C0500
+#define CFG1_PLL2CFG_ADDR	0x292C0510
+
+#define PCC_XRDC_MGR_ADDR	0x292d00bc
+
+#define PCC3_RBASE		0x292d0000
+#define PCC4_RBASE		0x29800000
+#define PCC5_RBASE		0x2da70000
+
+#define IOMUXC_BASE_ADDR	0x298c0000
+
+#define LPUART4_RBASE		0x29390000
+#define LPUART5_RBASE		0x293a0000
+#define LPUART6_RBASE		0x29860000
+#define LPUART7_RBASE		0x29870000
+
+#define LPUART_BASE		LPUART5_RBASE
+
+#define FSB_BASE_ADDR		0x27010000
+
+#define USBOTG0_RBASE		0x29900000
+#define USB_PHY0_BASE_ADDR	0x29910000
+#define USBOTG1_RBASE		0x29920000
+#define USB_PHY1_BASE_ADDR	0x29930000
+#define USB_BASE_ADDR		USBOTG0_RBASE
+
+#define DDR_CTL_BASE_ADDR	0x2E060000
+#define DDR_PI_BASE_ADDR	0x2E062000
+#define DDR_PHY_BASE_ADDR	0x2E064000
+#define AVD_SIM_LPDDR_CTRL	0x2DA50014
+#define AVD_SIM_LPDDR_CTRL2	0x2DA50018
+
+#if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__))
+#include <asm/types.h>
+
+struct usbphy_regs {
+	u32	usbphy_pwd;			/* 0x000 */
+	u32	usbphy_pwd_set;			/* 0x004 */
+	u32	usbphy_pwd_clr;			/* 0x008 */
+	u32	usbphy_pwd_tog;			/* 0x00c */
+	u32	usbphy_tx;			/* 0x010 */
+	u32	usbphy_tx_set;			/* 0x014 */
+	u32	usbphy_tx_clr;			/* 0x018 */
+	u32	usbphy_tx_tog;			/* 0x01c */
+	u32	usbphy_rx;			/* 0x020 */
+	u32	usbphy_rx_set;			/* 0x024 */
+	u32	usbphy_rx_clr;			/* 0x028 */
+	u32	usbphy_rx_tog;			/* 0x02c */
+	u32	usbphy_ctrl;			/* 0x030 */
+	u32	usbphy_ctrl_set;		/* 0x034 */
+	u32	usbphy_ctrl_clr;		/* 0x038 */
+	u32	usbphy_ctrl_tog;		/* 0x03c */
+	u32	usbphy_status;			/* 0x040 */
+	u32	reserved0[3];
+	u32	usbphy_debug;			/* 0x050 */
+	u32	usbphy_debug_set;		/* 0x054 */
+	u32	usbphy_debug_clr;		/* 0x058 */
+	u32	usbphy_debug_tog;		/* 0x05c */
+	u32	usbphy_debug0_status;	/* 0x060 */
+	u32	reserved1[3];
+	u32	usbphy_debug1;			/* 0x070 */
+	u32	usbphy_debug1_set;		/* 0x074 */
+	u32	usbphy_debug1_clr;		/* 0x078 */
+	u32	usbphy_debug1_tog;		/* 0x07c */
+	u32	usbphy_version;			/* 0x080 */
+	u32	reserved2[7];
+	u32	usb1_pll_480_ctrl;		/* 0x0a0 */
+	u32	usb1_pll_480_ctrl_set;		/* 0x0a4 */
+	u32	usb1_pll_480_ctrl_clr;		/* 0x0a8 */
+	u32	usb1_pll_480_ctrl_tog;		/* 0x0ac */
+	u32	reserved3[4];
+	u32	usb1_vbus_detect;		/* 0xc0 */
+	u32	usb1_vbus_detect_set;		/* 0xc4 */
+	u32	usb1_vbus_detect_clr;		/* 0xc8 */
+	u32	usb1_vbus_detect_tog;		/* 0xcc */
+	u32	usb1_vbus_det_stat;		/* 0xd0 */
+	u32	reserved4[3];
+	u32	usb1_chrg_detect;		/* 0xe0 */
+	u32	usb1_chrg_detect_set;		/* 0xe4 */
+	u32	usb1_chrg_detect_clr;		/* 0xe8 */
+	u32	usb1_chrg_detect_tog;		/* 0xec */
+	u32	usb1_chrg_det_stat;		/* 0xf0 */
+	u32	reserved5[3];
+	u32	usbphy_anactrl;			/* 0x100 */
+	u32	usbphy_anactrl_set;		/* 0x104 */
+	u32	usbphy_anactrl_clr;		/* 0x108 */
+	u32	usbphy_anactrl_tog;		/* 0x10c */
+	u32	usb1_loopback;			/* 0x110 */
+	u32	usb1_loopback_set;		/* 0x114 */
+	u32	usb1_loopback_clr;		/* 0x118 */
+	u32	usb1_loopback_tog;		/* 0x11c */
+	u32	usb1_loopback_hsfscnt;		/* 0x120 */
+	u32	usb1_loopback_hsfscnt_set;	/* 0x124 */
+	u32	usb1_loopback_hsfscnt_clr;	/* 0x128 */
+	u32	usb1_loopback_hsfscnt_tog;	/* 0x12c */
+	u32	usphy_trim_override_en;		/* 0x130 */
+	u32	usphy_trim_override_en_set;	/* 0x134 */
+	u32	usphy_trim_override_en_clr;	/* 0x138 */
+	u32	usphy_trim_override_en_tog;	/* 0x13c */
+	u32	usb1_pfda_ctrl1;		/* 0x140 */
+	u32	usb1_pfda_ctrl1_set;		/* 0x144 */
+	u32	usb1_pfda_ctrl1_clr;		/* 0x148 */
+	u32	usb1_pfda_ctrl1_tog;		/* 0x14c */
+};
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/arch-imx8ulp/imx8ulp-pins.h b/arch/arm/include/asm/arch-imx8ulp/imx8ulp-pins.h
new file mode 100644
index 0000000000..d7c07f41b3
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8ulp/imx8ulp-pins.h
@@ -0,0 +1,60 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 NXP
+ */
+
+#ifndef __ASM_ARCH_IMX8ULP_PINS_H__
+#define __ASM_ARCH_IMX8ULP_PINS_H__
+
+#include <asm/arch/iomux.h>
+
+enum {
+	IMX8ULP_PAD_PTB7__PMIC0_MODE2                       = IOMUX_PAD(0x009C, 0x009C, IOMUX_CONFIG_MPORTS | 0xA, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTB8__PMIC0_MODE1                       = IOMUX_PAD(0x00A0, 0x00A0, IOMUX_CONFIG_MPORTS | 0xA, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTB9__PMIC0_MODE0                       = IOMUX_PAD(0x00A4, 0x00A4, IOMUX_CONFIG_MPORTS | 0xA, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTB10__PMIC0_SDA                        = IOMUX_PAD(0x00A8, 0x00A8, IOMUX_CONFIG_MPORTS | 0xA, 0x0804, 0x2, 0),
+	IMX8ULP_PAD_PTB11__PMIC0_SCL                        = IOMUX_PAD(0x00AC, 0x00AC, IOMUX_CONFIG_MPORTS | 0xA, 0x0800, 0x2, 0),
+
+	IMX8ULP_PAD_PTD0__SDHC0_RESET_b                     = IOMUX_PAD(0x0000, 0x0000, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD1__SDHC0_CMD                         = IOMUX_PAD(0x0004, 0x0004, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD2__SDHC0_CLK                         = IOMUX_PAD(0x0008, 0x0008, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD3__SDHC0_D7                          = IOMUX_PAD(0x000C, 0x000C, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD4__SDHC0_D6                          = IOMUX_PAD(0x0010, 0x0010, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD5__SDHC0_D5                          = IOMUX_PAD(0x0014, 0x0014, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD6__SDHC0_D4                          = IOMUX_PAD(0x0018, 0x0018, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD7__SDHC0_D3                          = IOMUX_PAD(0x001C, 0x001C, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD8__SDHC0_D2                          = IOMUX_PAD(0x0020, 0x0020, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD9__SDHC0_D1                          = IOMUX_PAD(0x0024, 0x0024, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD10__SDHC0_D0                         = IOMUX_PAD(0x0028, 0x0028, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD11__SDHC0_DQS                        = IOMUX_PAD(0x002C, 0x002C, 0x8, 0x0000, 0x0, 0),
+
+	IMX8ULP_PAD_PTD11__FLEXSPI2_B_SS0_B                 = IOMUX_PAD(0x002C, 0x002C, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD11__FLEXSPI2_A_SS1_B                 = IOMUX_PAD(0x002C, 0x002C, 0xa, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD12__FLEXSPI2_A_SS0_B                 = IOMUX_PAD(0x0030, 0x0030, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD12__FLEXSPI2_B_SS1_B                 = IOMUX_PAD(0x0030, 0x0030, 0xa, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD13__FLEXSPI2_A_SCLK                  = IOMUX_PAD(0x0034, 0x0034, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD14__FLEXSPI2_A_DATA3                 = IOMUX_PAD(0x0038, 0x0038, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD15__FLEXSPI2_A_DATA2                 = IOMUX_PAD(0x003c, 0x003c, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD16__FLEXSPI2_A_DATA1                 = IOMUX_PAD(0x0040, 0x0040, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD17__FLEXSPI2_A_DATA0                 = IOMUX_PAD(0x0044, 0x0044, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD18__FLEXSPI2_A_DQS                   = IOMUX_PAD(0x0048, 0x0048, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD19__FLEXSPI2_A_DATA7                 = IOMUX_PAD(0x004c, 0x004c, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD20__FLEXSPI2_A_DATA6                 = IOMUX_PAD(0x0050, 0x0050, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD21__FLEXSPI2_A_DATA5                 = IOMUX_PAD(0x0054, 0x0054, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD22__FLEXSPI2_A_DATA4                 = IOMUX_PAD(0x0058, 0x0058, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD23__FLEXSPI2_A_SS0_B                 = IOMUX_PAD(0x005c, 0x005c, 0x9, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTD23__FLEXSPI2_A_SCLK                  = IOMUX_PAD(0x005c, 0x005c, 0xa, 0x0000, 0x0, 0),
+
+	IMX8ULP_PAD_PTE19__ENET0_REFCLK                     = IOMUX_PAD(0x00CC, 0x00CC, 0xA, 0x0AF4, 0x1, 0),
+	IMX8ULP_PAD_PTF10__ENET0_1588_CLKIN                 = IOMUX_PAD(0x0128, 0x0128, 0x9, 0x0AD0, 0x2, 0),
+
+	IMX8ULP_PAD_PTF11__SDHC1_RESET_b                    = IOMUX_PAD(0x012C, 0x012C, 0x8, 0x0000, 0x0, 0),
+	IMX8ULP_PAD_PTF3__SDHC1_CMD                         = IOMUX_PAD(0x010C, 0x010C, 0x8, 0x0A60, 0x2, 0),
+	IMX8ULP_PAD_PTF2__SDHC1_CLK                         = IOMUX_PAD(0x0108, 0x0108, 0x8, 0x0A5C, 0x2, 0),
+	IMX8ULP_PAD_PTF4__SDHC1_D3                          = IOMUX_PAD(0x0110, 0x0110, 0x8, 0x0A70, 0x2, 0),
+	IMX8ULP_PAD_PTF5__SDHC1_D2                          = IOMUX_PAD(0x0114, 0x0114, 0x8, 0x0A6C, 0x2, 0),
+	IMX8ULP_PAD_PTF0__SDHC1_D1                          = IOMUX_PAD(0x0100, 0x0100, 0x8, 0x0A68, 0x2, 0),
+	IMX8ULP_PAD_PTF1__SDHC1_D0                          = IOMUX_PAD(0x0104, 0x0104, 0x8, 0x0A64, 0x2, 0),
+
+};
+#endif  /* __ASM_ARCH_IMX8ULP_PINS_H__ */
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 82aa39dee7..36224d8db9 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -227,6 +227,7 @@  obj-$(CONFIG_MX5) += mx5/
 obj-$(CONFIG_MX6) += mx6/
 obj-$(CONFIG_MX7) += mx7/
 obj-$(CONFIG_ARCH_MX7ULP) += mx7ulp/
+obj-$(CONFIG_ARCH_IMX8ULP) += imx8ulp/
 obj-$(CONFIG_IMX8M) += imx8m/
 obj-$(CONFIG_ARCH_IMX8) += imx8/
 obj-$(CONFIG_ARCH_IMXRT) += imxrt/
diff --git a/arch/arm/mach-imx/imx8ulp/Makefile b/arch/arm/mach-imx/imx8ulp/Makefile
new file mode 100644
index 0000000000..e8970dc04f
--- /dev/null
+++ b/arch/arm/mach-imx/imx8ulp/Makefile
@@ -0,0 +1,7 @@ 
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2020 NXP
+#
+
+obj-y += lowlevel_init.o
+obj-y += soc.o clock.o iomux.o
diff --git a/arch/arm/mach-imx/imx8ulp/clock.c b/arch/arm/mach-imx/imx8ulp/clock.c
new file mode 100644
index 0000000000..f866809fc2
--- /dev/null
+++ b/arch/arm/mach-imx/imx8ulp/clock.c
@@ -0,0 +1,27 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void clock_init(void)
+{
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+	return 0;
+}
+
+u32 get_lpuart_clk(void)
+{
+	return 24000000;
+}
diff --git a/arch/arm/mach-imx/imx8ulp/iomux.c b/arch/arm/mach-imx/imx8ulp/iomux.c
new file mode 100644
index 0000000000..c52ccdeaea
--- /dev/null
+++ b/arch/arm/mach-imx/imx8ulp/iomux.c
@@ -0,0 +1,4 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
diff --git a/arch/arm/mach-imx/imx8ulp/lowlevel_init.S b/arch/arm/mach-imx/imx8ulp/lowlevel_init.S
new file mode 100644
index 0000000000..7d81a75639
--- /dev/null
+++ b/arch/arm/mach-imx/imx8ulp/lowlevel_init.S
@@ -0,0 +1,32 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ */
+
+#include <config.h>
+
+.align 8
+.global rom_pointer
+rom_pointer:
+	.space 256
+
+/*
+ * Routine: save_boot_params (called after reset from start.S)
+ */
+
+.global save_boot_params
+save_boot_params:
+	/* The firmware provided ATAG/FDT address can be found in r2/x0 */
+	adr	x0, rom_pointer
+	stp	x1, x2, [x0], #16
+	stp	x3, x4, [x0], #16
+
+	/* Returns */
+	b	save_boot_params_ret
+
+.global restore_boot_params
+restore_boot_params:
+	adr	x0, rom_pointer
+	ldp	x1, x2, [x0], #16
+	ldp	x3, x4, [x0], #16
+	ret
diff --git a/arch/arm/mach-imx/imx8ulp/soc.c b/arch/arm/mach-imx/imx8ulp/soc.c
index 383dbe6000..92998e9146 100644
--- a/arch/arm/mach-imx/imx8ulp/soc.c
+++ b/arch/arm/mach-imx/imx8ulp/soc.c
@@ -7,8 +7,11 @@ 
 #include <asm/arch/clock.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/armv8/mmu.h>
 #include <asm/mach-imx/boot_mode.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 u32 get_cpu_rev(void)
 {
 	return (MXC_CPU_IMX8ULP << 12) | CHIP_REV_1_0;
@@ -52,8 +55,8 @@  static u32 reset_cause = -1;
 static char *get_reset_cause(char *ret)
 {
 	u32 cause1, cause = 0, srs = 0;
-	void __iomem *reg_ssrs = (void __iomem *)(SRC_BASE_ADDR + 0x88);
-	void __iomem *reg_srs = (void __iomem *)(SRC_BASE_ADDR + 0x80);
+	void __iomem *reg_ssrs = (void __iomem *)(CMC1_BASE_ADDR + 0x88);
+	void __iomem *reg_srs = (void __iomem *)(CMC1_BASE_ADDR + 0x80);
 
 	if (!ret)
 		return "null";
@@ -137,3 +140,147 @@  int print_cpuinfo(void)
 }
 #endif
 
+void init_wdog(void)
+{
+	/* TODO */
+}
+
+void s_init(void)
+{
+	/* Disable wdog */
+	init_wdog();
+}
+
+static struct mm_region imx8ulp_arm64_mem_map[] = {
+	{
+		/* ROM */
+		.virt = 0x0,
+		.phys = 0x0,
+		.size = 0x40000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_OUTER_SHARE
+	},
+	{
+		/* SSRAM (align with 2M) */
+		.virt = 0x1FE00000UL,
+		.phys = 0x1FE00000UL,
+		.size = 0x400000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_OUTER_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* SRAM1 (align with 2M) */
+		.virt = 0x21000000UL,
+		.phys = 0x21000000UL,
+		.size = 0x200000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_OUTER_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* SRAM0 (align with 2M) */
+		.virt = 0x22000000UL,
+		.phys = 0x22000000UL,
+		.size = 0x200000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_OUTER_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* Peripherals */
+		.virt = 0x27000000UL,
+		.phys = 0x27000000UL,
+		.size = 0x3000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* Peripherals */
+		.virt = 0x2D000000UL,
+		.phys = 0x2D000000UL,
+		.size = 0x1600000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* FLEXSPI1-2 */
+		.virt = 0x40000000UL,
+		.phys = 0x40000000UL,
+		.size = 0x40000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* DRAM1 */
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
+		.size = PHYS_SDRAM_SIZE,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_OUTER_SHARE
+	}, {
+		/*
+		 * empty entrie to split table entry 5
+		 * if needed when TEEs are used
+		 */
+		0,
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = imx8ulp_arm64_mem_map;
+
+/* simplify the page table size to enhance boot speed */
+#define MAX_PTE_ENTRIES		512
+#define MAX_MEM_MAP_REGIONS	16
+u64 get_page_table_size(void)
+{
+	u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
+	u64 size = 0;
+
+	/*
+	 * For each memory region, the max table size:
+	 * 2 level 3 tables + 2 level 2 tables + 1 level 1 table
+	 */
+	size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
+
+	/*
+	 * We need to duplicate our page table once to have an emergency pt to
+	 * resort to when splitting page tables later on
+	 */
+	size *= 2;
+
+	/*
+	 * We may need to split page tables later on if dcache settings change,
+	 * so reserve up to 4 (random pick) page tables for that.
+	 */
+	size += one_pt * 4;
+
+	return size;
+}
+
+void enable_caches(void)
+{
+	/* TODO: add TEE memmap region */
+
+	icache_enable();
+	dcache_enable();
+}
+
+int dram_init(void)
+{
+	gd->ram_size = PHYS_SDRAM_SIZE;
+
+	return 0;
+}
+
+#ifdef CONFIG_SERIAL_TAG
+void get_board_serial(struct tag_serialnr *serialnr)
+{
+	/* TODO */
+}
+#endif
+
+int arch_cpu_init(void)
+{
+	return 0;
+}