u-boot/board/toradex/verdin-imx8mp/verdin-imx8mp.c
Marcel Ziswiler 2bc2f817ce board: toradex: add verdin imx8m plus support
This adds initial support for the Toradex Verdin iMX8M Plus Quad 4GB WB
IT V1.0B module. They are strapped to boot from eFuses which are factory
fused to properly boot from their on-module eMMC. U-Boot supports
booting from the on-module eMMC only, SDP support is disabled for now
due to missing i.MX 8M Plus USB support.

Functionality wise the following is known to be working:
- eMMC, 8-bit and 4-bit MMC/SD card slots
- Ethernet both on-module eQoS and FEC (requires PHY on carrier board)
- GPIOs
- I2C

Boot sequence is:
SPL ---> ATF (TF-A) ---> U-boot proper

ATF, U-boot proper and u-boot.dtb images are packed into a FIT image,
loaded by SPL.

Boot:
U-Boot SPL 2022.04-rc1-00164-g21a0312611-dirty (Feb 07 2022 - 11:34:04 +0100)
Quad die, dual rank failed, attempting dual die, single rank configuration.
Normal Boot
WDT:   Started watchdog@30280000 with servicing (60s timeout)
Trying to boot from BOOTROM
Find img info 0x&48025a00, size 872
Need continue download 1024
Download 779264, Total size 780424
NOTICE:  BL31: v2.2(release):rel_imx_5.4.70_2.3.2_rc1-5-g835a8f67b
NOTICE:  BL31: Built : 16:52:37, Aug 26 2021

U-Boot 2022.04-rc1-00164-g21a0312611-dirty (Feb 07 2022 - 11:34:04 +0100)

CPU:   Freescale i.MX8MP[8] rev1.1 at 1200 MHz
Reset cause: POR
DRAM:  8 GiB
Core:  78 devices, 18 uclasses, devicetree: separate
WDT:   Started watchdog@30280000 with servicing (60s timeout)
MMC:   FSL_SDHC: 1, FSL_SDHC: 2
Loading Environment from MMC... OK
In:    serial
Out:   serial
Err:   serial
Model: Toradex Verdin iMX8M Plus Quad 4GB Wi-Fi / BT IT V1.0B, Serial# 06817281
Carrier: Toradex Verdin Development Board V1.1A, Serial# 10807609
Setting variant to wifi
Net:   Hard-coding pdata->enetaddr
eth1: ethernet@30be0000, eth0: ethernet@30bf0000 [PRIME]
Hit any key to stop autoboot:  0
Verdin iMX8MP #

Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Reviewed-by: Fabio Estevam <festevam@gmail.com>
2022-02-07 16:33:22 +01:00

140 lines
3.1 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2022 Toradex
*/
#include <common.h>
#include <asm/arch/clock.h>
#include <asm/arch/imx8mp_pins.h>
#include <asm/arch/sys_proto.h>
#include <asm-generic/gpio.h>
#include <asm/global_data.h>
#include <asm/mach-imx/gpio.h>
#include <asm/mach-imx/iomux-v3.h>
#include <errno.h>
#include <env.h>
#include <init.h>
#include <linux/delay.h>
#include <micrel.h>
#include <miiphy.h>
#include <netdev.h>
#include "../common/tdx-cfg-block.h"
DECLARE_GLOBAL_DATA_PTR;
#define UART_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_FSEL1)
#define WDOG_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_ODE | PAD_CTL_PUE | PAD_CTL_PE)
/* Verdin UART_3, Console/Debug UART */
static const iomux_v3_cfg_t uart_pads[] = {
MX8MP_PAD_UART3_RXD__UART3_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
MX8MP_PAD_UART3_TXD__UART3_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
};
static const iomux_v3_cfg_t wdog_pads[] = {
MX8MP_PAD_GPIO1_IO02__WDOG1_WDOG_B | MUX_PAD_CTRL(WDOG_PAD_CTRL),
};
int board_early_init_f(void)
{
struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
set_wdog_reset(wdog);
imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
init_uart_clk(2);
return 0;
}
static void setup_fec(void)
{
struct iomuxc_gpr_base_regs *gpr =
(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
/* Enable RGMII TX clk output */
setbits_le32(&gpr->gpr[1], BIT(22));
}
static int setup_eqos(void)
{
struct iomuxc_gpr_base_regs *gpr =
(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
/* set INTF as RGMII, enable RGMII TXC clock */
clrsetbits_le32(&gpr->gpr[1],
IOMUXC_GPR_GPR1_GPR_ENET_QOS_INTF_SEL_MASK, BIT(16));
setbits_le32(&gpr->gpr[1], BIT(19) | BIT(21));
return set_clk_eqos(ENET_125MHZ);
}
#if IS_ENABLED(CONFIG_NET)
int board_phy_config(struct phy_device *phydev)
{
if (phydev->drv->config)
phydev->drv->config(phydev);
return 0;
}
#endif
int board_init(void)
{
int ret = 0;
if (IS_ENABLED(CONFIG_FEC_MXC))
setup_fec();
if (IS_ENABLED(CONFIG_DWC_ETH_QOS))
ret = setup_eqos();
return ret;
}
static void select_dt_from_module_version(void)
{
char variant[32];
char *env_variant = env_get("variant");
int is_wifi = 0;
if (IS_ENABLED(CONFIG_TDX_CFG_BLOCK)) {
/*
* If we have a valid config block and it says we are a module with
* Wi-Fi/Bluetooth make sure we use the -wifi device tree.
*/
is_wifi = (tdx_hw_tag.prodid == VERDIN_IMX8MPQ_WIFI_BT_IT) ||
(tdx_hw_tag.prodid == VERDIN_IMX8MPQ_2GB_WIFI_BT_IT) ||
(tdx_hw_tag.prodid == VERDIN_IMX8MPQ_8GB_WIFI_BT);
}
if (is_wifi)
strlcpy(&variant[0], "wifi", sizeof(variant));
else
strlcpy(&variant[0], "nonwifi", sizeof(variant));
if (strcmp(variant, env_variant)) {
printf("Setting variant to %s\n", variant);
env_set("variant", variant);
if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
env_save();
}
}
int board_late_init(void)
{
select_dt_from_module_version();
return 0;
}
#if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP)
int ft_board_setup(void *blob, struct bd_info *bd)
{
return 0;
}
#endif