For 2020.10
-----------

- fixes for Toradex board
- fix warnings from previous PR
- HAB: reset instead of panic after failure
- new board:  MYiR Tech MYS-6ULX
- mx6cuboxi: use OF_PLATDATA
- further changes for DM

Travis: https://travis-ci.org/github/sbabic/u-boot-imx/builds/714513163
This commit is contained in:
Tom Rini
2020-08-04 11:11:02 -04:00
52 changed files with 1718 additions and 249 deletions

View File

@@ -0,0 +1,12 @@
if TARGET_MYS_6ULX
config SYS_BOARD
default "mys_6ulx"
config SYS_VENDOR
default "myir"
config SYS_CONFIG_NAME
default "mys_6ulx"
endif

View File

@@ -0,0 +1,9 @@
MYS_6ULX BOARD
M: Parthiban Nallathambi <parthiban@linumiz.com>
S: Maintained
F: arch/arm/dts/imx6ull-myir-mys-6ulx-nand.dts
F: arch/arm/dts/imx6ull-myir-mys-6ulx.dtsi
F: arch/arm/dts/imx6ull-mys-6ulx-u-boot.dtsi
F: board/myir/mys_6ulx/
F: configs/myir_mys_6ulx_defconfig
F: include/configs/mys_6ulx.h

View File

@@ -0,0 +1,4 @@
# SPDX-License-Identifier: GPL-2.0+
obj-y := mys_6ulx.o
obj-$(CONFIG_SPL_BUILD) += spl.o

View File

@@ -0,0 +1,52 @@
How to use U-Boot on MYiR MYS-6ULX Single Board Computer
--------------------------------------------------------
- Configure and build U-Boot for MYS-6ULX iMX6ULL:
$ make mrproper
$ make myir_mys_6ulx_defconfig
$ make
This will generate SPL and u-boot-dtb.img images.
Boot from MMC/SD:
- The SPL and u-boot-dtb.img images need to be flashed into the micro SD card:
$ sudo dd if=SPL of=/dev/mmcblk0 bs=1k seek=1; sync
$ sudo dd if=u-boot-dtb.img of=/dev/mmcblk0 bs=1k seek=69; sync
- Boot mode settings:
Boot switch position: SW1 -> 0
SW2 -> 1
SW3 -> 0
SW4 -> 1
Boot from NAND:
- Boot the board using SD/MMC or Serial download and load the SPL into memory
either from SD/MMC or TFTP.
Default MTD layout is 512k(spl),1m(uboot),1m(uboot-dup),-(ubi)
Flash SPL to NAND from SD/MMC,
$ ext4load mmc 0:2 $loadaddr SPL
$ nand erase.part spl
$ nandbcb init $loadaddr 0x0 $filesize
Flash u-boot proper to NAND from SD/MMC,
$ ext4load mmc 0:2 $loadaddr u-boot-dtb.img
$ nand erase.part uboot
$ nand write $loadaddr uboot $filesize
- Boot mode settings:
Boot switch position: SW1 -> 1
SW2 -> 0
SW3 -> 0
SW4 -> 1
- Connect the Serial cable to UART0 and the PC for the console.
- Reset the board using and U-Boot should boot from NAND.

View File

