diff mbox series

[U-Boot,v2,2/2] board: Add support for iMXQXP AI_ML board

Message ID 20190711180726.27200-3-manivannan.sadhasivam@linaro.org
State Superseded
Delegated to: Stefano Babic
Headers show
Series Add board support for iMX8QXP AI_ML board | expand

Commit Message

Manivannan Sadhasivam July 11, 2019, 6:07 p.m. UTC
This commit adds initial board support for iMXQXP AI_ML board from
Einfochips. This board is one of the 96Boards Consumer Edition and AI boards
of the 96Boards family based on i.MXQXP SoC from NXP/Freescale.

This initial supports contains following peripherals which are tested and
known to work:

1. Debug serial via UART2
2. SD card
3. Ethernet

More information about this board can be found in arrow website:
https://www.arrow.com/en/products/imx8-ai-ml/arrow-development-tools

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
 arch/arm/mach-imx/imx8/Kconfig                |   6 +
 board/einfochips/imx8qxp_ai_ml/Kconfig        |  12 ++
 board/einfochips/imx8qxp_ai_ml/MAINTAINERS    |   6 +
 board/einfochips/imx8qxp_ai_ml/Makefile       |   8 +
 board/einfochips/imx8qxp_ai_ml/README         |  49 ++++++
 .../einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c  | 128 ++++++++++++++
 board/einfochips/imx8qxp_ai_ml/imximage.cfg   |  24 +++
 board/einfochips/imx8qxp_ai_ml/spl.c          |  59 +++++++
 configs/imx8qxp_ai_ml_defconfig               |  83 +++++++++
 include/configs/imx8qxp_ai_ml.h               | 157 ++++++++++++++++++
 10 files changed, 532 insertions(+)
 create mode 100644 board/einfochips/imx8qxp_ai_ml/Kconfig
 create mode 100644 board/einfochips/imx8qxp_ai_ml/MAINTAINERS
 create mode 100644 board/einfochips/imx8qxp_ai_ml/Makefile
 create mode 100644 board/einfochips/imx8qxp_ai_ml/README
 create mode 100644 board/einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c
 create mode 100644 board/einfochips/imx8qxp_ai_ml/imximage.cfg
 create mode 100644 board/einfochips/imx8qxp_ai_ml/spl.c
 create mode 100644 configs/imx8qxp_ai_ml_defconfig
 create mode 100644 include/configs/imx8qxp_ai_ml.h

Comments

Peng Fan July 12, 2019, 3:41 a.m. UTC | #1
> Subject: [PATCH v2 2/2] board: Add support for iMXQXP AI_ML board
> 
> This commit adds initial board support for iMXQXP AI_ML board from
> Einfochips. This board is one of the 96Boards Consumer Edition and AI boards
> of the 96Boards family based on i.MXQXP SoC from NXP/Freescale.
> 
> This initial supports contains following peripherals which are tested and
> known to work:
> 
> 1. Debug serial via UART2
> 2. SD card
> 3. Ethernet
> 
> More information about this board can be found in arrow website:
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.
> arrow.com%2Fen%2Fproducts%2Fimx8-ai-ml%2Farrow-development-tools&
> amp;data=02%7C01%7Cpeng.fan%40nxp.com%7C87fef8ef84bf4c6190db08d
> 7062ab4f8%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636984
> 652801075517&amp;sdata=gbYa%2Fq8ZXQcId8IUtQIy0dB6axc0H%2FlqBRGY
> yamrap0%3D&amp;reserved=0
> 
> Signed-off-by: Manivannan Sadhasivam
> <manivannan.sadhasivam@linaro.org>
> ---
>  arch/arm/mach-imx/imx8/Kconfig                |   6 +
>  board/einfochips/imx8qxp_ai_ml/Kconfig        |  12 ++
>  board/einfochips/imx8qxp_ai_ml/MAINTAINERS    |   6 +
>  board/einfochips/imx8qxp_ai_ml/Makefile       |   8 +
>  board/einfochips/imx8qxp_ai_ml/README         |  49 ++++++
>  .../einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c  | 128 ++++++++++++++
>  board/einfochips/imx8qxp_ai_ml/imximage.cfg   |  24 +++
>  board/einfochips/imx8qxp_ai_ml/spl.c          |  59 +++++++
>  configs/imx8qxp_ai_ml_defconfig               |  83 +++++++++
>  include/configs/imx8qxp_ai_ml.h               | 157
> ++++++++++++++++++
>  10 files changed, 532 insertions(+)
>  create mode 100644 board/einfochips/imx8qxp_ai_ml/Kconfig
>  create mode 100644 board/einfochips/imx8qxp_ai_ml/MAINTAINERS
>  create mode 100644 board/einfochips/imx8qxp_ai_ml/Makefile
>  create mode 100644 board/einfochips/imx8qxp_ai_ml/README
>  create mode 100644 board/einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c
>  create mode 100644 board/einfochips/imx8qxp_ai_ml/imximage.cfg
>  create mode 100644 board/einfochips/imx8qxp_ai_ml/spl.c
>  create mode 100644 configs/imx8qxp_ai_ml_defconfig  create mode
> 100644 include/configs/imx8qxp_ai_ml.h
> 
> diff --git a/arch/arm/mach-imx/imx8/Kconfig
> b/arch/arm/mach-imx/imx8/Kconfig index bbe323d5ca..cec21f8dd2 100644
> --- a/arch/arm/mach-imx/imx8/Kconfig
> +++ b/arch/arm/mach-imx/imx8/Kconfig
> @@ -37,6 +37,11 @@ config TARGET_COLIBRI_IMX8X
>  	select BOARD_LATE_INIT
>  	select IMX8QXP
> 
> +config TARGET_IMX8QXP_AI_ML
> +	bool "Support i.MX8QXP AI_ML board"
> +	select BOARD_LATE_INIT
> +	select IMX8QXP
> +
>  config TARGET_IMX8QM_MEK
>  	bool "Support i.MX8QM MEK board"
>  	select BOARD_LATE_INIT
> @@ -49,6 +54,7 @@ config TARGET_IMX8QXP_MEK
> 
>  endchoice
> 
> +source "board/einfochips/imx8qxp_ai_ml/Kconfig"
>  source "board/freescale/imx8qm_mek/Kconfig"
>  source "board/freescale/imx8qxp_mek/Kconfig"
>  source "board/toradex/apalis-imx8/Kconfig"
> diff --git a/board/einfochips/imx8qxp_ai_ml/Kconfig
> b/board/einfochips/imx8qxp_ai_ml/Kconfig
> new file mode 100644
> index 0000000000..697a831013
> --- /dev/null
> +++ b/board/einfochips/imx8qxp_ai_ml/Kconfig
> @@ -0,0 +1,12 @@
> +if TARGET_IMX8QXP_AI_ML
> +
> +config SYS_BOARD
> +	default "imx8qxp_ai_ml"
> +
> +config SYS_VENDOR
> +	default "einfochips"
> +
> +config SYS_CONFIG_NAME
> +	default "imx8qxp_ai_ml"
> +
> +endif
> diff --git a/board/einfochips/imx8qxp_ai_ml/MAINTAINERS
> b/board/einfochips/imx8qxp_ai_ml/MAINTAINERS
> new file mode 100644
> index 0000000000..add0bd9431
> --- /dev/null
> +++ b/board/einfochips/imx8qxp_ai_ml/MAINTAINERS
> @@ -0,0 +1,6 @@
> +i.MX8QXP AI_ML BOARD
> +M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> +S:	Maintained
> +F:	board/einfochips/imx8qxp_ai_ml/
> +F:	include/configs/imx8qxp_ai_ml.h
> +F:	configs/imx8qxp_ai_ml_defconfig
> diff --git a/board/einfochips/imx8qxp_ai_ml/Makefile
> b/board/einfochips/imx8qxp_ai_ml/Makefile
> new file mode 100644
> index 0000000000..e08774dc6e
> --- /dev/null
> +++ b/board/einfochips/imx8qxp_ai_ml/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# Copyright 2019 Linaro Ltd.
> +#
> +# SPDX-License-Identifier:	GPL-2.0+
> +#
> +
> +obj-y += imx8qxp_ai_ml.o
> +obj-$(CONFIG_SPL_BUILD) += spl.o
> diff --git a/board/einfochips/imx8qxp_ai_ml/README
> b/board/einfochips/imx8qxp_ai_ml/README
> new file mode 100644
> index 0000000000..416a157ea8
> --- /dev/null
> +++ b/board/einfochips/imx8qxp_ai_ml/README
> @@ -0,0 +1,49 @@
> +U-Boot for the Einfochips i.MX8QXP AI_ML board
> +
> +Quick Start
> +===========
> +
> +- Build the ARM Trusted firmware binary
> +- Get scfw_tcm.bin and ahab-container.img
> +- Build U-Boot
> +- Flash the binary into the SD card
> +- Boot
> +
> +Get and Build the ARM Trusted firmware
> +======================================
> +
> +$ git clone
> +https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsourc
> +e.codeaurora.org%2Fexternal%2Fimx%2Fimx-atf&amp;data=02%7C01%7Cp
> eng.fan
> +%40nxp.com%7C87fef8ef84bf4c6190db08d7062ab4f8%7C686ea1d3bc2b4c
> 6fa92cd99
> +c5c301635%7C0%7C0%7C636984652801085512&amp;sdata=IuadiSiFUDJpf
> mZIQ1kagm
> +BaW%2B5r%2F5DrJhxJv5n2mZQ%3D&amp;reserved=0
> +$ cd imx-atf/
> +$ git checkout origin/imx_4.9.88_imx8qxp_beta2 -b
> +imx_4.9.88_imx8qxp_beta2 $ make PLAT=imx8qxp bl31
> +
> +Get scfw_tcm.bin and ahab-container.img
> +=======================================
> +
> +$ wget
> +https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fraw.g
> +ithubusercontent.com%2F96boards-ai-ml%2Fbinaries%2Fmaster%2Fmx8qx-
> aiml-
> +scfw-tcm.bin&amp;data=02%7C01%7Cpeng.fan%40nxp.com%7C87fef8ef84
> bf4c6190
> +db08d7062ab4f8%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C
> 63698465280
> +1085512&amp;sdata=HgSphYhcxj%2FpIUhZtmWYpJuUNBspjawb6BlGxX1QI
> qk%3D&amp;
> +reserved=0 $ wget
> +https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww
> .n
> +xp.com%2Flgfiles%2FNMG%2FMAD%2FYOCTO%2Ffirmware-imx-8.1.bin&a
> mp;data=02
> +%7C01%7Cpeng.fan%40nxp.com%7C87fef8ef84bf4c6190db08d7062ab4f8%
> 7C686ea1d
> +3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636984652801085512&amp;s
> data=9MsmaZ
> +ijpYiZdeFP%2FiQ4Zusnw80jzr2jPpfuD3P5G9I%3D&amp;reserved=0
> +$ chmod +x firmware-imx-8.1.bin
> +$ ./firmware-imx-8.1.bin
> +
> +Copy the following binaries to U-Boot folder:
> +
> +$ cp imx-atf/build/imx8qxp/release/bl31.bin .
> +$ cp firmware-imx-8.1/firmware/seco/mx8qx-ahab-container.img .
> +
> +Build U-Boot
> +============
> +
> +$ make imx8qxp_ai_ml_defconfig
> +$ make u-boot-dtb.imx
> +
> +Flash the binary into the SD card
> +=================================
> +
> +Burn the u-boot-dtb.imx binary to SD card offset 32KB:
> +
> +$ sudo dd if=u-boot-dtb.imx of=/dev/sd[x] bs=1024 seek=32
> +
> +Boot
> +====
> +
> +Set Boot switch SW2: 1100.
> diff --git a/board/einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c
> b/board/einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c
> new file mode 100644
> index 0000000000..d568b16ad9
> --- /dev/null
> +++ b/board/einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c
> @@ -0,0 +1,128 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2018 NXP
> + * Copyright 2019 Linaro Ltd.
> + */
> +
> +#include <common.h>
> +#include <errno.h>
> +#include <linux/libfdt.h>
> +#include <environment.h>
> +#include <fsl_esdhc.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/sci/sci.h>
> +#include <asm/arch/imx8-pins.h>
> +#include <asm/arch/iomux.h>
> +#include <asm/arch/sys_proto.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define UART_PAD_CTRL	((SC_PAD_CONFIG_OUT_IN <<
> PADRING_CONFIG_SHIFT) | \
> +			 (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
> +			 (SC_PAD_28FDSOI_DSE_DV_HIGH << PADRING_DSE_SHIFT) |
> \
> +			 (SC_PAD_28FDSOI_PS_PU << PADRING_PULL_SHIFT))
> +
> +static iomux_cfg_t uart2_pads[] = {
> +	SC_P_UART2_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
> +	SC_P_UART2_TX | MUX_PAD_CTRL(UART_PAD_CTRL), };
> +
> +static void setup_iomux_uart(void)
> +{
> +	imx8_iomux_setup_multiple_pads(uart2_pads,
> ARRAY_SIZE(uart2_pads)); }
> +
> +int board_early_init_f(void)
> +{
> +	sc_pm_clock_rate_t rate = SC_80MHZ;
> +	int ret;
> +
> +	/* Set UART2 clock root to 80 MHz */
> +	ret = sc_pm_setup_uart(SC_R_UART_2, rate);
> +	if (ret)
> +		return ret;
> +
> +	setup_iomux_uart();
> +
> +	return 0;
> +}
> +
> +#if IS_ENABLED(CONFIG_DM_GPIO)
> +static void board_gpio_init(void)
> +{
> +	/* TODO */
> +}
> +#else
> +static inline void board_gpio_init(void) {} #endif
> +
> +#if IS_ENABLED(CONFIG_FEC_MXC)
> +#include <miiphy.h>
> +
> +int board_phy_config(struct phy_device *phydev) {
> +	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
> +	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x8);
> +
> +	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
> +	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
> +
> +	if (phydev->drv->config)
> +		phydev->drv->config(phydev);
> +
> +	return 0;
> +}
> +#endif
> +
> +int checkboard(void)
> +{
> +	puts("Board: iMX8QXP AI_ML\n");
> +
> +	build_info();
> +	print_bootinfo();
> +
> +	return 0;
> +}
> +
> +int board_init(void)
> +{
> +	board_gpio_init();
> +
> +	return 0;
> +}
> +
> +void detail_board_ddr_info(void)
> +{
> +	puts("\nDDR    ");
> +}
> +
> +/*
> + * Board specific reset that is system reset.
> + */
> +void reset_cpu(ulong addr)
> +{
> +	/* TODO */
> +}
> +
> +#ifdef CONFIG_OF_BOARD_SETUP
> +int ft_board_setup(void *blob, bd_t *bd) {
> +	return 0;
> +}
> +#endif
> +
> +int board_mmc_get_env_dev(int devno)
> +{
> +	return devno;
> +}
> +
> +int board_late_init(void)
> +{
> +#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
> +	env_set("board_name", "AI_ML");
> +	env_set("board_rev", "v1.0");
> +#endif
> +
> +	return 0;
> +}
> diff --git a/board/einfochips/imx8qxp_ai_ml/imximage.cfg
> b/board/einfochips/imx8qxp_ai_ml/imximage.cfg
> new file mode 100644
> index 0000000000..4fc5ade313
> --- /dev/null
> +++ b/board/einfochips/imx8qxp_ai_ml/imximage.cfg
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2018 NXP
> + *
> + * Refer doc/README.imx8image for more details about how-to configure
> + * and create imx8image boot image
> + */
> +
> +#define __ASSEMBLY__
> +
> +/* Boot from SD, sector size 0x400 */
> +BOOT_FROM SD 0x400
> +/* SoC type IMX8QX */
> +SOC_TYPE IMX8QX
> +/* Append seco container image */
> +APPEND mx8qx-ahab-container.img
> +/* Create the 2nd container */
> +CONTAINER
> +/* Add scfw image with exec attribute */ IMAGE SCU
> +mx8qx-aiml-scfw-tcm.bin
> +/* Add ATF image with exec attribute */ IMAGE A35 bl31.bin 0x80000000
> +/* Add U-Boot image with load attribute */ DATA A35 u-boot-dtb.bin
> +0x80020000
> diff --git a/board/einfochips/imx8qxp_ai_ml/spl.c
> b/board/einfochips/imx8qxp_ai_ml/spl.c
> new file mode 100644
> index 0000000000..cb4006eb2a
> --- /dev/null
> +++ b/board/einfochips/imx8qxp_ai_ml/spl.c
> @@ -0,0 +1,59 @@
> +/*
> + * Copyright 2018 NXP
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <spl.h>
> +#include <dm/uclass.h>
> +#include <dm/device.h>
> +#include <dm/uclass-internal.h>
> +#include <dm/device-internal.h>
> +#include <dm/lists.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +void spl_board_init(void)
> +{
> +	struct udevice *dev;
> +
> +	uclass_find_first_device(UCLASS_MISC, &dev);
> +
> +	for (; dev; uclass_find_next_device(&dev)) {
> +		if (device_probe(dev))
> +			continue;
> +	}
> +
> +	arch_cpu_init();
> +
> +	board_early_init_f();
> +
> +	timer_init();
> +
> +	preloader_console_init();
> +
> +	puts("Normal Boot\n");
> +}
> +
> +#ifdef CONFIG_SPL_LOAD_FIT
> +int board_fit_config_name_match(const char *name) {
> +	/* Just empty function now - can't decide what to choose */
> +	debug("%s: %s\n", __func__, name);
> +
> +	return 0;
> +}
> +#endif
> +
> +void board_init_f(ulong dummy)
> +{
> +	/* Clear global data */
> +	memset((void *)gd, 0, sizeof(gd_t));
> +
> +	/* Clear the BSS. */
> +	memset(__bss_start, 0, __bss_end - __bss_start);
> +
> +	board_init_r(NULL, 0);
> +}
> diff --git a/configs/imx8qxp_ai_ml_defconfig
> b/configs/imx8qxp_ai_ml_defconfig new file mode 100644 index
> 0000000000..3d2d26ea70
> --- /dev/null
> +++ b/configs/imx8qxp_ai_ml_defconfig
> @@ -0,0 +1,83 @@
> +CONFIG_ARM=y
> +CONFIG_SPL_SYS_ICACHE_OFF=y
> +CONFIG_SPL_SYS_DCACHE_OFF=y
> +CONFIG_ARCH_IMX8=y
> +CONFIG_SYS_TEXT_BASE=0x80020000
> +CONFIG_SPL_GPIO_SUPPORT=y
> +CONFIG_SPL_LIBCOMMON_SUPPORT=y
> +CONFIG_SPL_LIBGENERIC_SUPPORT=y
> +CONFIG_SYS_MALLOC_F_LEN=0x4000
> +CONFIG_TARGET_IMX8QXP_AI_ML=y
> +CONFIG_SPL_MMC_SUPPORT=y
> +CONFIG_SPL_SERIAL_SUPPORT=y
> +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
> +CONFIG_NR_DRAM_BANKS=4
> +CONFIG_SPL=y
> +CONFIG_FIT=y
> +CONFIG_SPL_LOAD_FIT=y
> +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh"
> +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/einfochips/imx8qxp_a
> i_ml/imximage.cfg"
> +CONFIG_BOOTDELAY=3
> +CONFIG_LOG=y
> +CONFIG_SPL_BOARD_INIT=y
> +CONFIG_SPL_SYS_MALLOC_SIMPLE=y
> +CONFIG_SPL_SEPARATE_BSS=y
> +CONFIG_SPL_POWER_SUPPORT=y
> +CONFIG_SPL_POWER_DOMAIN=y
> +CONFIG_SPL_WATCHDOG_SUPPORT=y
> +CONFIG_HUSH_PARSER=y
> +CONFIG_CMD_CPU=y
> +# CONFIG_CMD_IMPORTENV is not set
> +CONFIG_CMD_CLK=y
> +CONFIG_CMD_DM=y
> +CONFIG_CMD_FUSE=y
> +CONFIG_CMD_GPIO=y
> +CONFIG_CMD_GPT=y
> +CONFIG_CMD_I2C=y
> +CONFIG_CMD_MMC=y
> +CONFIG_CMD_DHCP=y
> +CONFIG_CMD_MII=y
> +CONFIG_CMD_PING=y
> +CONFIG_CMD_CACHE=y
> +CONFIG_CMD_EXT4=y
> +CONFIG_CMD_EXT4_WRITE=y
> +CONFIG_CMD_FAT=y
> +CONFIG_FAT_WRITE=y
> +CONFIG_CMD_FS_GENERIC=y
> +CONFIG_SPL_OF_CONTROL=y
> +CONFIG_DEFAULT_DEVICE_TREE="fsl-imx8qxp-ai_ml"
> +CONFIG_ENV_IS_IN_MMC=y
> +CONFIG_SPL_DM=y
> +CONFIG_SPL_CLK=y
> +CONFIG_CLK_IMX8=y
> +CONFIG_CPU=y
> +CONFIG_DM_GPIO=y
> +CONFIG_MXC_GPIO=y
> +CONFIG_DM_I2C=y
> +CONFIG_SYS_I2C_IMX_LPI2C=y
> +CONFIG_MISC=y
> +CONFIG_DM_MMC=y
> +CONFIG_PHYLIB=y
> +CONFIG_PHY_ADDR_ENABLE=y
> +CONFIG_PHY_ATHEROS=y
> +CONFIG_DM_ETH=y
> +CONFIG_NET_RANDOM_ETHADDR=y
> +CONFIG_PHY_GIGE=y
> +CONFIG_FEC_MXC_SHARE_MDIO=y
> +CONFIG_FEC_MXC_MDIO_BASE=0x5B040000
> +CONFIG_FEC_MXC=y
> +CONFIG_MII=y
> +CONFIG_PINCTRL=y
> +CONFIG_SPL_PINCTRL=y
> +CONFIG_PINCTRL_IMX8=y
> +CONFIG_POWER_DOMAIN=y
> +CONFIG_IMX8_POWER_DOMAIN=y
> +CONFIG_DM_REGULATOR=y
> +CONFIG_SPL_DM_REGULATOR=y
> +CONFIG_DM_REGULATOR_FIXED=y
> +CONFIG_DM_REGULATOR_GPIO=y
> +CONFIG_SPL_DM_REGULATOR_GPIO=y
> +CONFIG_DM_SERIAL=y
> +CONFIG_FSL_LPUART=y
> +CONFIG_SPL_TINY_MEMSET=y
> +# CONFIG_EFI_LOADER is not set
> diff --git a/include/configs/imx8qxp_ai_ml.h
> b/include/configs/imx8qxp_ai_ml.h new file mode 100644 index
> 0000000000..ce7dc415c3
> --- /dev/null
> +++ b/include/configs/imx8qxp_ai_ml.h
> @@ -0,0 +1,157 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2018 NXP
> + * Copyright 2019 Linaro Ltd.
> + */
> +
> +#ifndef __IMX8QXP_AI_ML_H
> +#define __IMX8QXP_AI_ML_H
> +
> +#include <linux/sizes.h>
> +#include <asm/arch/imx-regs.h>
> +
> +#ifdef CONFIG_SPL_BUILD
> +#define CONFIG_SPL_MAX_SIZE				(124 * 1024)
> +#define CONFIG_SYS_MONITOR_LEN				(1024 * 1024)
> +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
> +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
> 	0x250
> +#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION		0
> +
> +#define CONFIG_SPL_LDSCRIPT		"arch/arm/cpu/armv8/u-boot-spl.lds"
> +#define CONFIG_SPL_STACK		0x013E000
> +#define CONFIG_SPL_BSS_START_ADDR	0x00128000
> +#define CONFIG_SPL_BSS_MAX_SIZE		0x1000	/* 4 KB */
> +#define CONFIG_SYS_SPL_MALLOC_START	0x00120000
> +#define CONFIG_SYS_SPL_MALLOC_SIZE	0x3000	/* 12 KB */
> +#define CONFIG_SERIAL_LPUART_BASE	0x5a080000
> +#define CONFIG_MALLOC_F_ADDR		0x00120000
> +
> +#define CONFIG_SPL_RAW_IMAGE_ARM_TRUSTED_FIRMWARE
> +
> +#define CONFIG_SPL_ABORT_ON_RAW_IMAGE
> +
> +#define CONFIG_OF_EMBED
> +#endif
> +
> +#define CONFIG_REMAKE_ELF
> +
> +#define CONFIG_BOARD_EARLY_INIT_F
> +
> +/* Flat Device Tree Definitions */
> +#define CONFIG_OF_BOARD_SETUP
> +
> +#define CONFIG_FSL_ESDHC
> +#define CONFIG_FSL_USDHC
> +#define CONFIG_SYS_FSL_ESDHC_ADDR       0
> +#define USDHC1_BASE_ADDR                0x5B010000
> +#define USDHC2_BASE_ADDR                0x5B020000
> +
> +#define CONFIG_ENV_OVERWRITE
> +
> +#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
> +
> +/* Initial environment variables */
> +#define CONFIG_EXTRA_ENV_SETTINGS		\
> +	"script=boot.scr\0" \
> +	"image=Image\0" \
> +	"panel=NULL\0" \
> +	"console=ttyLP2,${baudrate}
> earlycon=lpuart32,0x5a080000,${baudrate}\0" \
> +	"fdt_addr=0x83000000\0"			\
> +	"fdt_high=0xffffffffffffffff\0"		\
> +	"boot_fdt=try\0" \
> +	"fdt_file=imx8qxp-ai_ml.dtb\0" \
> +	"initrd_addr=0x83800000\0"		\
> +	"initrd_high=0xffffffffffffffff\0" \
> +	"mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \
> +	"mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
> +	"mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
> +	"mmcautodetect=yes\0" \
> +	"mmcargs=setenv bootargs console=${console} root=${mmcroot}\0 " \
> +	"loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr}
> ${script};\0" \
> +	"bootscript=echo Running bootscript from mmc ...; " \
> +		"source\0" \
> +	"loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr}
> ${image}\0" \
> +	"loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0"
> \
> +	"mmcboot=echo Booting from mmc ...; " \
> +		"run mmcargs; " \
> +		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
> +			"if run loadfdt; then " \
> +				"booti ${loadaddr} - ${fdt_addr}; " \
> +			"else " \
> +				"echo WARN: Cannot load the DT; " \
> +			"fi; " \
> +		"else " \
> +			"echo wait for boot; " \
> +		"fi;\0" \
> +	"netargs=setenv bootargs console=${console} " \
> +		"root=/dev/nfs " \
> +		"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
> +	"netboot=echo Booting from net ...; " \
> +		"run netargs;  " \
> +		"if test ${ip_dyn} = yes; then " \
> +			"setenv get_cmd dhcp; " \
> +		"else " \
> +			"setenv get_cmd tftp; " \
> +		"fi; " \
> +		"${get_cmd} ${loadaddr} ${image}; " \
> +		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
> +			"if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
> +				"booti ${loadaddr} - ${fdt_addr}; " \
> +			"else " \
> +				"echo WARN: Cannot load the DT; " \
> +			"fi; " \
> +		"else " \
> +			"booti; " \
> +		"fi;\0"
> +
> +#define CONFIG_BOOTCOMMAND \
> +	   "mmc dev ${mmcdev}; if mmc rescan; then " \
> +		   "if run loadbootscript; then " \
> +			   "run bootscript; " \
> +		   "else " \
> +			   "if run loadimage; then " \
> +				   "run mmcboot; " \
> +			   "else run netboot; " \
> +			   "fi; " \
> +		   "fi; " \
> +	   "else booti ${loadaddr} - ${fdt_addr}; fi"
> +
> +/* Link Definitions */
> +#define CONFIG_LOADADDR			0x80280000
> +
> +#define CONFIG_SYS_LOAD_ADDR           CONFIG_LOADADDR
> +
> +#define CONFIG_SYS_INIT_SP_ADDR         0x80200000
> +
> +/* Default environment is in SD */
> +#define CONFIG_ENV_SIZE			0x1000
> +#define CONFIG_ENV_OFFSET		(64 * SZ_64K)
> +#define CONFIG_SYS_MMC_ENV_PART		0	/* user area */
> +
> +#define CONFIG_SYS_MMC_IMG_LOAD_PART	1
> +
> +/* USDHC2 is the SD card interface */
> +#define CONFIG_SYS_MMC_ENV_DEV		1   /* USDHC2 */
> +#define CONFIG_MMCROOT			"/dev/mmcblk1p2"  /* USDHC2
> */
> +#define CONFIG_SYS_FSL_USDHC_NUM	2
> +
> +/* Size of malloc() pool */
> +#define CONFIG_SYS_MALLOC_LEN		((CONFIG_ENV_SIZE + (32 * 1024))
> * 1024)
> +
> +#define CONFIG_SYS_SDRAM_BASE		0x80000000
> +#define PHYS_SDRAM_1			0x80000000
> +#define PHYS_SDRAM_2			0x880000000
> +#define PHYS_SDRAM_1_SIZE		SZ_2G		/* 2 GB */
> +#define PHYS_SDRAM_2_SIZE		0x00000000	/* 0 GB */
> +
> +/* Serial */
> +#define CONFIG_BAUDRATE			115200
> +
> +/* Generic Timer Definitions */
> +#define COUNTER_FREQUENCY		8000000	/* 8MHz */
> +
> +/* Networking */
> +#define CONFIG_FEC_XCV_TYPE		RGMII
> +#define FEC_QUIRK_ENET_MAC
> +
> +#endif /* __IMX8QXP_AI_ML_H */

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