@@ -0,0 +1,117 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2020 Linumiz
* Author: Parthiban Nallathambi <parthiban@linumiz.com>
*/
#include <init.h>
#include <asm/arch/clock.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/mx6-pins.h>
#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm/mach-imx/mxc_i2c.h>
#include <fsl_esdhc_imx.h>
#include <linux/bitops.h>
#include <miiphy.h>
#include <netdev.h>
#include <usb.h>
#include <usb/ehci-ci.h>
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
return 0;
}
#define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | \
PAD_CTL_HYS)
static iomux_v3_cfg_t const uart1_pads[] = {
MX6_PAD_UART1_TX_DATA__UART1_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_UART1_RX_DATA__UART1_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
};
static iomux_v3_cfg_t const uart5_pads[] = {
MX6_PAD_UART5_TX_DATA__UART5_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_UART5_RX_DATA__UART5_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_GPIO1_IO09__UART5_DCE_CTS | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_GPIO1_IO08__UART5_DCE_RTS | MUX_PAD_CTRL(UART_PAD_CTRL),
};
static void setup_iomux_uart(void)
{
imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
imx_iomux_v3_setup_multiple_pads(uart5_pads, ARRAY_SIZE(uart5_pads));
}
#ifdef CONFIG_FEC_MXC
static int setup_fec(void)
{
struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
int ret;
/*
* Use 50M anatop loopback REF_CLK1 for ENET1,
* clear gpr1[13], set gpr1[17].
*/
clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK,
IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK);
ret = enable_fec_anatop_clock(0, ENET_50MHZ);
if (ret)
return ret;
enable_enet_clk(1);
return 0;
}
int board_phy_config(struct phy_device *phydev)
{
/*
* Defaults + Enable status LEDs (LED1: Activity, LED0: Link) & select
* 50 MHz RMII clock mode.
*/
phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x8190);
if (phydev->drv->config)
phydev->drv->config(phydev);
return 0;
}
#endif /* CONFIG_FEC_MXC */
int board_early_init_f(void)
{
setup_iomux_uart();
return 0;
}
int board_init(void)
{
/* Address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
#ifdef CONFIG_FEC_MXC
setup_fec();
#endif
return 0;
}
int checkboard(void)
{
u32 cpurev = get_cpu_rev();
printf("Board: MYiR MYS-6ULX %s Single Board Computer\n",
get_imx_type((cpurev & 0xFF000) >> 12));
return 0;
}

206
board/myir/mys_6ulx/spl.c Normal file
View File

@@ -0,0 +1,206 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2020 Linumiz
* Author: Parthiban Nallathambi <parthiban@linumiz.com>
*/
#include <common.h>
#include <init.h>
#include <spl.h>
#include <asm/arch/clock.h>
#include <asm/io.h>
#include <asm/arch/mx6-ddr.h>
#include <asm/arch/mx6-pins.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/sys_proto.h>
#include <fsl_esdhc_imx.h>
/* Configuration for Micron MT41K128M16JT-125, 32M x 16 x 8 -> 256MiB */
static struct mx6ul_iomux_grp_regs mx6_grp_ioregs = {
.grp_addds = 0x00000030,
.grp_ddrmode_ctl = 0x00020000,
.grp_b0ds = 0x00000030,
.grp_ctlds = 0x00000030,
.grp_b1ds = 0x00000030,
.grp_ddrpke = 0x00000000,
.grp_ddrmode = 0x00020000,
.grp_ddr_type = 0x000c0000,
};
static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = {
.dram_dqm0 = 0x00000030,
.dram_dqm1 = 0x00000030,
.dram_ras = 0x00000030,
.dram_cas = 0x00000030,
.dram_odt0 = 0x00000030,
.dram_odt1 = 0x00000030,
.dram_sdba2 = 0x00000000,
.dram_sdclk_0 = 0x00000030,
.dram_sdqs0 = 0x00000030,
.dram_sdqs1 = 0x00000030,
.dram_reset = 0x00000030,
};
static struct mx6_mmdc_calibration mx6_mmcd_calib = {
.p0_mpwldectrl0 = 0x00000000,
.p0_mpdgctrl0 = 0x41480148,
.p0_mprddlctl = 0x40403E42,
.p0_mpwrdlctl = 0x40405852,
};
struct mx6_ddr_sysinfo ddr_sysinfo = {
.dsize = 0, /* Bus size = 16bit */
.cs_density = 32,
.ncs = 1,
.cs1_mirror = 0,
.rtt_wr = 1,
.rtt_nom = 1,
.walat = 1, /* Write additional latency */
.ralat = 5, /* Read additional latency */
.mif3_mode = 3, /* Command prediction working mode */
.bi_on = 1, /* Bank interleaving enabled */
.pd_fast_exit = 1,
.sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
.rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
.ddr_type = DDR_TYPE_DDR3,
.refsel = 1, /* Refresh cycles at 32KHz */
.refr = 7, /* 8 refresh commands per refresh cycle */
};
/* MT41K128M16JT-125 (2Gb density) */
static struct mx6_ddr3_cfg mem_ddr = {
.mem_speed = 1600,
.density = 2,
.width = 16,
.banks = 8,
.rowaddr = 14,
.coladdr = 10,
.pagesz = 2,
.trcd = 1375,
.trcmin = 4875,
.trasmin = 3500,
};
static void ccgr_init(void)
{
struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
writel(0xFFFFFFFF, &ccm->CCGR0);
writel(0xFFFFFFFF, &ccm->CCGR1);
writel(0xFFFFFFFF, &ccm->CCGR2);
writel(0xFFFFFFFF, &ccm->CCGR3);
writel(0xFFFFFFFF, &ccm->CCGR4);
writel(0xFFFFFFFF, &ccm->CCGR5);
writel(0xFFFFFFFF, &ccm->CCGR6);
}
static void spl_dram_init(void)
{
mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
mx6_dram_cfg(&ddr_sysinfo, &mx6_mmcd_calib, &mem_ddr);
}
#ifdef CONFIG_FSL_ESDHC_IMX
#define USDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
PAD_CTL_PUS_22K_UP | PAD_CTL_SPEED_LOW | \
PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | \
PAD_CTL_HYS)
static iomux_v3_cfg_t const usdhc1_pads[] = {
MX6_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_UART1_RTS_B__USDHC1_CD_B | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};
#ifndef CONFIG_NAND_MXS
static iomux_v3_cfg_t const usdhc2_pads[] = {
MX6_PAD_NAND_RE_B__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_WE_B__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_DATA00__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_DATA01__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_DATA02__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_DATA03__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_DATA04__USDHC2_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_DATA05__USDHC2_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_DATA06__USDHC2_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
MX6_PAD_NAND_DATA07__USDHC2_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};
#endif
static struct fsl_esdhc_cfg usdhc_cfg[] = {
{
.esdhc_base = USDHC1_BASE_ADDR,
.max_bus_width = 4,
},
#ifndef CONFIG_NAND_MXS
{
.esdhc_base = USDHC2_BASE_ADDR,
.max_bus_width = 8,
},
#endif
};
int board_mmc_getcd(struct mmc *mmc)
{
return 1;
}
int board_mmc_init(struct bd_info *bis)
{
int i, ret;
for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
switch (i) {
case 0:
SETUP_IOMUX_PADS(usdhc1_pads);
usdhc_cfg[i].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
break;
#ifndef CONFIG_NAND_MXS
case 1:
SETUP_IOMUX_PADS(usdhc2_pads);
usdhc_cfg[i].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
break;
#endif
default:
printf("Warning - USDHC%d controller not supporting\n",
i + 1);
return 0;
}
ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
if (ret) {
printf("Warning: failed to initialize mmc dev %d\n", i);
return ret;
}
}
return 0;
}
#endif /* CONFIG_FSL_ESDHC_IMX */
void board_init_f(ulong dummy)
{
ccgr_init();
/* Setup AIPS and disable watchdog */
arch_cpu_init();
/* Setup iomux and fec */
board_early_init_f();
/* Setup GP timer */
timer_init();
/* UART clocks enabled and gd valid - init serial console */
preloader_console_init();
/* DDR initialization */
spl_dram_init();
}