> --
> 2.17.1
Fabio Estevam July 12, 2019, 11:37 a.m. UTC | #2
Hi Manivannan,

On Thu, Jul 11, 2019 at 3:07 PM Manivannan Sadhasivam
<manivannan.sadhasivam@linaro.org> wrote:
>
> This commit adds initial board support for iMXQXP AI_ML board from

iMXQXP --> i.MX8QXP


> Einfochips. This board is one of the 96Boards Consumer Edition and AI boards
> of the 96Boards family based on i.MXQXP SoC from NXP/Freescale.

i.MXQXP -> i.MX8QXP

> --- /dev/null
> +++ b/board/einfochips/imx8qxp_ai_ml/README
> @@ -0,0 +1,49 @@
> +U-Boot for the Einfochips i.MX8QXP AI_ML board
> +
> +Quick Start
> +===========
> +
> +- Build the ARM Trusted firmware binary

The first instruction here is to build the ATF...

> +- Get scfw_tcm.bin and ahab-container.img
> +- Build U-Boot
> +- Flash the binary into the SD card
> +- Boot
> +
> +Get and Build the ARM Trusted firmware
> +======================================
> +
> +$ git clone https://source.codeaurora.org/external/imx/imx-atf

and later it is described how to get the ATF.

Looks like the order needs to be inverted.

> +void detail_board_ddr_info(void)
> +{
> +       puts("\nDDR    ");

Is this function really useful as its only purpose is to print "DDR" ?

> +}
> +
> +/*
> + * Board specific reset that is system reset.
> + */

You could use single line comment style instead.

> +#ifdef CONFIG_SPL_LOAD_FIT
> +int board_fit_config_name_match(const char *name)
> +{
> +       /* Just empty function now - can't decide what to choose */
> +       debug("%s: %s\n", __func__, name);

It seems you don't need this function then.

> +CONFIG_ARM=y
> +CONFIG_SPL_SYS_ICACHE_OFF=y
> +CONFIG_SPL_SYS_DCACHE_OFF=y

Why do you turn off the caches?

> +CONFIG_PHY_GIGE=y
> +CONFIG_FEC_MXC_SHARE_MDIO=y
> +CONFIG_FEC_MXC_MDIO_BASE=0x5B040000

Just wondering why CONFIG_FEC_MXC_MDIO_BASE is set in a board config file?

Shouldn't this base address be retrieved from device tree?

> +/* Flat Device Tree Definitions */
> +#define CONFIG_OF_BOARD_SETUP
> +
> +#define CONFIG_FSL_ESDHC
> +#define CONFIG_FSL_USDHC
> +#define CONFIG_SYS_FSL_ESDHC_ADDR       0
> +#define USDHC1_BASE_ADDR                0x5B010000
> +#define USDHC2_BASE_ADDR                0x5B020000

These base addresses should not be needed as they can be retrieved
from device tree.

> +#define CONFIG_ENV_OVERWRITE
> +
> +#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
> +
> +/* Initial environment variables */
> +#define CONFIG_EXTRA_ENV_SETTINGS              \
> +       "script=boot.scr\0" \
> +       "image=Image\0" \
> +       "panel=NULL\0" \

If you don't need the variable 'panel', then there is no need to define it.

> +#define CONFIG_BOOTCOMMAND \
> +          "mmc dev ${mmcdev}; if mmc rescan; then " \
> +                  "if run loadbootscript; then " \
> +                          "run bootscript; " \
> +                  "else " \
> +                          "if run loadimage; then " \
> +                                  "run mmcboot; " \
> +                          "else run netboot; " \
> +                          "fi; " \
> +                  "fi; " \
> +          "else booti ${loadaddr} - ${fdt_addr}; fi"

You may consider to use distro_boot for this community board. It makes
easier for Linux distros to support it.
Manivannan Sadhasivam July 12, 2019, 5:51 p.m. UTC | #3
Hi Fabio,

On Fri, Jul 12, 2019 at 08:37:24AM -0300, Fabio Estevam wrote:
> Hi Manivannan,
> 
> On Thu, Jul 11, 2019 at 3:07 PM Manivannan Sadhasivam
> <manivannan.sadhasivam@linaro.org> wrote:
> >
> > This commit adds initial board support for iMXQXP AI_ML board from
> 
> iMXQXP --> i.MX8QXP
> 

Ack.

> 
> > Einfochips. This board is one of the 96Boards Consumer Edition and AI boards
> > of the 96Boards family based on i.MXQXP SoC from NXP/Freescale.
> 
> i.MXQXP -> i.MX8QXP
> 

Ack.

> > --- /dev/null
> > +++ b/board/einfochips/imx8qxp_ai_ml/README
> > @@ -0,0 +1,49 @@
> > +U-Boot for the Einfochips i.MX8QXP AI_ML board
> > +
> > +Quick Start
> > +===========
> > +
> > +- Build the ARM Trusted firmware binary
> 
> The first instruction here is to build the ATF...
> 

Oops, this should be "Get and Build the ARM Trusted firmware"

> > +- Get scfw_tcm.bin and ahab-container.img
> > +- Build U-Boot
> > +- Flash the binary into the SD card
> > +- Boot
> > +
> > +Get and Build the ARM Trusted firmware
> > +======================================
> > +
> > +$ git clone https://source.codeaurora.org/external/imx/imx-atf
> 
> and later it is described how to get the ATF.
> 
> Looks like the order needs to be inverted.
> 
> > +void detail_board_ddr_info(void)
> > +{
> > +       puts("\nDDR    ");
> 
> Is this function really useful as its only purpose is to print "DDR" ?
> 

Copy paste clutter. Will remove it.

> > +}
> > +
> > +/*
> > + * Board specific reset that is system reset.
> > + */
> 
> You could use single line comment style instead.
> 

Ack.

> > +#ifdef CONFIG_SPL_LOAD_FIT
> > +int board_fit_config_name_match(const char *name)
> > +{
> > +       /* Just empty function now - can't decide what to choose */
> > +       debug("%s: %s\n", __func__, name);
> 
> It seems you don't need this function then.
> 

Yeah, will remove it.

> > +CONFIG_ARM=y
> > +CONFIG_SPL_SYS_ICACHE_OFF=y
> > +CONFIG_SPL_SYS_DCACHE_OFF=y
> 
> Why do you turn off the caches?
> 

This also slipped when copying from mek board. Will remove.

> > +CONFIG_PHY_GIGE=y
> > +CONFIG_FEC_MXC_SHARE_MDIO=y
> > +CONFIG_FEC_MXC_MDIO_BASE=0x5B040000
> 
> Just wondering why CONFIG_FEC_MXC_MDIO_BASE is set in a board config file?
> 
> Shouldn't this base address be retrieved from device tree?
> 

Ideally it should but the driver is not matured enough to retrieve address
from DT. Currently it relies on the Kconfig symbol, hence it needs to be
present till the driver is cleaned up.

> > +/* Flat Device Tree Definitions */
> > +#define CONFIG_OF_BOARD_SETUP
> > +
> > +#define CONFIG_FSL_ESDHC
> > +#define CONFIG_FSL_USDHC
> > +#define CONFIG_SYS_FSL_ESDHC_ADDR       0
> > +#define USDHC1_BASE_ADDR                0x5B010000
> > +#define USDHC2_BASE_ADDR                0x5B020000
> 
> These base addresses should not be needed as they can be retrieved
> from device tree.
> 

Actually these defines are not needed. Will remove.

> > +#define CONFIG_ENV_OVERWRITE
> > +
> > +#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
> > +
> > +/* Initial environment variables */
> > +#define CONFIG_EXTRA_ENV_SETTINGS              \
> > +       "script=boot.scr\0" \
> > +       "image=Image\0" \
> > +       "panel=NULL\0" \
> 
> If you don't need the variable 'panel', then there is no need to define it.
> 

Ack.

> > +#define CONFIG_BOOTCOMMAND \
> > +          "mmc dev ${mmcdev}; if mmc rescan; then " \
> > +                  "if run loadbootscript; then " \
> > +                          "run bootscript; " \
> > +                  "else " \
> > +                          "if run loadimage; then " \
> > +                                  "run mmcboot; " \
> > +                          "else run netboot; " \
> > +                          "fi; " \
> > +                  "fi; " \
> > +          "else booti ${loadaddr} - ${fdt_addr}; fi"
> 
> You may consider to use distro_boot for this community board. It makes
> easier for Linux distros to support it.

Agree. Initially I thought of not using it since the most of imx8 boards are
not using distro_boot, but anyway it doesn't hurt to do so.

Thanks,
Mani
diff mbox series

Patch

diff --git a/arch/arm/mach-imx/imx8/Kconfig b/arch/arm/mach-imx/imx8/Kconfig
index bbe323d5ca..cec21f8dd2 100644
--- a/arch/arm/mach-imx/imx8/Kconfig
+++ b/arch/arm/mach-imx/imx8/Kconfig
@@ -37,6 +37,11 @@  config TARGET_COLIBRI_IMX8X
 	select BOARD_LATE_INIT
 	select IMX8QXP
 
+config TARGET_IMX8QXP_AI_ML
+	bool "Support i.MX8QXP AI_ML board"
+	select BOARD_LATE_INIT
+	select IMX8QXP
+
 config TARGET_IMX8QM_MEK
 	bool "Support i.MX8QM MEK board"
 	select BOARD_LATE_INIT
@@ -49,6 +54,7 @@  config TARGET_IMX8QXP_MEK
 
 endchoice
 
+source "board/einfochips/imx8qxp_ai_ml/Kconfig"
 source "board/freescale/imx8qm_mek/Kconfig"
 source "board/freescale/imx8qxp_mek/Kconfig"
 source "board/toradex/apalis-imx8/Kconfig"
diff --git a/board/einfochips/imx8qxp_ai_ml/Kconfig b/board/einfochips/imx8qxp_ai_ml/Kconfig
new file mode 100644
index 0000000000..697a831013
--- /dev/null
+++ b/board/einfochips/imx8qxp_ai_ml/Kconfig
@@ -0,0 +1,12 @@ 
+if TARGET_IMX8QXP_AI_ML
+
+config SYS_BOARD
+	default "imx8qxp_ai_ml"
+
+config SYS_VENDOR
+	default "einfochips"
+
+config SYS_CONFIG_NAME
+	default "imx8qxp_ai_ml"
+
+endif
diff --git a/board/einfochips/imx8qxp_ai_ml/MAINTAINERS b/board/einfochips/imx8qxp_ai_ml/MAINTAINERS
new file mode 100644
index 0000000000..add0bd9431
--- /dev/null
+++ b/board/einfochips/imx8qxp_ai_ml/MAINTAINERS
@@ -0,0 +1,6 @@ 
+i.MX8QXP AI_ML BOARD
+M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+S:	Maintained
+F:	board/einfochips/imx8qxp_ai_ml/
+F:	include/configs/imx8qxp_ai_ml.h
+F:	configs/imx8qxp_ai_ml_defconfig
diff --git a/board/einfochips/imx8qxp_ai_ml/Makefile b/board/einfochips/imx8qxp_ai_ml/Makefile
new file mode 100644
index 0000000000..e08774dc6e
--- /dev/null
+++ b/board/einfochips/imx8qxp_ai_ml/Makefile
@@ -0,0 +1,8 @@ 
+#
+# Copyright 2019 Linaro Ltd.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += imx8qxp_ai_ml.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
diff --git a/board/einfochips/imx8qxp_ai_ml/README b/board/einfochips/imx8qxp_ai_ml/README
new file mode 100644
index 0000000000..416a157ea8
--- /dev/null
+++ b/board/einfochips/imx8qxp_ai_ml/README
@@ -0,0 +1,49 @@ 
+U-Boot for the Einfochips i.MX8QXP AI_ML board
+
+Quick Start
+===========
+
+- Build the ARM Trusted firmware binary
+- Get scfw_tcm.bin and ahab-container.img
+- Build U-Boot
+- Flash the binary into the SD card
+- Boot
+
+Get and Build the ARM Trusted firmware
+======================================
+
+$ git clone https://source.codeaurora.org/external/imx/imx-atf
+$ cd imx-atf/
+$ git checkout origin/imx_4.9.88_imx8qxp_beta2 -b imx_4.9.88_imx8qxp_beta2
+$ make PLAT=imx8qxp bl31
+
+Get scfw_tcm.bin and ahab-container.img
+=======================================
+
+$ wget https://raw.githubusercontent.com/96boards-ai-ml/binaries/master/mx8qx-aiml-scfw-tcm.bin
+$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.1.bin
+$ chmod +x firmware-imx-8.1.bin
+$ ./firmware-imx-8.1.bin
+
+Copy the following binaries to U-Boot folder:
+
+$ cp imx-atf/build/imx8qxp/release/bl31.bin .
+$ cp firmware-imx-8.1/firmware/seco/mx8qx-ahab-container.img .
+
+Build U-Boot
+============
+
+$ make imx8qxp_ai_ml_defconfig
+$ make u-boot-dtb.imx
+
+Flash the binary into the SD card
+=================================
+
+Burn the u-boot-dtb.imx binary to SD card offset 32KB:
+
+$ sudo dd if=u-boot-dtb.imx of=/dev/sd[x] bs=1024 seek=32
+
+Boot
+====
+
+Set Boot switch SW2: 1100.
diff --git a/board/einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c b/board/einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c
new file mode 100644
index 0000000000..d568b16ad9
--- /dev/null
+++ b/board/einfochips/imx8qxp_ai_ml/imx8qxp_ai_ml.c
@@ -0,0 +1,128 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Copyright 2019 Linaro Ltd.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <linux/libfdt.h>
+#include <environment.h>
+#include <fsl_esdhc.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sci/sci.h>
+#include <asm/arch/imx8-pins.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/sys_proto.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_PAD_CTRL	((SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \
+			 (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
+			 (SC_PAD_28FDSOI_DSE_DV_HIGH << PADRING_DSE_SHIFT) | \
+			 (SC_PAD_28FDSOI_PS_PU << PADRING_PULL_SHIFT))
+
+static iomux_cfg_t uart2_pads[] = {
+	SC_P_UART2_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	SC_P_UART2_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+static void setup_iomux_uart(void)
+{
+	imx8_iomux_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
+}
+
+int board_early_init_f(void)
+{
+	sc_pm_clock_rate_t rate = SC_80MHZ;
+	int ret;
+
+	/* Set UART2 clock root to 80 MHz */
+	ret = sc_pm_setup_uart(SC_R_UART_2, rate);
+	if (ret)
+		return ret;
+
+	setup_iomux_uart();
+
+	return 0;
+}
+
+#if IS_ENABLED(CONFIG_DM_GPIO)
+static void board_gpio_init(void)
+{
+	/* TODO */
+}
+#else
+static inline void board_gpio_init(void) {}
+#endif
+
+#if IS_ENABLED(CONFIG_FEC_MXC)
+#include <miiphy.h>
+
+int board_phy_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x8);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
+
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+
+	return 0;
+}
+#endif
+
+int checkboard(void)
+{
+	puts("Board: iMX8QXP AI_ML\n");
+
+	build_info();
+	print_bootinfo();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	board_gpio_init();
+
+	return 0;
+}
+
+void detail_board_ddr_info(void)
+{
+	puts("\nDDR    ");
+}
+
+/*
+ * Board specific reset that is system reset.
+ */
+void reset_cpu(ulong addr)
+{
+	/* TODO */
+}
+
+#ifdef CONFIG_OF_BOARD_SETUP
+int ft_board_setup(void *blob, bd_t *bd)
+{
+	return 0;
+}
+#endif
+
+int board_mmc_get_env_dev(int devno)
+{
+	return devno;
+}
+
+int board_late_init(void)
+{
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+	env_set("board_name", "AI_ML");
+	env_set("board_rev", "v1.0");
+#endif
+
+	return 0;
+}
diff --git a/board/einfochips/imx8qxp_ai_ml/imximage.cfg b/board/einfochips/imx8qxp_ai_ml/imximage.cfg
new file mode 100644
index 0000000000..4fc5ade313
--- /dev/null
+++ b/board/einfochips/imx8qxp_ai_ml/imximage.cfg
@@ -0,0 +1,24 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ *
+ * Refer doc/README.imx8image for more details about how-to configure
+ * and create imx8image boot image
+ */
+
+#define __ASSEMBLY__
+
+/* Boot from SD, sector size 0x400 */
+BOOT_FROM SD 0x400
+/* SoC type IMX8QX */
+SOC_TYPE IMX8QX
+/* Append seco container image */
+APPEND mx8qx-ahab-container.img
+/* Create the 2nd container */
+CONTAINER
+/* Add scfw image with exec attribute */
+IMAGE SCU mx8qx-aiml-scfw-tcm.bin
+/* Add ATF image with exec attribute */
+IMAGE A35 bl31.bin 0x80000000
+/* Add U-Boot image with load attribute */
+DATA A35 u-boot-dtb.bin 0x80020000
diff --git a/board/einfochips/imx8qxp_ai_ml/spl.c b/board/einfochips/imx8qxp_ai_ml/spl.c
new file mode 100644
index 0000000000..cb4006eb2a
--- /dev/null
+++ b/board/einfochips/imx8qxp_ai_ml/spl.c
@@ -0,0 +1,59 @@ 
+/*
+ * Copyright 2018 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spl.h>
+#include <dm/uclass.h>
+#include <dm/device.h>
+#include <dm/uclass-internal.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void spl_board_init(void)
+{
+	struct udevice *dev;
+
+	uclass_find_first_device(UCLASS_MISC, &dev);
+
+	for (; dev; uclass_find_next_device(&dev)) {
+		if (device_probe(dev))
+			continue;
+	}
+
+	arch_cpu_init();
+
+	board_early_init_f();
+
+	timer_init();
+
+	preloader_console_init();
+
+	puts("Normal Boot\n");
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	debug("%s: %s\n", __func__, name);
+
+	return 0;
+}
+#endif
+
+void board_init_f(ulong dummy)
+{
+	/* Clear global data */
+	memset((void *)gd, 0, sizeof(gd_t));
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	board_init_r(NULL, 0);
+}
diff --git a/configs/imx8qxp_ai_ml_defconfig b/configs/imx8qxp_ai_ml_defconfig
new file mode 100644
index 0000000000..3d2d26ea70
--- /dev/null
+++ b/configs/imx8qxp_ai_ml_defconfig
@@ -0,0 +1,83 @@ 
+CONFIG_ARM=y
+CONFIG_SPL_SYS_ICACHE_OFF=y
+CONFIG_SPL_SYS_DCACHE_OFF=y
+CONFIG_ARCH_IMX8=y
+CONFIG_SYS_TEXT_BASE=0x80020000
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_TARGET_IMX8QXP_AI_ML=y
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=4
+CONFIG_SPL=y
+CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh"
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/einfochips/imx8qxp_ai_ml/imximage.cfg"
+CONFIG_BOOTDELAY=3
+CONFIG_LOG=y
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SPL_POWER_SUPPORT=y
+CONFIG_SPL_POWER_DOMAIN=y
+CONFIG_SPL_WATCHDOG_SUPPORT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CPU=y
+# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DM=y
+CONFIG_CMD_FUSE=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_FAT_WRITE=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="fsl-imx8qxp-ai_ml"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_CLK=y
+CONFIG_CLK_IMX8=y
+CONFIG_CPU=y
+CONFIG_DM_GPIO=y
+CONFIG_MXC_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_IMX_LPI2C=y
+CONFIG_MISC=y
+CONFIG_DM_MMC=y
+CONFIG_PHYLIB=y
+CONFIG_PHY_ADDR_ENABLE=y
+CONFIG_PHY_ATHEROS=y
+CONFIG_DM_ETH=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_PHY_GIGE=y
+CONFIG_FEC_MXC_SHARE_MDIO=y
+CONFIG_FEC_MXC_MDIO_BASE=0x5B040000
+CONFIG_FEC_MXC=y
+CONFIG_MII=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_IMX8=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_IMX8_POWER_DOMAIN=y
+CONFIG_DM_REGULATOR=y
+CONFIG_SPL_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_SPL_DM_REGULATOR_GPIO=y
+CONFIG_DM_SERIAL=y
+CONFIG_FSL_LPUART=y
+CONFIG_SPL_TINY_MEMSET=y
+# CONFIG_EFI_LOADER is not set
diff --git a/include/configs/imx8qxp_ai_ml.h b/include/configs/imx8qxp_ai_ml.h
new file mode 100644
index 0000000000..ce7dc415c3
--- /dev/null
+++ b/include/configs/imx8qxp_ai_ml.h
@@ -0,0 +1,157 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ * Copyright 2019 Linaro Ltd.
+ */
+
+#ifndef __IMX8QXP_AI_ML_H
+#define __IMX8QXP_AI_ML_H
+
+#include <linux/sizes.h>
+#include <asm/arch/imx-regs.h>
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SPL_MAX_SIZE				(124 * 1024)
+#define CONFIG_SYS_MONITOR_LEN				(1024 * 1024)
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR		0x250
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION		0
+
+#define CONFIG_SPL_LDSCRIPT		"arch/arm/cpu/armv8/u-boot-spl.lds"
+#define CONFIG_SPL_STACK		0x013E000
+#define CONFIG_SPL_BSS_START_ADDR	0x00128000
+#define CONFIG_SPL_BSS_MAX_SIZE		0x1000	/* 4 KB */
+#define CONFIG_SYS_SPL_MALLOC_START	0x00120000
+#define CONFIG_SYS_SPL_MALLOC_SIZE	0x3000	/* 12 KB */
+#define CONFIG_SERIAL_LPUART_BASE	0x5a080000
+#define CONFIG_MALLOC_F_ADDR		0x00120000
+
+#define CONFIG_SPL_RAW_IMAGE_ARM_TRUSTED_FIRMWARE
+
+#define CONFIG_SPL_ABORT_ON_RAW_IMAGE
+
+#define CONFIG_OF_EMBED
+#endif
+
+#define CONFIG_REMAKE_ELF
+
+#define CONFIG_BOARD_EARLY_INIT_F
+
+/* Flat Device Tree Definitions */
+#define CONFIG_OF_BOARD_SETUP
+
+#define CONFIG_FSL_ESDHC
+#define CONFIG_FSL_USDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR       0
+#define USDHC1_BASE_ADDR                0x5B010000
+#define USDHC2_BASE_ADDR                0x5B020000
+
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+
+/* Initial environment variables */
+#define CONFIG_EXTRA_ENV_SETTINGS		\
+	"script=boot.scr\0" \
+	"image=Image\0" \
+	"panel=NULL\0" \
+	"console=ttyLP2,${baudrate} earlycon=lpuart32,0x5a080000,${baudrate}\0" \
+	"fdt_addr=0x83000000\0"			\
+	"fdt_high=0xffffffffffffffff\0"		\
+	"boot_fdt=try\0" \
+	"fdt_file=imx8qxp-ai_ml.dtb\0" \
+	"initrd_addr=0x83800000\0"		\
+	"initrd_high=0xffffffffffffffff\0" \
+	"mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \
+	"mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
+	"mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
+	"mmcautodetect=yes\0" \
+	"mmcargs=setenv bootargs console=${console} root=${mmcroot}\0 " \
+	"loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
+	"bootscript=echo Running bootscript from mmc ...; " \
+		"source\0" \
+	"loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
+	"loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
+	"mmcboot=echo Booting from mmc ...; " \
+		"run mmcargs; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if run loadfdt; then " \
+				"booti ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"echo WARN: Cannot load the DT; " \
+			"fi; " \
+		"else " \
+			"echo wait for boot; " \
+		"fi;\0" \
+	"netargs=setenv bootargs console=${console} " \
+		"root=/dev/nfs " \
+		"ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
+	"netboot=echo Booting from net ...; " \
+		"run netargs;  " \
+		"if test ${ip_dyn} = yes; then " \
+			"setenv get_cmd dhcp; " \
+		"else " \
+			"setenv get_cmd tftp; " \
+		"fi; " \
+		"${get_cmd} ${loadaddr} ${image}; " \
+		"if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
+			"if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
+				"booti ${loadaddr} - ${fdt_addr}; " \
+			"else " \
+				"echo WARN: Cannot load the DT; " \
+			"fi; " \
+		"else " \
+			"booti; " \
+		"fi;\0"
+
+#define CONFIG_BOOTCOMMAND \
+	   "mmc dev ${mmcdev}; if mmc rescan; then " \
+		   "if run loadbootscript; then " \
+			   "run bootscript; " \
+		   "else " \
+			   "if run loadimage; then " \
+				   "run mmcboot; " \
+			   "else run netboot; " \
+			   "fi; " \
+		   "fi; " \
+	   "else booti ${loadaddr} - ${fdt_addr}; fi"
+
+/* Link Definitions */
+#define CONFIG_LOADADDR			0x80280000
+
+#define CONFIG_SYS_LOAD_ADDR           CONFIG_LOADADDR
+
+#define CONFIG_SYS_INIT_SP_ADDR         0x80200000
+
+/* Default environment is in SD */
+#define CONFIG_ENV_SIZE			0x1000
+#define CONFIG_ENV_OFFSET		(64 * SZ_64K)
+#define CONFIG_SYS_MMC_ENV_PART		0	/* user area */
+
+#define CONFIG_SYS_MMC_IMG_LOAD_PART	1
+
+/* USDHC2 is the SD card interface */
+#define CONFIG_SYS_MMC_ENV_DEV		1   /* USDHC2 */
+#define CONFIG_MMCROOT			"/dev/mmcblk1p2"  /* USDHC2 */
+#define CONFIG_SYS_FSL_USDHC_NUM	2
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		((CONFIG_ENV_SIZE + (32 * 1024)) * 1024)
+
+#define CONFIG_SYS_SDRAM_BASE		0x80000000
+#define PHYS_SDRAM_1			0x80000000
+#define PHYS_SDRAM_2			0x880000000
+#define PHYS_SDRAM_1_SIZE		SZ_2G		/* 2 GB */
+#define PHYS_SDRAM_2_SIZE		0x00000000	/* 0 GB */
+
+/* Serial */
+#define CONFIG_BAUDRATE			115200
+
+/* Generic Timer Definitions */
+#define COUNTER_FREQUENCY		8000000	/* 8MHz */
+
+/* Networking */
+#define CONFIG_FEC_XCV_TYPE		RGMII
+#define FEC_QUIRK_ENET_MAC
+
+#endif /* __IMX8QXP_AI_ML_H */