View File

@@ -61,17 +61,21 @@ Then, clear the SPI flash:
=> sf probe
=> sf erase 0x0 0x1000000
Load the SPL from raw MMC into memory and copy to the SPI. The SPL is maximum
392*512-byte blocks in size therefore 0x188 blocks, totaling 0x31000 bytes:
Load the equivalent of u-boot-with-spl.imx from the raw MMC into memory and
copy to the SPI. The SPL is expected at an offset of 0x400, and its size is
maximum 392*512-byte blocks in size, therefore 0x188 blocks, totaling 0x31000
bytes. Assume U-boot should fit into 640KiB, therefore 0x500 512-byte blocks,
totalling 0xA0000 bytes. Adding these together:
=> mmc read ${loadaddr} 0x2 0x188
=> sf write ${loadaddr} 0x400 0x31000
=> mmc read ${loadaddr} 0x2 0x688
=> sf write ${loadaddr} 0x400 0xD1000
Load the U-boot binary into memory and copy to the SPI. U-boot should fit into
640KiB, so 0x500 512-byte blocks, totalling 0xA0000 bytes:
The SPL is located at offset 0x400, and U-boot at 0x31400 in SPI flash, as to
match the SD Card layout. This would allow, instead of reading from the SD Card
above, with networking and TFTP correctly configured, the equivalent of:
=> mmc read ${loadaddr} 0x18a 0x500
=> sf write ${loadaddr} 0x40000 0xA0000
=> tftp u-boot-with-spl.imx
=> sf write ${fileaddr} 0x400 ${filesize}
The default NAND bootscripts expect a single MTD partition named "rootfs",
which in turn contains the UBI volumes "fit" (which contains the kernel fit-

View File

@@ -57,32 +57,7 @@ static void setup_gpmi_nand(void)
}
#endif /* CONFIG_NAND_MXS */
#ifdef CONFIG_VIDEO_MXS
static iomux_v3_cfg_t const lcd_pads[] = {
MX6_PAD_LCD_CLK__LCDIF_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_ENABLE__LCDIF_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_HSYNC__LCDIF_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_CLK__LCDIF_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA00__LCDIF_DATA00 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA01__LCDIF_DATA01 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA02__LCDIF_DATA02 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA03__LCDIF_DATA03 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA04__LCDIF_DATA04 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA05__LCDIF_DATA05 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA06__LCDIF_DATA06 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA07__LCDIF_DATA07 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA08__LCDIF_DATA08 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA09__LCDIF_DATA09 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA10__LCDIF_DATA10 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA11__LCDIF_DATA11 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA12__LCDIF_DATA12 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA13__LCDIF_DATA13 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA14__LCDIF_DATA14 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA15__LCDIF_DATA15 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA16__LCDIF_DATA16 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX6_PAD_LCD_DATA17__LCDIF_DATA17 | MUX_PAD_CTRL(LCD_PAD_CTRL),
};
#ifdef CONFIG_DM_VIDEO
static iomux_v3_cfg_t const backlight_pads[] = {
/* Backlight On */
MX6_PAD_JTAG_TMS__GPIO1_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL),
@@ -95,8 +70,6 @@ static iomux_v3_cfg_t const backlight_pads[] = {
static int setup_lcd(void)
{
imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
imx_iomux_v3_setup_multiple_pads(backlight_pads, ARRAY_SIZE(backlight_pads));
/* Set BL_ON */
@@ -153,11 +126,6 @@ int board_init(void)
#ifdef CONFIG_NAND_MXS
setup_gpmi_nand();
#endif
#ifdef CONFIG_VIDEO_MXS
setup_lcd();
#endif
return 0;
}
@@ -203,6 +171,12 @@ int board_late_init(void)
}
#endif /* CONFIG_CMD_USB_SDP */
#if defined(CONFIG_DM_VIDEO)
setup_lcd();
show_boot_logo();
#endif
return 0;
}

View File

@@ -9,5 +9,6 @@ F: include/configs/colibri_imx7.h
F: configs/colibri_imx7_defconfig
F: configs/colibri_imx7_emmc_defconfig
F: arch/arm/dts/imx7-colibri.dtsi
F: arch/arm/dts/imx7-colibri-u-boot.dtsi
F: arch/arm/dts/imx7-colibri-emmc.dts
F: arch/arm/dts/imx7-colibri-rawnand.dts

View File

@@ -100,32 +100,7 @@ static void setup_gpmi_nand(void)
}
#endif
#ifdef CONFIG_VIDEO_MXS
static iomux_v3_cfg_t const lcd_pads[] = {
MX7D_PAD_LCD_CLK__LCD_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_ENABLE__LCD_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_HSYNC__LCD_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_VSYNC__LCD_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA00__LCD_DATA0 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA01__LCD_DATA1 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA02__LCD_DATA2 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA03__LCD_DATA3 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA04__LCD_DATA4 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA05__LCD_DATA5 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA06__LCD_DATA6 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA07__LCD_DATA7 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA08__LCD_DATA8 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA09__LCD_DATA9 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA10__LCD_DATA10 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA11__LCD_DATA11 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA12__LCD_DATA12 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA13__LCD_DATA13 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA14__LCD_DATA14 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA15__LCD_DATA15 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA16__LCD_DATA16 | MUX_PAD_CTRL(LCD_PAD_CTRL),
MX7D_PAD_LCD_DATA17__LCD_DATA17 | MUX_PAD_CTRL(LCD_PAD_CTRL),
};
#ifdef CONFIG_DM_VIDEO
static iomux_v3_cfg_t const backlight_pads[] = {
/* Backlight On */
MX7D_PAD_SD1_WP__GPIO5_IO1 | MUX_PAD_CTRL(NO_PAD_CTRL),
@@ -139,8 +114,6 @@ static iomux_v3_cfg_t const backlight_pads[] = {
static int setup_lcd(void)
{
imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads));
imx_iomux_v3_setup_multiple_pads(backlight_pads, ARRAY_SIZE(backlight_pads));
/* Set BL_ON */
@@ -215,10 +188,6 @@ int board_init(void)
setup_gpmi_nand();
#endif
#ifdef CONFIG_VIDEO_MXS
setup_lcd();
#endif
#ifdef CONFIG_USB_EHCI_MX7
imx_iomux_v3_setup_multiple_pads(usb_cdet_pads, ARRAY_SIZE(usb_cdet_pads));
gpio_request(USB_CDET_GPIO, "usb-cdet-gpio");
@@ -382,4 +351,15 @@ int board_usb_phy_mode(int port)
return USB_INIT_HOST;
}
}
int board_late_init(void)
{
#if defined(CONFIG_DM_VIDEO)
setup_lcd();
show_boot_logo();
#endif
return 0;
}
#endif

View File

@@ -20,6 +20,12 @@ config TDX_HAVE_NAND
config TDX_HAVE_NOR
bool
config TDX_HAVE_EEPROM
bool
config TDX_HAVE_EEPROM_EXTRA
bool
if TDX_CFG_BLOCK
config TDX_CFG_BLOCK_IS_IN_MMC
@@ -37,6 +43,11 @@ config TDX_CFG_BLOCK_IS_IN_NOR
depends on TDX_HAVE_NOR
default y
config TDX_CFG_BLOCK_IS_IN_EEPROM
bool
depends on TDX_HAVE_EEPROM
default y
config TDX_CFG_BLOCK_DEV
int "Toradex config block eMMC device ID"
depends on TDX_CFG_BLOCK_IS_IN_MMC
@@ -66,4 +77,11 @@ config TDX_CFG_BLOCK_2ND_ETHADDR
Ethernet carrier boards. This options enables the code to set the
second Ethernet address as environment variable (eth1addr).
config TDX_CFG_BLOCK_EXTRA
bool "Support for additional EEPROMs (carrier board, display adapter)"
depends on TDX_HAVE_EEPROM_EXTRA
help
Enables fetching auxilary config blocks from carrier board/display
adapter EEPROMs.
endif

View File

@@ -8,4 +8,5 @@ obj- := __dummy__.o
else
obj-$(CONFIG_TDX_CFG_BLOCK) += tdx-cfg-block.o
obj-y += tdx-common.o
obj-y += tdx-eeprom.o
endif

View File

@@ -5,6 +5,8 @@
#include <common.h>
#include "tdx-cfg-block.h"
#include "tdx-eeprom.h"
#include <command.h>
#include <asm/cache.h>
@@ -37,21 +39,31 @@ DECLARE_GLOBAL_DATA_PTR;
#define TAG_VALID 0xcf01
#define TAG_MAC 0x0000
#define TAG_CAR_SERIAL 0x0021
#define TAG_HW 0x0008
#define TAG_INVALID 0xffff
#define TAG_FLAG_VALID 0x1
#define TDX_EEPROM_ID_MODULE 0
#define TDX_EEPROM_ID_CARRIER 1
#if defined(CONFIG_TDX_CFG_BLOCK_IS_IN_MMC)
#define TDX_CFG_BLOCK_MAX_SIZE 512
#elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_NAND)
#define TDX_CFG_BLOCK_MAX_SIZE 64
#elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_NOR)
#define TDX_CFG_BLOCK_MAX_SIZE 64
#elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_EEPROM)
#define TDX_CFG_BLOCK_MAX_SIZE 64
#else
#error Toradex config block location not set
#endif
#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
#define TDX_CFG_BLOCK_EXTRA_MAX_SIZE 64
#endif
struct toradex_tag {
u32 len:14;
u32 flags:2;
@@ -62,6 +74,11 @@ bool valid_cfgblock;
struct toradex_hw tdx_hw_tag;
struct toradex_eth_addr tdx_eth_addr;
u32 tdx_serial;
#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
u32 tdx_car_serial;
bool valid_cfgblock_carrier;
struct toradex_hw tdx_car_hw_tag;
#endif
const char * const toradex_modules[] = {
[0] = "UNKNOWN MODULE",
@@ -124,6 +141,18 @@ const char * const toradex_modules[] = {
[57] = "Verdin iMX8M Mini DualLite 1GB",
};
const char * const toradex_carrier_boards[] = {
[0] = "UNKNOWN CARRIER BOARD",
[155] = "Dahlia",
[156] = "Verdin Development Board",
};
const char * const toradex_display_adapters[] = {
[0] = "UNKNOWN DISPLAY ADAPTER",
[157] = "Verdin DSI to HDMI Adapter",
[159] = "Verdin DSI to LVDS Adapter",
};
#ifdef CONFIG_TDX_CFG_BLOCK_IS_IN_MMC
static int tdx_cfg_block_mmc_storage(u8 *config_block, int write)
{
@@ -224,6 +253,20 @@ static int write_tdx_cfg_block_to_nor(unsigned char *config_block)
}
#endif
#ifdef CONFIG_TDX_CFG_BLOCK_IS_IN_EEPROM
static int read_tdx_cfg_block_from_eeprom(unsigned char *config_block)
{
return read_tdx_eeprom_data(TDX_EEPROM_ID_MODULE, 0x0, config_block,
TDX_CFG_BLOCK_MAX_SIZE);
}
static int write_tdx_cfg_block_to_eeprom(unsigned char *config_block)
{
return write_tdx_eeprom_data(TDX_EEPROM_ID_MODULE, 0x0, config_block,
TDX_CFG_BLOCK_MAX_SIZE);
}
#endif
int read_tdx_cfg_block(void)
{
int ret = 0;
@@ -247,6 +290,8 @@ int read_tdx_cfg_block(void)
ret = read_tdx_cfg_block_from_nand(config_block);
#elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_NOR)
ret = read_tdx_cfg_block_from_nor(config_block);
#elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_EEPROM)
ret = read_tdx_cfg_block_from_eeprom(config_block);
#else
ret = -EINVAL;
#endif
@@ -263,7 +308,12 @@ int read_tdx_cfg_block(void)
valid_cfgblock = true;
offset = 4;
while (offset < TDX_CFG_BLOCK_MAX_SIZE) {
/*
* check if there is enough space for storing tag and value of the
* biggest element
*/
while (offset + sizeof(struct toradex_tag) +
sizeof(struct toradex_hw) < TDX_CFG_BLOCK_MAX_SIZE) {
tag = (struct toradex_tag *)(config_block + offset);
offset += 4;
if (tag->id == TAG_INVALID)
@@ -322,7 +372,6 @@ static int get_cfgblock_interactive(void)
it = 'y';
#endif
#if defined(CONFIG_TARGET_APALIS_IMX8) || \
defined(CONFIG_TARGET_APALIS_IMX8X) || \
defined(CONFIG_TARGET_COLIBRI_IMX6ULL) || \
@@ -493,7 +542,8 @@ static int get_cfgblock_interactive(void)
return 0;
}
static int get_cfgblock_barcode(char *barcode)
static int get_cfgblock_barcode(char *barcode, struct toradex_hw *tag,
u32 *serial)
{
if (strlen(barcode) < 16) {
printf("Argument too short, barcode is 16 chars long\n");
@@ -501,30 +551,137 @@ static int get_cfgblock_barcode(char *barcode)
}
/* Get hardware information from the first 8 digits */
tdx_hw_tag.ver_major = barcode[4] - '0';
tdx_hw_tag.ver_minor = barcode[5] - '0';
tdx_hw_tag.ver_assembly = barcode[7] - '0';
tag->ver_major = barcode[4] - '0';
tag->ver_minor = barcode[5] - '0';
tag->ver_assembly = barcode[7] - '0';
barcode[4] = '\0';
tdx_hw_tag.prodid = simple_strtoul(barcode, NULL, 10);
tag->prodid = simple_strtoul(barcode, NULL, 10);
/* Parse second part of the barcode (serial number */
barcode += 8;
tdx_serial = simple_strtoul(barcode, NULL, 10);
*serial = simple_strtoul(barcode, NULL, 10);
return 0;
}
static int do_cfgblock_create(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
static int write_tag(u8 *config_block, int *offset, int tag_id,
u8 *tag_data, size_t tag_data_size)
{
u8 *config_block;
struct toradex_tag *tag;
size_t size = TDX_CFG_BLOCK_MAX_SIZE;
if (!offset || !config_block)
return -EINVAL;
tag = (struct toradex_tag *)(config_block + *offset);
tag->id = tag_id;
tag->flags = TAG_FLAG_VALID;
/* len is provided as number of 32bit values after the tag */
tag->len = (tag_data_size + sizeof(u32) - 1) / sizeof(u32);
*offset += sizeof(struct toradex_tag);
if (tag_data && tag_data_size) {
memcpy(config_block + *offset, tag_data,
tag_data_size);
*offset += tag_data_size;
}
return 0;
}
#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
int read_tdx_cfg_block_carrier(void)
{
int ret = 0;
u8 *config_block = NULL;
struct toradex_tag *tag;
size_t size = TDX_CFG_BLOCK_EXTRA_MAX_SIZE;
int offset;
/* Allocate RAM area for carrier config block */
config_block = memalign(ARCH_DMA_MINALIGN, size);
if (!config_block) {
printf("Not enough malloc space available!\n");
return -ENOMEM;
}
memset(config_block, 0, size);
ret = read_tdx_eeprom_data(TDX_EEPROM_ID_CARRIER, 0x0, config_block,
size);
if (ret)
return ret;
/* Expect a valid tag first */
tag = (struct toradex_tag *)config_block;
if (tag->flags != TAG_FLAG_VALID || tag->id != TAG_VALID) {
valid_cfgblock_carrier = false;
ret = -EINVAL;
goto out;
}
valid_cfgblock_carrier = true;
offset = 4;
while (offset + sizeof(struct toradex_tag) +
sizeof(struct toradex_hw) < TDX_CFG_BLOCK_MAX_SIZE) {
tag = (struct toradex_tag *)(config_block + offset);
offset += 4;
if (tag->id == TAG_INVALID)
break;
if (tag->flags == TAG_FLAG_VALID) {
switch (tag->id) {
case TAG_CAR_SERIAL:
memcpy(&tdx_car_serial, config_block + offset,
sizeof(tdx_car_serial));
break;
case TAG_HW:
memcpy(&tdx_car_hw_tag, config_block +
offset, 8);
break;
}
}
/* Get to next tag according to current tags length */
offset += tag->len * 4;
}
out:
free(config_block);
return ret;
}
int check_pid8_sanity(char *pid8)
{
char s_carrierid_verdin_dev[5];
char s_carrierid_dahlia[5];
sprintf(s_carrierid_verdin_dev, "0%d", VERDIN_DEVELOPMENT_BOARD);
sprintf(s_carrierid_dahlia, "0%d", DAHLIA);
/* sane value check, first 4 chars which represent carrier id */
if (!strncmp(pid8, s_carrierid_verdin_dev, 4))
return 0;
if (!strncmp(pid8, s_carrierid_dahlia, 4))
return 0;
return -EINVAL;
}
int try_migrate_tdx_cfg_block_carrier(void)
{
char pid8[8];
int offset = 0;
int ret = CMD_RET_SUCCESS;
int err;
int force_overwrite = 0;
size_t size = TDX_CFG_BLOCK_EXTRA_MAX_SIZE;
u8 *config_block;
memset(pid8, 0x0, 8);
ret = read_tdx_eeprom_data(TDX_EEPROM_ID_CARRIER, 0x0, (u8 *)pid8, 8);
if (ret)
return ret;
if (check_pid8_sanity(pid8))
return -EINVAL;
/* Allocate RAM area for config block */
config_block = memalign(ARCH_DMA_MINALIGN, size);
@@ -534,12 +691,189 @@ static int do_cfgblock_create(struct cmd_tbl *cmdtp, int flag, int argc,
}
memset(config_block, 0xff, size);
/* we try parse PID8 concatenating zeroed serial number */
tdx_car_hw_tag.ver_major = pid8[4] - '0';
tdx_car_hw_tag.ver_minor = pid8[5] - '0';
tdx_car_hw_tag.ver_assembly = pid8[7] - '0';
pid8[4] = '\0';
tdx_car_hw_tag.prodid = simple_strtoul(pid8, NULL, 10);
/* Valid Tag */
write_tag(config_block, &offset, TAG_VALID, NULL, 0);
/* Product Tag */
write_tag(config_block, &offset, TAG_HW, (u8 *)&tdx_car_hw_tag,
sizeof(tdx_car_hw_tag));
/* Serial Tag */
write_tag(config_block, &offset, TAG_CAR_SERIAL, (u8 *)&tdx_car_serial,
sizeof(tdx_car_serial));
memset(config_block + offset, 0, 32 - offset);
ret = write_tdx_eeprom_data(TDX_EEPROM_ID_CARRIER, 0x0, config_block,
size);
if (ret) {
printf("Failed to write Toradex Extra config block: %d\n",
ret);
ret = CMD_RET_FAILURE;
goto out;
}
printf("Successfully migrated to Toradex Config Block from PID8\n");
out:
free(config_block);
return ret;
}
static int get_cfgblock_carrier_interactive(void)
{
char message[CONFIG_SYS_CBSIZE];
int len;
printf("Supported carrier boards:\n");
printf("CARRIER BOARD NAME\t\t [ID]\n");
for (int i = 0; i < sizeof(toradex_carrier_boards) /
sizeof(toradex_carrier_boards[0]); i++)
if (toradex_carrier_boards[i])
printf("%s \t\t [%d]\n", toradex_carrier_boards[i], i);
sprintf(message, "Choose your carrier board (provide ID): ");
len = cli_readline(message);
tdx_car_hw_tag.prodid = simple_strtoul(console_buffer, NULL, 10);
do {
sprintf(message, "Enter carrier board version (e.g. V1.1B): V");
len = cli_readline(message);
} while (len < 4);
tdx_car_hw_tag.ver_major = console_buffer[0] - '0';
tdx_car_hw_tag.ver_minor = console_buffer[2] - '0';
tdx_car_hw_tag.ver_assembly = console_buffer[3] - 'A';
while (len < 8) {
sprintf(message, "Enter carrier board serial number: ");
len = cli_readline(message);
}
tdx_car_serial = simple_strtoul(console_buffer, NULL, 10);
return 0;
}
static int do_cfgblock_carrier_create(struct cmd_tbl *cmdtp, int flag, int argc,
char * const argv[])
{
u8 *config_block;
size_t size = TDX_CFG_BLOCK_EXTRA_MAX_SIZE;
int offset = 0;
int ret = CMD_RET_SUCCESS;
int err;
int force_overwrite = 0;
if (argc >= 3) {
if (argv[2][0] == '-' && argv[2][1] == 'y')
force_overwrite = 1;
}
/* Allocate RAM area for config block */
config_block = memalign(ARCH_DMA_MINALIGN, size);
if (!config_block) {
printf("Not enough malloc space available!\n");
return CMD_RET_FAILURE;
}
memset(config_block, 0xff, size);
read_tdx_cfg_block_carrier();
if (valid_cfgblock_carrier && !force_overwrite) {
char message[CONFIG_SYS_CBSIZE];
sprintf(message, "A valid Toradex Carrier config block is present, still recreate? [y/N] ");
if (!cli_readline(message))
goto out;
if (console_buffer[0] != 'y' &&
console_buffer[0] != 'Y')
goto out;
}
if (argc < 3 || (force_overwrite && argc < 4)) {
err = get_cfgblock_carrier_interactive();
} else {
if (force_overwrite)
err = get_cfgblock_barcode(argv[3], &tdx_car_hw_tag,
&tdx_car_serial);
else
err = get_cfgblock_barcode(argv[2], &tdx_car_hw_tag,
&tdx_car_serial);
}
if (err) {
ret = CMD_RET_FAILURE;
goto out;
}
/* Valid Tag */
write_tag(config_block, &offset, TAG_VALID, NULL, 0);
/* Product Tag */
write_tag(config_block, &offset, TAG_HW, (u8 *)&tdx_car_hw_tag,
sizeof(tdx_car_hw_tag));
/* Serial Tag */
write_tag(config_block, &offset, TAG_CAR_SERIAL, (u8 *)&tdx_car_serial,
sizeof(tdx_car_serial));
memset(config_block + offset, 0, 32 - offset);
err = write_tdx_eeprom_data(TDX_EEPROM_ID_CARRIER, 0x0, config_block,
size);
if (err) {
printf("Failed to write Toradex Extra config block: %d\n",
ret);
ret = CMD_RET_FAILURE;
goto out;
}
printf("Toradex Extra config block successfully written\n");
out:
free(config_block);
return ret;
}
#endif /* CONFIG_TDX_CFG_BLOCK_EXTRA */
static int do_cfgblock_create(struct cmd_tbl *cmdtp, int flag, int argc,
char * const argv[])
{
u8 *config_block;
size_t size = TDX_CFG_BLOCK_MAX_SIZE;
int offset = 0;
int ret = CMD_RET_SUCCESS;
int err;
int force_overwrite = 0;
if (argc >= 3) {
#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
if (!strcmp(argv[2], "carrier"))
return do_cfgblock_carrier_create(cmdtp, flag,
--argc, ++argv);
#endif /* CONFIG_TDX_CFG_BLOCK_EXTRA */
if (argv[2][0] == '-' && argv[2][1] == 'y')
force_overwrite = 1;
}
/* Allocate RAM area for config block */
config_block = memalign(ARCH_DMA_MINALIGN, size);
if (!config_block) {
printf("Not enough malloc space available!\n");
return CMD_RET_FAILURE;
}
memset(config_block, 0xff, size);
read_tdx_cfg_block();
if (valid_cfgblock) {
#if defined(CONFIG_TDX_CFG_BLOCK_IS_IN_NAND)
@@ -581,9 +915,11 @@ static int do_cfgblock_create(struct cmd_tbl *cmdtp, int flag, int argc,
err = get_cfgblock_interactive();
} else {
if (force_overwrite)
err = get_cfgblock_barcode(argv[3]);
err = get_cfgblock_barcode(argv[3], &tdx_hw_tag,
&tdx_serial);
else
err = get_cfgblock_barcode(argv[2]);
err = get_cfgblock_barcode(argv[2], &tdx_hw_tag,
&tdx_serial);
}
if (err) {
ret = CMD_RET_FAILURE;
@@ -595,39 +931,25 @@ static int do_cfgblock_create(struct cmd_tbl *cmdtp, int flag, int argc,
tdx_eth_addr.nic = htonl(tdx_serial << 8);
/* Valid Tag */
tag = (struct toradex_tag *)config_block;
tag->id = TAG_VALID;
tag->flags = TAG_FLAG_VALID;
tag->len = 0;
offset += 4;
write_tag(config_block, &offset, TAG_VALID, NULL, 0);
/* Product Tag */
tag = (struct toradex_tag *)(config_block + offset);
tag->id = TAG_HW;
tag->flags = TAG_FLAG_VALID;
tag->len = 2;
offset += 4;
memcpy(config_block + offset, &tdx_hw_tag, 8);
offset += 8;
write_tag(config_block, &offset, TAG_HW, (u8 *)&tdx_hw_tag,
sizeof(tdx_hw_tag));
/* MAC Tag */
tag = (struct toradex_tag *)(config_block + offset);
tag->id = TAG_MAC;
tag->flags = TAG_FLAG_VALID;
tag->len = 2;
offset += 4;
write_tag(config_block, &offset, TAG_MAC, (u8 *)&tdx_eth_addr,
sizeof(tdx_eth_addr));
memcpy(config_block + offset, &tdx_eth_addr, 6);
offset += 6;
memset(config_block + offset, 0, 32 - offset);
#if defined(CONFIG_TDX_CFG_BLOCK_IS_IN_MMC)
err = tdx_cfg_block_mmc_storage(config_block, 1);
#elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_NAND)
err = write_tdx_cfg_block_to_nand(config_block);
#elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_NOR)
err = write_tdx_cfg_block_to_nor(config_block);
#elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_EEPROM)
err = write_tdx_cfg_block_to_eeprom(config_block);
#else
err = -EINVAL;
#endif
@@ -667,8 +989,10 @@ static int do_cfgblock(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_USAGE;
}
U_BOOT_CMD(cfgblock, 4, 0, do_cfgblock,
"Toradex config block handling commands",
"create [-y] [barcode] - (Re-)create Toradex config block\n"
"cfgblock reload - Reload Toradex config block from flash"
U_BOOT_CMD(
cfgblock, 5, 0, do_cfgblock,
"Toradex config block handling commands",
"create [-y] [barcode] - (Re-)create Toradex config block\n"
"create carrier [-y] [barcode] - (Re-)create Toradex Carrier config block\n"
"cfgblock reload - Reload Toradex config block from flash"
);

View File

@@ -80,12 +80,28 @@ enum {
VERDIN_IMX8MMDL,
};
enum {
DAHLIA = 155,
VERDIN_DEVELOPMENT_BOARD = 156,
};
enum {
VERDIN_DSI_TO_HDMI_ADAPTER = 157,
VERDIN_DSI_TO_LVDS_ADAPTER = 159,
};
extern const char * const toradex_modules[];
extern const char * const toradex_carrier_boards[];
extern bool valid_cfgblock;
extern struct toradex_hw tdx_hw_tag;
extern struct toradex_hw tdx_car_hw_tag;
extern struct toradex_eth_addr tdx_eth_addr;
extern u32 tdx_serial;
extern u32 tdx_car_serial;
int read_tdx_cfg_block(void);
int read_tdx_cfg_block_carrier(void);
int try_migrate_tdx_cfg_block_carrier(void);
#endif /* _TDX_CFG_BLOCK_H */

View File

@@ -9,6 +9,13 @@
#include <init.h>
#include <linux/libfdt.h>
#ifdef CONFIG_DM_VIDEO
#include <bmp_logo.h>
#include <dm.h>
#include <splash.h>
#include <video.h>
#endif
#include "tdx-cfg-block.h"
#include <asm/setup.h>
#include "tdx-common.h"
@@ -19,6 +26,12 @@
static char tdx_serial_str[9];
static char tdx_board_rev_str[6];
#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
static char tdx_car_serial_str[9];
static char tdx_car_rev_str[6];
static char *tdx_carrier_board_name;
#endif
#ifdef CONFIG_REVISION_TAG
u32 get_board_rev(void)
{
@@ -88,6 +101,28 @@ int show_board_info(void)
toradex_modules[tdx_hw_tag.prodid],
tdx_board_rev_str,
tdx_serial_str);
#ifdef CONFIG_TDX_CFG_BLOCK_EXTRA
if (read_tdx_cfg_block_carrier()) {
printf("MISSING TORADEX CARRIER CONFIG BLOCKS\n");
try_migrate_tdx_cfg_block_carrier();
} else {
tdx_carrier_board_name = (char *)
toradex_carrier_boards[tdx_car_hw_tag.prodid];
sprintf(tdx_car_serial_str, "%08u", tdx_car_serial);
sprintf(tdx_car_rev_str, "V%1d.%1d%c",
tdx_car_hw_tag.ver_major,
tdx_car_hw_tag.ver_minor,
(char)tdx_car_hw_tag.ver_assembly +
'A');
env_set("carrier_serial#", tdx_car_serial_str);
printf("Carrier: Toradex %s %s, Serial# %s\n",
tdx_carrier_board_name,
tdx_car_rev_str,
tdx_car_serial_str);
}
#endif
}
/*
@@ -168,3 +203,22 @@ int ft_common_board_setup(void *blob, struct bd_info *bd)
}
#endif /* CONFIG_TDX_CFG_BLOCK */
#if defined(CONFIG_DM_VIDEO)
int show_boot_logo(void)
{
struct udevice *dev;
int ret;
int xpos, ypos;
splash_get_pos(&xpos, &ypos);
ret = uclass_get_device(UCLASS_VIDEO, 0, &dev);
if (ret)
return ret;
ret = video_bmp_display(dev, (ulong)bmp_logo_bitmap, xpos, ypos, true);
return ret;
}
#endif /* CONFIG_DM_VIDEO */

View File

@@ -11,4 +11,8 @@
int ft_common_board_setup(void *blob, struct bd_info *bd);
#if defined(CONFIG_DM_VIDEO)
int show_boot_logo(void);
#endif
#endif /* _TDX_COMMON_H */

View File

@@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2020 Toradex
*/
#include <dm.h>
#include <i2c_eeprom.h>
#include <linux/errno.h>
DECLARE_GLOBAL_DATA_PTR;
static int get_tdx_eeprom(u32 eeprom_id, struct udevice **devp)
{
int ret = 0;
int node;
ofnode eeprom;
char eeprom_str[16];
const char *path;
if (!gd->fdt_blob) {
printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
return -EFAULT;
}
node = fdt_path_offset(gd->fdt_blob, "/aliases");
if (node < 0)
return -ENODEV;
sprintf(eeprom_str, "eeprom%d", eeprom_id);
path = fdt_getprop(gd->fdt_blob, node, eeprom_str, NULL);
if (!path) {
printf("%s: no alias for %s\n", __func__, eeprom_str);
return -ENODEV;
}
eeprom = ofnode_path(path);
if (!ofnode_valid(eeprom)) {
printf("%s: invalid hardware path to EEPROM\n", __func__);
return -ENODEV;
}
ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, devp);
if (ret) {
printf("%s: cannot find EEPROM by node\n", __func__);
return ret;
}
return ret;
}
int read_tdx_eeprom_data(u32 eeprom_id, int offset, u8 *buf,
int size)
{
struct udevice *dev;
int ret;
ret = get_tdx_eeprom(eeprom_id, &dev);
if (ret)
return ret;
ret = i2c_eeprom_read(dev, 0x0, buf, size);
if (ret) {
printf("%s: error reading data from EEPROM id: %d!, ret = %d\n",
__func__, eeprom_id, ret);
return ret;
}
return ret;
}
int write_tdx_eeprom_data(u32 eeprom_id, int offset, u8 *buf,
int size)
{
struct udevice *dev;
int ret;
ret = get_tdx_eeprom(eeprom_id, &dev);
if (ret)
return ret;
ret = i2c_eeprom_write(dev, 0x0, buf, size);
if (ret) {
printf("%s: error writing data to EEPROM id: %d, ret = %d\n",
__func__, eeprom_id, ret);
return ret;
}
return ret;
}

View File

@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2020 Toradex
*/
#ifndef _TDX_EEPROM_H
#define _TDX_EEPROM_H
#include <i2c_eeprom.h>
int read_tdx_eeprom_data(u32 eeprom_id, int offset, uint8_t *buf, int size);
int write_tdx_eeprom_data(u32 eeprom_id, int offset, uint8_t *buf, int size);
#endif /* _TDX_EEPROM_H */

View File

@@ -12,9 +12,15 @@ config SYS_CONFIG_NAME
config TDX_CFG_BLOCK
default y
config TDX_CFG_BLOCK_EXTRA
default y
config TDX_HAVE_MMC
default y
config TDX_HAVE_EEPROM_EXTRA
default y
config TDX_CFG_BLOCK_DEV
default "0"