diff options
Diffstat (limited to 'board')
28 files changed, 1294 insertions, 621 deletions
diff --git a/board/amarula/vyasa-rk3288/vyasa-rk3288.c b/board/amarula/vyasa-rk3288/vyasa-rk3288.c index 2b509f529f1..baf197c4851 100644 --- a/board/amarula/vyasa-rk3288/vyasa-rk3288.c +++ b/board/amarula/vyasa-rk3288/vyasa-rk3288.c @@ -6,14 +6,6 @@ #include <common.h> #ifndef CONFIG_TPL_BUILD -#include <spl.h> - -void board_boot_order(u32 *spl_boot_list) -{ - /* eMMC prior to sdcard. */ - spl_boot_list[0] = BOOT_DEVICE_MMC2; - spl_boot_list[1] = BOOT_DEVICE_MMC1; -} int spl_start_uboot(void) { diff --git a/board/chipspark/popmetal_rk3288/popmetal-rk3288.c b/board/chipspark/popmetal_rk3288/popmetal-rk3288.c index 355c78b7b73..9ba1fbd0e27 100644 --- a/board/chipspark/popmetal_rk3288/popmetal-rk3288.c +++ b/board/chipspark/popmetal_rk3288/popmetal-rk3288.c @@ -4,16 +4,8 @@ */ #include <common.h> -#include <spl.h> #include <asm/gpio.h> -void board_boot_order(u32 *spl_boot_list) -{ - /* eMMC prior to sdcard */ - spl_boot_list[0] = BOOT_DEVICE_MMC2; - spl_boot_list[1] = BOOT_DEVICE_MMC1; -} - #define GPIO7A3_HUB_RST 227 int rk_board_late_init(void) diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c index 5180128db46..43483d526ad 100644 --- a/board/davinci/da8xxevm/da850evm.c +++ b/board/davinci/da8xxevm/da850evm.c @@ -13,7 +13,6 @@ #include <environment.h> #include <i2c.h> #include <net.h> -#include <netdev.h> #include <spi.h> #include <spi_flash.h> #include <asm/arch/hardware.h> @@ -482,11 +481,6 @@ int board_eth_init(bd_t *bis) if (rmii_hw_init()) printf("RMII hardware init failed!!!\n"); #endif - if (!davinci_emac_initialize()) { - printf("Error: Ethernet init failed!\n"); - return -1; - } - return 0; } #endif /* CONFIG_DRIVER_TI_EMAC */ diff --git a/board/davinci/da8xxevm/omapl138_lcdk.c b/board/davinci/da8xxevm/omapl138_lcdk.c index fe1bf441014..dd115514283 100644 --- a/board/davinci/da8xxevm/omapl138_lcdk.c +++ b/board/davinci/da8xxevm/omapl138_lcdk.c @@ -11,7 +11,6 @@ #include <common.h> #include <i2c.h> #include <net.h> -#include <netdev.h> #include <spi.h> #include <spi_flash.h> #include <asm/arch/hardware.h> @@ -229,19 +228,6 @@ int board_init(void) #ifdef CONFIG_DRIVER_TI_EMAC -/* - * Initializes on-board ethernet controllers. - */ -int board_eth_init(bd_t *bis) -{ - if (!davinci_emac_initialize()) { - printf("Error: Ethernet init failed!\n"); - return -1; - } - - return 0; -} - #endif /* CONFIG_DRIVER_TI_EMAC */ #define CFG_MAC_ADDR_SPI_BUS 0 diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig index 7f9a74dd48e..6cc7c31dc65 100644 --- a/board/emulation/qemu-riscv/Kconfig +++ b/board/emulation/qemu-riscv/Kconfig @@ -24,6 +24,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply VIRTIO_MMIO imply VIRTIO_NET imply VIRTIO_BLK + imply VIRTIO_PCI imply CMD_PING imply CMD_FS_GENERIC imply DOS_PARTITION diff --git a/board/freescale/ls1021atsn/Kconfig b/board/freescale/ls1021atsn/Kconfig new file mode 100644 index 00000000000..d999fa46900 --- /dev/null +++ b/board/freescale/ls1021atsn/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +if TARGET_LS1021ATSN + +config SYS_BOARD + default "ls1021atsn" + +config SYS_VENDOR + default "freescale" + +config SYS_SOC + default "ls102xa" + +config SYS_CONFIG_NAME + default "ls1021atsn" + +source "board/freescale/common/Kconfig" + +endif diff --git a/board/freescale/ls1021atsn/MAINTAINERS b/board/freescale/ls1021atsn/MAINTAINERS new file mode 100644 index 00000000000..560bb615d2f --- /dev/null +++ b/board/freescale/ls1021atsn/MAINTAINERS @@ -0,0 +1,8 @@ +NXP LS1021A-TSN Board +M: Vladimir Oltean <olteanv@gmail.com> +S: Maintained +F: arch/arm/dts/ls1021a-tsn.dts +F: board/freescale/ls1021atsn/ +F: include/configs/ls1021atsn.h +F: configs/ls1021atsn_qspi_defconfig +F: configs/ls1021atsn_sdcard_defconfig diff --git a/board/freescale/ls1021atsn/Makefile b/board/freescale/ls1021atsn/Makefile new file mode 100644 index 00000000000..b4808f05e8e --- /dev/null +++ b/board/freescale/ls1021atsn/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-y += ls1021atsn.o +obj-$(CONFIG_ARMV7_PSCI) += ../ls1021atwr/psci.o diff --git a/board/freescale/ls1021atsn/README.rst b/board/freescale/ls1021atsn/README.rst new file mode 100644 index 00000000000..cdec02f1a35 --- /dev/null +++ b/board/freescale/ls1021atsn/README.rst @@ -0,0 +1,97 @@ +.. SPDX-License-Identifier: GPL-2.0 + +LS1021A-TSN Board Overview +========================== + + - 1GB DDR3 at 800 MHz + - Spansion/Cypress 64 MB (Rev. A) / 32 MB (Rev. B and C) QSPI NOR flash + - Ethernet + - 2 SGMII 10/100/1G Ethernet ports (Atheros AR8031) + - One SJA1105T switch with 4 Ethernet ports (Broadcom BCM5464R) + - One internal RGMII port connected to the switch + - SDHC + - microSDHC/SDXC connector + - Other I/O + - One Serial port + - Arduino and expansion headers + - mPCIE slot + - SATA port + - USB3.0 port + +LS1021A Memory map +================== + +The addresses in brackets are physical addresses. + +============== ============== ============================== ======= +Start Address End Address Description Size +============== ============== ============================== ======= +0x00_0000_0000 0x00_000F_FFFF Secure Boot ROM 1MB +0x00_0100_0000 0x00_0FFF_FFFF CCSRBAR 240MB +0x00_1000_0000 0x00_1000_FFFF OCRAM0 64KB +0x00_1001_0000 0x00_1001_FFFF OCRAM1 64KB +0x00_2000_0000 0x00_20FF_FFFF DCSR 16MB +0x00_4000_0000 0x00_5FFF_FFFF QSPI 512MB +0x00_6000_0000 0x00_67FF_FFFF IFC - NOR Flash 128MB +0x00_8000_0000 0x00_FFFF_FFFF DRAM1 2GB +============== ============== ============================== ======= + +Compiling and flashing +====================== + +The LS1021A-TSN board comes along with a microSD card with OpenIL U-Boot that +can be used to update its internal QSPI flash (which is empty out of the +factory). + +To compile and flash an SD card image:: + + make ls1021atsn_sdcard_defconfig && make -j 8 && sudo cp u-boot-with-spl-pbl.bin /srv/tftpboot/ + => tftp 0x82000000 u-boot-with-spl-pbl.bin && mmc rescan && mmc erase 8 0x1100 && mmc write 0x82000000 8 0x1100 + +For the QSPI flash, first obtain the Reset Configuration Word binary for +bootimg from the QSPI flash from the rcw project +(https://source.codeaurora.org/external/qoriq/qoriq-components/rcw):: + + make -j 8 && sudo cp ls1021atsn/SSR_PNS_30/rcw_1200_qspiboot.bin.swapped /srv/tftpboot/ + +The above RCW binary takes care of swapping the QSPI AMBA memory, so that the +U-Boot binary does not need to be swapped when flashing it. + +To compile and flash a U-Boot image for QSPI:: + + make ls1021atsn_qspi_defconfig && make -j 8 && sudo cp u-boot.bin /srv/tftpboot/ + +Then optionally create a custom uboot-env.txt file (although the default +environment already supports distro boot) and convert it to binary format:: + + mkenvimage -s 2M -o /srv/tftpboot/uboot-env.bin uboot-env.txt + +To program the QSPI flash with the images:: + + => tftp 0x82000000 rcw_1200_qspiboot.bin.swapped && sf probe && sf erase 0x0 +${filesize} && sf write 0x82000000 0x0 ${filesize} + => tftp 0x82000000 u-boot.bin && sf probe && sf erase 0x100000 +${filesize} && sf write 0x82000000 0x100000 ${filesize} + => tftp 0x82000000 uboot-env.bin && sf probe && sf erase 0x400000 +${filesize} && sf write 0x82000000 0x400000 ${filesize} + +The boards contain an AT24 I2C EEPROM that is supposed to hold the MAC +addresses of the Ethernet interfaces, however the EEPROM comes blank out of +the factory, and the MAC addresses are printed on a label on the bottom of +the boards. + +To write the MAC addresses to the EEPROM, the following needs to be done once:: + + => mac id + => mac 0 00:1F:7B:xx:xx:xx + => mac 1 00:1F:7B:xx:xx:xx + => mac 2 00:1F:7B:xx:xx:xx + => mac save + +The switch ports do not have their own MAC address - they inherit it from the +master enet2 port. + +Known issues and limitations +============================ + +- The 4 SJA1105 switch ports are not functional in U-Boot for now. +- Since the IFC pins are multiplexed with QSPI on LS1021A, currently there is + no way to talk to the CPLD for e.g. running the "qixis_reset" command, or + turning the fan on, etc. diff --git a/board/freescale/ls1021atsn/ls1021atsn.c b/board/freescale/ls1021atsn/ls1021atsn.c new file mode 100644 index 00000000000..39e825ca496 --- /dev/null +++ b/board/freescale/ls1021atsn/ls1021atsn.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2016-2019 NXP Semiconductors + */ +#include <common.h> +#include <asm/arch-ls102xa/ls102xa_soc.h> +#include <asm/arch/ls102xa_devdis.h> +#include <asm/arch/immap_ls102xa.h> +#include <asm/arch/ls102xa_soc.h> +#include <asm/arch/fsl_serdes.h> +#include "../common/sleep.h" +#include <fsl_validate.h> +#include <fsl_immap.h> +#include <fsl_csu.h> +#include <netdev.h> +#include <spl.h> +#ifdef CONFIG_U_QE +#include <fsl_qe.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static void ddrmc_init(void) +{ +#if (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)) + struct ccsr_ddr *ddr = (struct ccsr_ddr *)CONFIG_SYS_FSL_DDR_ADDR; + u32 temp_sdram_cfg, tmp; + + out_be32(&ddr->sdram_cfg, DDR_SDRAM_CFG); + + out_be32(&ddr->cs0_bnds, DDR_CS0_BNDS); + out_be32(&ddr->cs0_config, DDR_CS0_CONFIG); + + out_be32(&ddr->timing_cfg_0, DDR_TIMING_CFG_0); + out_be32(&ddr->timing_cfg_1, DDR_TIMING_CFG_1); + out_be32(&ddr->timing_cfg_2, DDR_TIMING_CFG_2); + out_be32(&ddr->timing_cfg_3, DDR_TIMING_CFG_3); + out_be32(&ddr->timing_cfg_4, DDR_TIMING_CFG_4); + out_be32(&ddr->timing_cfg_5, DDR_TIMING_CFG_5); + +#ifdef CONFIG_DEEP_SLEEP + if (is_warm_boot()) { + out_be32(&ddr->sdram_cfg_2, + DDR_SDRAM_CFG_2 & ~SDRAM_CFG2_D_INIT); + out_be32(&ddr->init_addr, CONFIG_SYS_SDRAM_BASE); + out_be32(&ddr->init_ext_addr, (1 << 31)); + + /* DRAM VRef will not be trained */ + out_be32(&ddr->ddr_cdr2, + DDR_DDR_CDR2 & ~DDR_CDR2_VREF_TRAIN_EN); + } else +#endif + { + out_be32(&ddr->sdram_cfg_2, DDR_SDRAM_CFG_2); + out_be32(&ddr->ddr_cdr2, DDR_DDR_CDR2); + } + + out_be32(&ddr->sdram_mode, DDR_SDRAM_MODE); + out_be32(&ddr->sdram_mode_2, DDR_SDRAM_MODE_2); + + out_be32(&ddr->sdram_interval, DDR_SDRAM_INTERVAL); + + out_be32(&ddr->ddr_wrlvl_cntl, DDR_DDR_WRLVL_CNTL); + + out_be32(&ddr->ddr_wrlvl_cntl_2, DDR_DDR_WRLVL_CNTL_2); + out_be32(&ddr->ddr_wrlvl_cntl_3, DDR_DDR_WRLVL_CNTL_3); + + out_be32(&ddr->ddr_cdr1, DDR_DDR_CDR1); + + out_be32(&ddr->sdram_clk_cntl, DDR_SDRAM_CLK_CNTL); + out_be32(&ddr->ddr_zq_cntl, DDR_DDR_ZQ_CNTL); + + out_be32(&ddr->cs0_config_2, DDR_CS0_CONFIG_2); + + /* DDR erratum A-009942 */ + tmp = in_be32(&ddr->debug[28]); + out_be32(&ddr->debug[28], tmp | 0x0070006f); + + udelay(1); + +#ifdef CONFIG_DEEP_SLEEP + if (is_warm_boot()) { + /* enter self-refresh */ + temp_sdram_cfg = in_be32(&ddr->sdram_cfg_2); + temp_sdram_cfg |= SDRAM_CFG2_FRC_SR; + out_be32(&ddr->sdram_cfg_2, temp_sdram_cfg); + + temp_sdram_cfg = (DDR_SDRAM_CFG_MEM_EN | SDRAM_CFG_BI); + } else +#endif + temp_sdram_cfg = (DDR_SDRAM_CFG_MEM_EN & ~SDRAM_CFG_BI); + + out_be32(&ddr->sdram_cfg, DDR_SDRAM_CFG | temp_sdram_cfg); + +#ifdef CONFIG_DEEP_SLEEP + if (is_warm_boot()) { + /* exit self-refresh */ + temp_sdram_cfg = in_be32(&ddr->sdram_cfg_2); + temp_sdram_cfg &= ~SDRAM_CFG2_FRC_SR; + out_be32(&ddr->sdram_cfg_2, temp_sdram_cfg); + } +#endif +#endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */ +} + +int dram_init(void) +{ + ddrmc_init(); + + erratum_a008850_post(); + + gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE); + +#if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD) + fsl_dp_resume(); +#endif + + return 0; +} + +int board_eth_init(bd_t *bis) +{ + return pci_eth_init(bis); +} + +int board_early_init_f(void) +{ + struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; + +#ifdef CONFIG_TSEC_ENET + /* + * Clear BD & FR bits for big endian BD's and frame data (aka set + * correct eTSEC endianness). This is crucial in ensuring that it does + * not report Data Parity Errors in its RX/TX FIFOs when attempting to + * send traffic. + */ + clrbits_be32(&scfg->etsecdmamcr, SCFG_ETSECDMAMCR_LE_BD_FR); + /* EC3_GTX_CLK125 (of enet2) used for all RGMII interfaces */ + out_be32(&scfg->etsecmcr, SCFG_ETSECCMCR_GE2_CLK125); +#endif + + arch_soc_init(); + +#if defined(CONFIG_DEEP_SLEEP) + if (is_warm_boot()) { + timer_init(); + dram_init(); + } +#endif + + return 0; +} + +#ifdef CONFIG_SPL_BUILD +void board_init_f(ulong dummy) +{ + void (*second_uboot)(void); + + /* Clear the BSS */ + memset(__bss_start, 0, __bss_end - __bss_start); + + get_clocks(); + +#if defined(CONFIG_DEEP_SLEEP) + if (is_warm_boot()) + fsl_dp_disable_console(); +#endif + + preloader_console_init(); + + dram_init(); + + /* Allow OCRAM access permission as R/W */ +#ifdef CONFIG_LAYERSCAPE_NS_ACCESS + enable_layerscape_ns_access(); + enable_layerscape_ns_access(); +#endif + + /* + * if it is woken up from deep sleep, then jump to second + * stage U-Boot and continue executing without recopying + * it from SD since it has already been reserved in memory + * in last boot. + */ + if (is_warm_boot()) { + second_uboot = (void (*)(void))CONFIG_SYS_TEXT_BASE; + second_uboot(); + } + + board_init_r(NULL, 0); +} +#endif + +int board_init(void) +{ +#ifndef CONFIG_SYS_FSL_NO_SERDES + fsl_serdes_init(); +#endif + ls102xa_smmu_stream_id_init(); + +#ifdef CONFIG_LAYERSCAPE_NS_ACCESS + enable_layerscape_ns_access(); +#endif + +#ifdef CONFIG_U_QE + u_qe_init(); +#endif + + return 0; +} + +#if defined(CONFIG_SPL_BUILD) +void spl_board_init(void) +{ + ls102xa_smmu_stream_id_init(); +} +#endif + +#ifdef CONFIG_BOARD_LATE_INIT +int board_late_init(void) +{ +#ifdef CONFIG_CHAIN_OF_TRUST + fsl_setenv_chain_of_trust(); +#endif + + return 0; +} +#endif + +#if defined(CONFIG_MISC_INIT_R) +int misc_init_r(void) +{ +#ifdef CONFIG_FSL_DEVICE_DISABLE + device_disable(devdis_tbl, ARRAY_SIZE(devdis_tbl)); +#endif + +#ifdef CONFIG_FSL_CAAM + return sec_init(); +#endif +} +#endif + +#if defined(CONFIG_DEEP_SLEEP) +void board_sleep_prepare(void) +{ +#ifdef CONFIG_LAYERSCAPE_NS_ACCESS + enable_layerscape_ns_access(); +#endif +} +#endif + +int ft_board_setup(void *blob, bd_t *bd) +{ + ft_cpu_setup(blob, bd); + +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); +#endif + + return 0; +} diff --git a/board/freescale/ls1021atsn/ls102xa_pbi.cfg b/board/freescale/ls1021atsn/ls102xa_pbi.cfg new file mode 100644 index 00000000000..ba1499b2644 --- /dev/null +++ b/board/freescale/ls1021atsn/ls102xa_pbi.cfg @@ -0,0 +1,15 @@ +# PBI commands + +09570200 ffffffff +09570158 00000300 +8940007c 21f47300 + +# Configure Scratch register +09ee0200 10000000 +# Configure alternate space +09570158 00001000 +# Flush PBL data +096100c0 000FFFFF + +09ea085c 00502880 +09ea0560 80800000 diff --git a/board/freescale/ls1021atsn/ls102xa_rcw_sd.cfg b/board/freescale/ls1021atsn/ls102xa_rcw_sd.cfg new file mode 100644 index 00000000000..a6fc91436f2 --- /dev/null +++ b/board/freescale/ls1021atsn/ls102xa_rcw_sd.cfg @@ -0,0 +1,8 @@ +# PBL preamble and RCW header +aa55aa55 01ee0100 + +# Disable IFC, enable QSPI and DSPI +0608000c 00000000 00000000 00000000 +30000000 08007900 40105a00 21046000 +00000000 00000000 00000000 10002000 +20124801 8804b340 00000000 00000000 diff --git a/board/freescale/ls1021atwr/ls1021atwr.c b/board/freescale/ls1021atwr/ls1021atwr.c index 01ba1bc9621..fcf2ec97889 100644 --- a/board/freescale/ls1021atwr/ls1021atwr.c +++ b/board/freescale/ls1021atwr/ls1021atwr.c @@ -248,44 +248,6 @@ int board_mmc_init(bd_t *bis) int board_eth_init(bd_t *bis) { -#ifdef CONFIG_TSEC_ENET - struct fsl_pq_mdio_info mdio_info; - struct tsec_info_struct tsec_info[4]; - int num = 0; - -#ifdef CONFIG_TSEC1 - SET_STD_TSEC_INFO(tsec_info[num], 1); - if (is_serdes_configured(SGMII_TSEC1)) { - puts("eTSEC1 is in sgmii mode.\n"); - tsec_info[num].flags |= TSEC_SGMII; - } - num++; -#endif -#ifdef CONFIG_TSEC2 - SET_STD_TSEC_INFO(tsec_info[num], 2); - if (is_serdes_configured(SGMII_TSEC2)) { - puts("eTSEC2 is in sgmii mode.\n"); - tsec_info[num].flags |= TSEC_SGMII; - } - num++; -#endif -#ifdef CONFIG_TSEC3 - SET_STD_TSEC_INFO(tsec_info[num], 3); - tsec_info[num].interface = PHY_INTERFACE_MODE_RGMII_ID; - num++; -#endif - if (!num) { - printf("No TSECs initialized\n"); - return 0; - } - - mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR; - mdio_info.name = DEFAULT_MII_NAME; - fsl_pq_mdio_init(bis, &mdio_info); - - tsec_eth_init(bis, tsec_info, num); -#endif - return pci_eth_init(bis); } diff --git a/board/logicpd/am3517evm/am3517evm.c b/board/logicpd/am3517evm/am3517evm.c index 10031a48018..bfd4e782749 100644 --- a/board/logicpd/am3517evm/am3517evm.c +++ b/board/logicpd/am3517evm/am3517evm.c @@ -28,7 +28,6 @@ #include <linux/usb/gadget.h> #include <linux/usb/musb.h> #include <i2c.h> -#include <netdev.h> #include "am3517evm.h" DECLARE_GLOBAL_DATA_PTR; diff --git a/board/mqmaker/miqi_rk3288/miqi-rk3288.c b/board/mqmaker/miqi_rk3288/miqi-rk3288.c index d6992a26caf..779bc646b2a 100644 --- a/board/mqmaker/miqi_rk3288/miqi-rk3288.c +++ b/board/mqmaker/miqi_rk3288/miqi-rk3288.c @@ -3,12 +3,3 @@ * (C) Copyright 2016 Rockchip Electronics Co., Ltd */ -#include <common.h> -#include <spl.h> - -void board_boot_order(u32 *spl_boot_list) -{ - /* eMMC prior to sdcard. */ - spl_boot_list[0] = BOOT_DEVICE_MMC2; - spl_boot_list[1] = BOOT_DEVICE_MMC1; -} diff --git a/board/rockchip/evb_rk3288/evb-rk3288.c b/board/rockchip/evb_rk3288/evb-rk3288.c index d6992a26caf..779bc646b2a 100644 --- a/board/rockchip/evb_rk3288/evb-rk3288.c +++ b/board/rockchip/evb_rk3288/evb-rk3288.c @@ -3,12 +3,3 @@ * (C) Copyright 2016 Rockchip Electronics Co., Ltd */ -#include <common.h> -#include <spl.h> - -void board_boot_order(u32 *spl_boot_list) -{ - /* eMMC prior to sdcard. */ - spl_boot_list[0] = BOOT_DEVICE_MMC2; - spl_boot_list[1] = BOOT_DEVICE_MMC1; -} diff --git a/board/rockchip/evb_rk3399/README b/board/rockchip/evb_rk3399/README index 64698219872..ea3258cf378 100644 --- a/board/rockchip/evb_rk3399/README +++ b/board/rockchip/evb_rk3399/README @@ -35,12 +35,6 @@ Get the Source and prebuild binary > git clone https://github.com/rockchip-linux/rkbin.git > git clone https://github.com/rockchip-linux/rkdeveloptool.git -Get some prerequisites -====================== - -You need the Python elftools.elf.elffile library for make_fit_atf.py to work: - - > sudo apt-get install python-pyelftools Compile ATF =========== diff --git a/board/rockchip/fennec_rk3288/fennec-rk3288.c b/board/rockchip/fennec_rk3288/fennec-rk3288.c index ce455449dd7..779bc646b2a 100644 --- a/board/rockchip/fennec_rk3288/fennec-rk3288.c +++ b/board/rockchip/fennec_rk3288/fennec-rk3288.c @@ -3,12 +3,3 @@ * (C) Copyright 2016 Rockchip Electronics Co., Ltd */ -#include <common.h> -#include <spl.h> - -void board_boot_order(u32 *spl_boot_list) -{ - /* eMMC prior to sdcard */ - spl_boot_list[0] = BOOT_DEVICE_MMC2; - spl_boot_list[1] = BOOT_DEVICE_MMC1; -} diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox deleted file mode 100644 index c10dd444df0..00000000000 --- a/board/sandbox/README.sandbox +++ /dev/null @@ -1,508 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 2014 The Chromium OS Authors. - */ - -Native Execution of U-Boot -========================== - -The 'sandbox' architecture is designed to allow U-Boot to run under Linux on -almost any hardware. To achieve this it builds U-Boot (so far as possible) -as a normal C application with a main() and normal C libraries. - -All of U-Boot's architecture-specific code therefore cannot be built as part -of the sandbox U-Boot. The purpose of running U-Boot under Linux is to test -all the generic code, not specific to any one architecture. The idea is to -create unit tests which we can run to test this upper level code. - -CONFIG_SANDBOX is defined when building a native board. - -The board name is 'sandbox' but the vendor name is unset, so there is a -single board in board/sandbox. - -CONFIG_SANDBOX_BIG_ENDIAN should be defined when running on big-endian -machines. - -There are two versions of the sandbox: One using 32-bit-wide integers, and one -using 64-bit-wide integers. The 32-bit version can be build and run on either -32 or 64-bit hosts by either selecting or deselecting CONFIG_SANDBOX_32BIT; by -default, the sandbox it built for a 32-bit host. The sandbox using 64-bit-wide -integers can only be built on 64-bit hosts. - -Note that standalone/API support is not available at present. - - -Basic Operation ---------------- - -To run sandbox U-Boot use something like: - - make sandbox_defconfig all - ./u-boot - -Note: - If you get errors about 'sdl-config: Command not found' you may need to - install libsdl1.2-dev or similar to get SDL support. Alternatively you can - build sandbox without SDL (i.e. no display/keyboard support) by removing - the CONFIG_SANDBOX_SDL line in include/configs/sandbox.h or using: - - make sandbox_defconfig all NO_SDL=1 - ./u-boot - -U-Boot will start on your computer, showing a sandbox emulation of the serial -console: - - -U-Boot 2014.04 (Mar 20 2014 - 19:06:00) - -DRAM: 128 MiB -Using default environment - -In: serial -Out: lcd -Err: lcd -=> - -You can issue commands as your would normally. If the command you want is -not supported you can add it to include/configs/sandbox.h. - -To exit, type 'reset' or press Ctrl-C. - - -Console / LCD support ---------------------- - -Assuming that CONFIG_SANDBOX_SDL is defined when building, you can run the -sandbox with LCD and keyboard emulation, using something like: - - ./u-boot -d u-boot.dtb -l - -This will start U-Boot with a window showing the contents of the LCD. If -that window has the focus then you will be able to type commands as you -would on the console. You can adjust the display settings in the device -tree file - see arch/sandbox/dts/sandbox.dts. - - -Command-line Options --------------------- - -Various options are available, mostly for test purposes. Use -h to see -available options. Some of these are described below. - -The terminal is normally in what is called 'raw-with-sigs' mode. This means -that you can use arrow keys for command editing and history, but if you -press Ctrl-C, U-Boot will exit instead of handling this as a keypress. - -Other options are 'raw' (so Ctrl-C is handled within U-Boot) and 'cooked' -(where the terminal is in cooked mode and cursor keys will not work, Ctrl-C -will exit). - -As mentioned above, -l causes the LCD emulation window to be shown. - -A device tree binary file can be provided with -d. If you edit the source -(it is stored at arch/sandbox/dts/sandbox.dts) you must rebuild U-Boot to -recreate the binary file. - -To execute commands directly, use the -c option. You can specify a single -command, or multiple commands separated by a semicolon, as is normal in -U-Boot. Be careful with quoting as the shell will normally process and -swallow quotes. When -c is used, U-Boot exits after the command is complete, -but you can force it to go to interactive mode instead with -i. - - -Memory Emulation ----------------- - -Memory emulation is supported, with the size set by CONFIG_SYS_SDRAM_SIZE. -The -m option can be used to read memory from a file on start-up and write -it when shutting down. This allows preserving of memory contents across -test runs. You can tell U-Boot to remove the memory file after it is read -(on start-up) with the --rm_memory option. - -To access U-Boot's emulated memory within the code, use map_sysmem(). This -function is used throughout U-Boot to ensure that emulated memory is used -rather than the U-Boot application memory. This provides memory starting -at 0 and extending to the size of the emulation. - - -Storing State -------------- - -With sandbox you can write drivers which emulate the operation of drivers on -real devices. Some of these drivers may want to record state which is -preserved across U-Boot runs. This is particularly useful for testing. For -example, the contents of a SPI flash chip should not disappear just because -U-Boot exits. - -State is stored in a device tree file in a simple format which is driver- -specific. You then use the -s option to specify the state file. Use -r to -make U-Boot read the state on start-up (otherwise it starts empty) and -w -to write it on exit (otherwise the stored state is left unchanged and any -changes U-Boot made will be lost). You can also use -n to tell U-Boot to -ignore any problems with missing state. This is useful when first running -since the state file will be empty. - -The device tree file has one node for each driver - the driver can store -whatever properties it likes in there. See 'Writing Sandbox Drivers' below -for more details on how to get drivers to read and write their state. - - -Running and Booting -------------------- - -Since there is no machine architecture, sandbox U-Boot cannot actually boot -a kernel, but it does support the bootm command. Filesystems, memory -commands, hashing, FIT images, verified boot and many other features are -supported. - -When 'bootm' runs a kernel, sandbox will exit, as U-Boot does on a real -machine. Of course in this case, no kernel is run. - -It is also possible to tell U-Boot that it has jumped from a temporary -previous U-Boot binary, with the -j option. That binary is automatically -removed by the U-Boot that gets the -j option. This allows you to write -tests which emulate the action of chain-loading U-Boot, typically used in -a situation where a second 'updatable' U-Boot is stored on your board. It -is very risky to overwrite or upgrade the only U-Boot on a board, since a -power or other failure will brick the board and require return to the -manufacturer in the case of a consumer device. - - -Supported Drivers ------------------ - -U-Boot sandbox supports these emulations: - -- Block devices -- Chrome OS EC -- GPIO -- Host filesystem (access files on the host from within U-Boot) -- I2C -- Keyboard (Chrome OS) -- LCD -- Network -- Serial (for console only) -- Sound (incomplete - see sandbox_sdl_sound_init() for details) -- SPI -- SPI flash -- TPM (Trusted Platform Module) - -A wide range of commands are implemented. Filesystems which use a block -device are supported. - -Also sandbox supports driver model (CONFIG_DM) and associated commands. - - -Sandbox Variants ----------------- - -There are unfortunately quite a few variants at present: - -sandbox - should be used for most tests -sandbox64 - special build that forces a 64-bit host -sandbox_flattree - builds with dev_read_...() functions defined as inline. - We need this build so that we can test those inline functions, and we - cannot build with both the inline functions and the non-inline functions - since they are named the same. -sandbox_noblk - builds without CONFIG_BLK, which means the legacy block - drivers are used. We cannot use both the legacy and driver-model block - drivers since they implement the same functions -sandbox_spl - builds sandbox with SPL support, so you can run spl/u-boot-spl - and it will start up and then load ./u-boot. It is also possible to - run ./u-boot directly. - -Of these sandbox_noblk can be removed once CONFIG_BLK is used everwhere, and -sandbox_spl can probably be removed since it is a superset of sandbox. - -Most of the config options should be identical between these variants. - - -Linux RAW Networking Bridge ---------------------------- - -The sandbox_eth_raw driver bridges traffic between the bottom of the network -stack and the RAW sockets API in Linux. This allows much of the U-Boot network -functionality to be tested in sandbox against real network traffic. - -For Ethernet network adapters, the bridge utilizes the RAW AF_PACKET API. This -is needed to get access to the lowest level of the network stack in Linux. This -means that all of the Ethernet frame is included. This allows the U-Boot network -stack to be fully used. In other words, nothing about the Linux network stack is -involved in forming the packets that end up on the wire. To receive the -responses to packets sent from U-Boot the network interface has to be set to -promiscuous mode so that the network card won't filter out packets not destined -for its configured (on Linux) MAC address. - -The RAW sockets Ethernet API requires elevated privileges in Linux. You can -either run as root, or you can add the capability needed like so: - -sudo /sbin/setcap "CAP_NET_RAW+ep" /path/to/u-boot - -The default device tree for sandbox includes an entry for eth0 on the sandbox -host machine whose alias is "eth1". The following are a few examples of network -operations being tested on the eth0 interface. - -sudo /path/to/u-boot -D - -DHCP -.... - -setenv autoload no -setenv ethrotate no -setenv ethact eth1 -dhcp - -PING -.... - -setenv autoload no -setenv ethrotate no -setenv ethact eth1 -dhcp -ping $gatewayip - -TFTP -.... - -setenv autoload no -setenv ethrotate no -setenv ethact eth1 -dhcp -setenv serverip WWW.XXX.YYY.ZZZ -tftpboot u-boot.bin - -The bridge also supports (to a lesser extent) the localhost interface, 'lo'. - -The 'lo' interface cannot use the RAW AF_PACKET API because the lo interface -doesn't support Ethernet-level traffic. It is a higher-level interface that is -expected only to be used at the AF_INET level of the API. As such, the most raw -we can get on that interface is the RAW AF_INET API on UDP. This allows us to -set the IP_HDRINCL option to include everything except the Ethernet header in -the packets we send and receive. - -Because only UDP is supported, ICMP traffic will not work, so expect that ping -commands will time out. - -The default device tree for sandbox includes an entry for lo on the sandbox -host machine whose alias is "eth5". The following is an example of a network -operation being tested on the lo interface. - -TFTP -.... - -setenv ethrotate no -setenv ethact eth5 -tftpboot u-boot.bin - - -SPI Emulation -------------- - -Sandbox supports SPI and SPI flash emulation. - -This is controlled by the spi_sf argument, the format of which is: - - bus:cs:device:file - - bus - SPI bus number - cs - SPI chip select number - device - SPI device emulation name - file - File on disk containing the data - -For example: - - dd if=/dev/zero of=spi.bin bs=1M count=4 - ./u-boot --spi_sf 0:0:M25P16:spi.bin - -With this setup you can issue SPI flash commands as normal: - -=>sf probe -SF: Detected M25P16 with page size 64 KiB, total 2 MiB -=>sf read 0 0 10000 -SF: 65536 bytes @ 0x0 Read: OK -=> - -Since this is a full SPI emulation (rather than just flash), you can -also use low-level SPI commands: - -=>sspi 0:0 32 9f -FF202015 - -This is issuing a READ_ID command and getting back 20 (ST Micro) part -0x2015 (the M25P16). - -Drivers are connected to a particular bus/cs using sandbox's state -structure (see the 'spi' member). A set of operations must be provided -for each driver. - - -Configuration settings for the curious are: - -CONFIG_SANDBOX_SPI_MAX_BUS - The maximum number of SPI buses supported by the driver (default 1). - -CONFIG_SANDBOX_SPI_MAX_CS - The maximum number of chip selects supported by the driver - (default 10). - -CONFIG_SPI_IDLE_VAL - The idle value on the SPI bus - - -Block Device Emulation ----------------------- - -U-Boot can use raw disk images for block device emulation. To e.g. list -the contents of the root directory on the second partion of the image -"disk.raw", you can use the following commands: - -=>host bind 0 ./disk.raw -=>ls host 0:2 - -A disk image can be created using the following commands: - -$> truncate -s 1200M ./disk.raw -$> echo -e "label: gpt\n,64M,U\n,,L" | /usr/sbin/sgdisk ./disk.raw -$> lodev=`sudo losetup -P -f --show ./disk.raw` -$> sudo mkfs.vfat -n EFI -v ${lodev}p1 -$> sudo mkfs.ext4 -L ROOT -v ${lodev}p2 - -or utilize the device described in test/py/make_test_disk.py: - - #!/usr/bin/python - import make_test_disk - make_test_disk.makeDisk() - -Writing Sandbox Drivers ------------------------ - -Generally you should put your driver in a file containing the word 'sandbox' -and put it in the same directory as other drivers of its type. You can then -implement the same hooks as the other drivers. - -To access U-Boot's emulated memory, use map_sysmem() as mentioned above. - -If your driver needs to store configuration or state (such as SPI flash -contents or emulated chip registers), you can use the device tree as -described above. Define handlers for this with the SANDBOX_STATE_IO macro. -See arch/sandbox/include/asm/state.h for documentation. In short you provide -a node name, compatible string and functions to read and write the state. -Since writing the state can expand the device tree, you may need to use -state_setprop() which does this automatically and avoids running out of -space. See existing code for examples. - - -Debugging the init sequence ---------------------------- - -If you get a failure in the initcall sequence, like this: - - initcall sequence 0000560775957c80 failed at call 0000000000048134 (err=-96) - -Then you use can use grep to see which init call failed, e.g.: - - $ grep 0000000000048134 u-boot.map - stdio_add_devices - -Of course another option is to run it with a debugger such as gdb: - - $ gdb u-boot - ... - (gdb) br initcall.h:41 - Breakpoint 1 at 0x4db9d: initcall.h:41. (2 locations) - -Note that two locations are reported, since this function is used in both -board_init_f() and board_init_r(). - - (gdb) r - Starting program: /tmp/b/sandbox/u-boot - [Thread debugging using libthread_db enabled] - Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". - - U-Boot 2018.09-00264-ge0c2ba9814-dirty (Sep 22 2018 - 12:21:46 -0600) - - DRAM: 128 MiB - MMC: - - Breakpoint 1, initcall_run_list (init_sequence=0x5555559619e0 <init_sequence_f>) - at /scratch/sglass/cosarm/src/third_party/u-boot/files/include/initcall.h:41 - 41 printf("initcall sequence %p failed at call %p (err=%d)\n", - (gdb) print *init_fnc_ptr - $1 = (const init_fnc_t) 0x55555559c114 <stdio_add_devices> - (gdb) - - -This approach can be used on normal boards as well as sandbox. - - -SDL_CONFIG ----------- - -If sdl-config is on a different path from the default, set the SDL_CONFIG -environment variable to the correct pathname before building U-Boot. - - -Using valgrind / memcheck -------------------------- - -It is possible to run U-Boot under valgrind to check memory allocations: - - valgrind u-boot - -If you are running sandbox SPL or TPL, then valgrind will not by default -notice when U-Boot jumps from TPL to SPL, or from SPL to U-Boot proper. To -fix this, use: - - valgrind --trace-children=yes u-boot - - -Testing -------- - -U-Boot sandbox can be used to run various tests, mostly in the test/ -directory. These include: - - command_ut - - Unit tests for command parsing and handling - compression - - Unit tests for U-Boot's compression algorithms, useful for - security checking. It supports gzip, bzip2, lzma and lzo. - driver model - - Run this pytest - ./test/py/test.py --bd sandbox --build -k ut_dm -v - image - - Unit tests for images: - test/image/test-imagetools.sh - multi-file images - test/image/test-fit.py - FIT images - tracing - - test/trace/test-trace.sh tests the tracing system (see README.trace) - verified boot - - See test/vboot/vboot_test.sh for this - -If you change or enhance any of the above subsystems, you shold write or -expand a test and include it with your patch series submission. Test -coverage in U-Boot is limited, as we need to work to improve it. - -Note that many of these tests are implemented as commands which you can -run natively on your board if desired (and enabled). - -To run all tests use "make check". - - -Memory Map ----------- - -Sandbox has its own emulated memory starting at 0. Here are some of the things -that are mapped into that memory: - - 0 CONFIG_SYS_FDT_LOAD_ADDR Device tree - e000 CONFIG_BLOBLIST_ADDR Blob list - 10000 CONFIG_MALLOC_F_ADDR Early memory allocation - f0000 CONFIG_PRE_CON_BUF_ADDR Pre-console buffer - 100000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled) -= - - --- -Simon Glass <sjg@chromium.org> -Updated 22-Mar-14 diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 8eb5e304ab2..5d650804291 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -28,7 +28,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply CMD_PING imply CLK_SIFIVE imply CLK_SIFIVE_FU540_PRCI - imply CLK_SIFIVE_GEMGXL_MGMT imply DOS_PARTITION imply EFI_PARTITION imply IP_DYN @@ -39,6 +38,12 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply PHY_LIB imply PHY_MSCC imply SIFIVE_SERIAL + imply SPI + imply SPI_SIFIVE + imply MMC + imply MMC_SPI + imply MMC_BROKEN_CD + imply CMD_MMC imply SMP endif diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index 5adc4a3d4a7..11daf1a75a0 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -8,6 +8,128 @@ #include <common.h> #include <dm.h> +#include <linux/delay.h> +#include <linux/io.h> + +#ifdef CONFIG_MISC_INIT_R + +#define FU540_OTP_BASE_ADDR 0x10070000 + +struct fu540_otp_regs { + u32 pa; /* Address input */ + u32 paio; /* Program address input */ + u32 pas; /* Program redundancy cell selection input */ + u32 pce; /* OTP Macro enable input */ + u32 pclk; /* Clock input */ + u32 pdin; /* Write data input */ + u32 pdout; /* Read data output */ + u32 pdstb; /* Deep standby mode enable input (active low) */ + u32 pprog; /* Program mode enable input */ + u32 ptc; /* Test column enable input */ + u32 ptm; /* Test mode enable input */ + u32 ptm_rep;/* Repair function test mode enable input */ + u32 ptr; /* Test row enable input */ + u32 ptrim; /* Repair function enable input */ + u32 pwe; /* Write enable input (defines program cycle) */ +} __packed; + +#define BYTES_PER_FUSE 4 +#define NUM_FUSES 0x1000 + +static int fu540_otp_read(int offset, void *buf, int size) +{ + struct fu540_otp_regs *regs = (void __iomem *)FU540_OTP_BASE_ADDR; + unsigned int i; + int fuseidx = offset / BYTES_PER_FUSE; + int fusecount = size / BYTES_PER_FUSE; + u32 fusebuf[fusecount]; + + /* check bounds */ + if (offset < 0 || size < 0) + return -EINVAL; + if (fuseidx >= NUM_FUSES) + return -EINVAL; + if ((fuseidx + fusecount) > NUM_FUSES) + return -EINVAL; + + /* init OTP */ + writel(0x01, ®s->pdstb); /* wake up from stand-by */ + writel(0x01, ®s->ptrim); /* enable repair function */ + writel(0x01, ®s->pce); /* enable input */ + + /* read all requested fuses */ + for (i = 0; i < fusecount; i++, fuseidx++) { + writel(fuseidx, ®s->pa); + + /* cycle clock to read */ + writel(0x01, ®s->pclk); + mdelay(1); + writel(0x00, ®s->pclk); + mdelay(1); + + /* read the value */ + fusebuf[i] = readl(®s->pdout); + } + + /* shut down */ + writel(0, ®s->pce); + writel(0, ®s->ptrim); + writel(0, ®s->pdstb); + + /* copy out */ + memcpy(buf, fusebuf, size); + + return 0; +} + +static u32 fu540_read_serialnum(void) +{ + int ret; + u32 serial[2] = {0}; + + for (int i = 0xfe * 4; i > 0; i -= 8) { + ret = fu540_otp_read(i, serial, sizeof(serial)); + if (ret) { + printf("%s: error reading from OTP\n", __func__); + break; + } + if (serial[0] == ~serial[1]) + return serial[0]; + } + + return 0; +} + +static void fu540_setup_macaddr(u32 serialnum) +{ + /* Default MAC address */ + unsigned char mac[6] = { 0x70, 0xb3, 0xd5, 0x92, 0xf0, 0x00 }; + + /* + * We derive our board MAC address by ORing last three bytes + * of board serial number to above default MAC address. + * + * This logic of deriving board MAC address is taken from + * SiFive FSBL and is kept unchanged. + */ + mac[5] |= (serialnum >> 0) & 0xff; + mac[4] |= (serialnum >> 8) & 0xff; + mac[3] |= (serialnum >> 16) & 0xff; + + /* Update environment variable */ + eth_env_set_enetaddr("ethaddr", mac); +} + +int misc_init_r(void) +{ + /* Set ethaddr environment variable if not set */ + if (!env_get("ethaddr")) + fu540_setup_macaddr(fu540_read_serialnum()); + + return 0; +} + +#endif int board_init(void) { diff --git a/board/ti/am65x/Kconfig b/board/ti/am65x/Kconfig index 98172c28f5d..47b41cd6afe 100644 --- a/board/ti/am65x/Kconfig +++ b/board/ti/am65x/Kconfig @@ -12,14 +12,18 @@ config TARGET_AM654_A53_EVM select ARM64 select SOC_K3_AM6 select SYS_DISABLE_DCACHE_OPS + select BOARD_LATE_INIT + imply TI_I2C_BOARD_DETECT config TARGET_AM654_R5_EVM bool "TI K3 based AM654 EVM running on R5" select CPU_V7R select SYS_THUMB_BUILD select SOC_K3_AM6 + select K3_LOAD_SYSFW select K3_AM654_DDRSS imply SYS_K3_SPL_ATF + imply TI_I2C_BOARD_DETECT endchoice @@ -34,6 +38,8 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "am65x_evm" +source "board/ti/common/Kconfig" + endif if TARGET_AM654_R5_EVM @@ -50,4 +56,6 @@ config SYS_CONFIG_NAME config SPL_LDSCRIPT default "arch/arm/mach-omap2/u-boot-spl.lds" +source "board/ti/common/Kconfig" + endif diff --git a/board/ti/am65x/README b/board/ti/am65x/README index 0b82bd557b5..16384e05ea2 100644 --- a/board/ti/am65x/README +++ b/board/ti/am65x/README @@ -209,3 +209,55 @@ Image formats: | | Secure config | | | +-------------------+ | +-----------------------+ + +eMMC: +----- +ROM supports booting from eMMC from boot0 partition offset 0x0 + +Flashing images to eMMC: + +The following commands can be used to download tiboot3.bin, tispl.bin, +u-boot.img, and sysfw.itb from an SD card and write them to the eMMC boot0 +partition at respective addresses. + +=> mmc dev 0 1 +=> fatload mmc 1 ${loadaddr} tiboot3.bin +=> mmc write ${loadaddr} 0x0 0x400 +=> fatload mmc 1 ${loadaddr} tispl.bin +=> mmc write ${loadaddr} 0x400 0x1000 +=> fatload mmc 1 ${loadaddr} u-boot.img +=> mmc write ${loadaddr} 0x1400 0x2000 +=> fatload mmc 1 ${loadaddr} sysfw.itb +=> mmc write ${loadaddr} 0x3600 0x800 + +To give the ROM access to the boot partition, the following commands must be +used for the first time: +=> mmc partconf 0 1 1 1 +=> mmc bootbus 0 1 0 0 + +To create a software partition for the rootfs, the following command can be +used: +=> gpt write mmc 0 ${partitions} + +eMMC layout: + + boot0 partition (8 MB) user partition + 0x0+----------------------------------+ 0x0+-------------------------+ + | tiboot3.bin (512 KB) | | | + 0x400+----------------------------------+ | | + | tispl.bin (2 MB) | | | +0x1400+----------------------------------+ | rootfs | + | u-boot.img (4 MB) | | | +0x3400+----------------------------------+ | | + | environment (128 KB) | | | +0x3500+----------------------------------+ | | + | backup environment (128 KB) | | | +0x3600+----------------------------------+ | | + | sysfw (1 MB) | | | +0x3E00+----------------------------------+ +-------------------------+ + +Kernel image and DT are expected to be present in the /boot folder of rootfs. +To boot kernel from eMMC, use the following commands: +=> setenv mmcdev 0 +=> setenv bootpart 0 +=> boot diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c index 52f5d6b11e3..7bd8c4fa665 100644 --- a/board/ti/am65x/evm.c +++ b/board/ti/am65x/evm.c @@ -8,10 +8,31 @@ */ #include <common.h> +#include <dm.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/hardware.h> +#include <asm/gpio.h> #include <asm/io.h> +#include <asm/omap_common.h> #include <spl.h> #include <asm/arch/sys_proto.h> +#include "../common/board_detect.h" + +#define board_is_am65x_base_board() board_ti_is("AM6-COMPROCEVM") + +/* Daughter card presence detection signals */ +enum { + AM65X_EVM_APP_BRD_DET, + AM65X_EVM_LCD_BRD_DET, + AM65X_EVM_SERDES_BRD_DET, + AM65X_EVM_HDMI_GPMC_BRD_DET, + AM65X_EVM_BRD_DET_COUNT, +}; + +/* Max number of MAC addresses that are parsed/processed per daughter card */ +#define DAUGHTER_CARD_NO_OF_MAC_ADDR 8 + DECLARE_GLOBAL_DATA_PTR; int board_init(void) @@ -80,3 +101,223 @@ int ft_board_setup(void *blob, bd_t *bd) return ret; } #endif + +int do_board_detect(void) +{ + int ret; + + ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS, + CONFIG_EEPROM_CHIP_ADDRESS); + if (ret) + pr_err("Reading on-board EEPROM at 0x%02x failed %d\n", + CONFIG_EEPROM_CHIP_ADDRESS, ret); + + return ret; +} + +static void setup_board_eeprom_env(void) +{ + char *name = "am65x"; + + if (do_board_detect()) + goto invalid_eeprom; + + if (board_is_am65x_base_board()) + name = "am65x"; + else + printf("Unidentified board claims %s in eeprom header\n", + board_ti_get_name()); + +invalid_eeprom: + set_board_info_env_am6(name); +} + +static int init_daughtercard_det_gpio(char *gpio_name, struct gpio_desc *desc) +{ + int ret; + + memset(desc, 0, sizeof(*desc)); + + ret = dm_gpio_lookup_name(gpio_name, desc); + if (ret < 0) + return ret; + + /* Request GPIO, simply re-using the name as label */ + ret = dm_gpio_request(desc, gpio_name); + if (ret < 0) + return ret; + + return dm_gpio_set_dir_flags(desc, GPIOD_IS_IN); +} + +static int probe_daughtercards(void) +{ + struct ti_am6_eeprom ep; + struct gpio_desc board_det_gpios[AM65X_EVM_BRD_DET_COUNT]; + char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; + u8 mac_addr_cnt; + char name_overlays[1024] = { 0 }; + int i, j; + int ret; + + /* + * Daughter card presence detection signal name to GPIO (via I2C I/O + * expander @ address 0x38) name and EEPROM I2C address mapping. + */ + const struct { + char *gpio_name; + u8 i2c_addr; + } slot_map[AM65X_EVM_BRD_DET_COUNT] = { + { "gpio@38_0", 0x52, }, /* AM65X_EVM_APP_BRD_DET */ + { "gpio@38_1", 0x55, }, /* AM65X_EVM_LCD_BRD_DET */ + { "gpio@38_2", 0x54, }, /* AM65X_EVM_SERDES_BRD_DET */ + { "gpio@38_3", 0x53, }, /* AM65X_EVM_HDMI_GPMC_BRD_DET */ + }; + + /* Declaration of daughtercards to probe */ + const struct { + u8 slot_index; /* Slot the card is installed */ + char *card_name; /* EEPROM-programmed card name */ + char *dtbo_name; /* Device tree overlay to apply */ + u8 eth_offset; /* ethXaddr MAC address index offset */ + } cards[] = { + { + AM65X_EVM_APP_BRD_DET, + "AM6-GPAPPEVM", + "k3-am654-gp.dtbo", + 0, + }, + { + AM65X_EVM_APP_BRD_DET, + "AM6-IDKAPPEVM", + "k3-am654-idk.dtbo", + 3, + }, + { + AM65X_EVM_SERDES_BRD_DET, + "SER-PCIE2LEVM", + "k3-am654-pcie-usb2.dtbo", + 0, + }, + { + AM65X_EVM_SERDES_BRD_DET, + "SER-PCIEUSBEVM", + "k3-am654-pcie-usb3.dtbo", + 0, + }, + { + AM65X_EVM_LCD_BRD_DET, + "OLDI-LCD1EVM", + "k3-am654-evm-oldi-lcd1evm.dtbo", + 0, + }, + }; + + /* + * Initialize GPIO used for daughtercard slot presence detection and + * keep the resulting handles in local array for easier access. + */ + for (i = 0; i < AM65X_EVM_BRD_DET_COUNT; i++) { + ret = init_daughtercard_det_gpio(slot_map[i].gpio_name, + &board_det_gpios[i]); + if (ret < 0) + return ret; + } + + for (i = 0; i < ARRAY_SIZE(cards); i++) { + /* Obtain card-specific slot index and associated I2C address */ + u8 slot_index = cards[i].slot_index; + u8 i2c_addr = slot_map[slot_index].i2c_addr; + + /* + * The presence detection signal is active-low, hence skip + * over this card slot if anything other than 0 is returned. + */ + ret = dm_gpio_get_value(&board_det_gpios[slot_index]); + if (ret < 0) + return ret; + else if (ret) + continue; + + /* Get and parse the daughter card EEPROM record */ + ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, i2c_addr, + &ep, + (char **)mac_addr, + DAUGHTER_CARD_NO_OF_MAC_ADDR, + &mac_addr_cnt); + if (ret) { + pr_err("Reading daughtercard EEPROM at 0x%02x failed %d\n", + i2c_addr, ret); + /* + * Even this is pretty serious let's just skip over + * this particular daughtercard, rather than ending + * the probing process altogether. + */ + continue; + } + + /* Only process the parsed data if we found a match */ + if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name))) + continue; + + printf("detected %s\n", cards[i].card_name); + + /* + * Populate any MAC addresses from daughtercard into the U-Boot + * environment, starting with a card-specific offset so we can + * have multiple cards contribute to the MAC pool in a well- + * defined manner. + */ + for (j = 0; j < mac_addr_cnt; j++) { + if (!is_valid_ethaddr((u8 *)mac_addr[j])) + continue; + + eth_env_set_enetaddr_by_index("eth", + cards[i].eth_offset + j, + (uchar *)mac_addr[j]); + } + + /* Skip if no overlays are to be added */ + if (!strlen(cards[i].dtbo_name)) + continue; + + /* + * Make sure we are not running out of buffer space by checking + * if we can fit the new overlay, a trailing space to be used + * as a separator, plus the terminating zero. + */ + if (strlen(name_overlays) + strlen(cards[i].dtbo_name) + 2 > + sizeof(name_overlays)) + return -ENOMEM; + + /* Append to our list of overlays */ + strcat(name_overlays, cards[i].dtbo_name); + strcat(name_overlays, " "); + } + + /* Apply device tree overlay(s) to the U-Boot environment, if any */ + if (strlen(name_overlays)) + return env_set("name_overlays", name_overlays); + + return 0; +} + +int board_late_init(void) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + + setup_board_eeprom_env(); + + /* + * The first MAC address for ethernet a.k.a. ethernet0 comes from + * efuse populated via the am654 gigabit eth switch subsystem driver. + * All the other ones are populated via EEPROM, hence continue with + * an index of 1. + */ + board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt); + + /* Check for and probe any plugged-in daughtercards */ + probe_daughtercards(); + + return 0; +} diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index e258e22f371..32fa10599e8 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -8,6 +8,7 @@ */ #include <common.h> +#include <asm/arch/hardware.h> #include <asm/omap_common.h> #include <dm/uclass.h> #include <i2c.h> @@ -284,6 +285,191 @@ int __maybe_unused ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr) return 0; } +static int ti_i2c_eeprom_am6_parse_record(struct ti_am6_eeprom_record *record, + struct ti_am6_eeprom *ep, + char **mac_addr, + u8 mac_addr_max_cnt, + u8 *mac_addr_cnt) +{ + switch (record->header.id) { + case TI_AM6_EEPROM_RECORD_BOARD_INFO: + if (record->header.len != sizeof(record->data.board_info)) + return -EINVAL; + + if (!ep) + break; + + /* Populate (and clean, if needed) the board name */ + strlcpy(ep->name, record->data.board_info.name, + sizeof(ep->name)); + ti_eeprom_string_cleanup(ep->name); + + /* Populate selected other fields from the board info record */ + strlcpy(ep->version, record->data.board_info.version, + sizeof(ep->version)); + strlcpy(ep->software_revision, + record->data.board_info.software_revision, + sizeof(ep->software_revision)); + strlcpy(ep->serial, record->data.board_info.serial, + sizeof(ep->serial)); + break; + case TI_AM6_EEPROM_RECORD_MAC_INFO: + if (record->header.len != sizeof(record->data.mac_info)) + return -EINVAL; + + if (!mac_addr || !mac_addr_max_cnt) + break; + + *mac_addr_cnt = ((record->data.mac_info.mac_control & + TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK) >> + TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT) + 1; + + /* + * The EEPROM can (but may not) hold a very large amount + * of MAC addresses, by far exceeding what we want/can store + * in the common memory array, so only grab what we can fit. + * Note that a value of 0 means 1 MAC address, and so on. + */ + *mac_addr_cnt = min(*mac_addr_cnt, mac_addr_max_cnt); + + memcpy(mac_addr, record->data.mac_info.mac_addr, + *mac_addr_cnt * TI_EEPROM_HDR_ETH_ALEN); + break; + case 0x00: + /* Illegal value... Fall through... */ + case 0xFF: + /* Illegal value... Something went horribly wrong... */ + return -EINVAL; + default: + pr_warn("%s: Ignoring record id %u\n", __func__, + record->header.id); + } + + return 0; +} + +int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr, + struct ti_am6_eeprom *ep, + char **mac_addr, + u8 mac_addr_max_cnt, + u8 *mac_addr_cnt) +{ + struct udevice *dev; + struct udevice *bus; + unsigned int eeprom_addr; + struct ti_am6_eeprom_record_board_id board_id; + struct ti_am6_eeprom_record record; + int rc; + + /* Initialize with a known bad marker for i2c fails.. */ + memset(ep, 0, sizeof(*ep)); + ep->header = TI_DEAD_EEPROM_MAGIC; + + /* Read the board ID record which is always the first EEPROM record */ + rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC, + sizeof(board_id), (uint8_t *)&board_id); + if (rc) + return rc; + + if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) { + pr_err("%s: Invalid board ID record!\n", __func__); + return -EINVAL; + } + + /* Establish DM handle to board config EEPROM */ + rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus); + if (rc) + return rc; + rc = i2c_get_chip(bus, dev_addr, 1, &dev); + if (rc) + return rc; + + ep->header = TI_EEPROM_HEADER_MAGIC; + + /* Ready to parse TLV structure. Initialize variables... */ + *mac_addr_cnt = 0; + + /* + * After the all-encompassing board ID record all other records follow + * a TLV-type scheme. Point to the first such record and then start + * parsing those one by one. + */ + eeprom_addr = sizeof(board_id); + + while (true) { + rc = dm_i2c_read(dev, eeprom_addr, (uint8_t *)&record.header, + sizeof(record.header)); + if (rc) + return rc; + + /* + * Check for end of list marker. If we reached it don't go + * any further and stop parsing right here. + */ + if (record.header.id == TI_AM6_EEPROM_RECORD_END_LIST) + break; + + eeprom_addr += sizeof(record.header); + + debug("%s: dev_addr=0x%02x header.id=%u header.len=%u\n", + __func__, dev_addr, record.header.id, + record.header.len); + + /* Read record into memory if it fits */ + if (record.header.len <= sizeof(record.data)) { + rc = dm_i2c_read(dev, eeprom_addr, + (uint8_t *)&record.data, + record.header.len); + if (rc) + return rc; + + /* Process record */ + rc = ti_i2c_eeprom_am6_parse_record(&record, ep, + mac_addr, + mac_addr_max_cnt, + mac_addr_cnt); + if (rc) { + pr_err("%s: EEPROM parsing error!\n", __func__); + return rc; + } + } else { + /* + * We may get here in case of larger records which + * are not yet understood. + */ + pr_err("%s: Ignoring record id %u\n", __func__, + record.header.id); + } + + eeprom_addr += record.header.len; + } + + return 0; +} + +int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + int ret; + + /* + * Always execute EEPROM read by not allowing to bypass it during the + * first invocation of SPL which happens on the R5 core. + */ +#if !(defined(CONFIG_SPL_BUILD) && defined(CONFIG_CPU_V7R)) + if (ep->header == TI_EEPROM_HEADER_MAGIC) { + debug("%s: EEPROM has already been read\n", __func__); + return 0; + } +#endif + + ret = ti_i2c_eeprom_am6_get(bus_addr, dev_addr, ep, + (char **)ep->mac_addr, + AM6_EEPROM_HDR_NO_OF_MAC_ADDR, + &ep->mac_addr_cnt); + return ret; +} + bool __maybe_unused board_ti_is(char *name_tag) { struct ti_common_eeprom *ep = TI_EEPROM_DATA; @@ -348,6 +534,25 @@ fail: memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN); } +void __maybe_unused +board_ti_am6_get_eth_mac_addr(int index, + u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN]) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + + if (ep->header == TI_DEAD_EEPROM_MAGIC) + goto fail; + + if (index < 0 || index >= ep->mac_addr_cnt) + goto fail; + + memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN); + return; + +fail: + memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN); +} + u64 __maybe_unused board_ti_get_emif1_size(void) { struct ti_common_eeprom *ep = TI_EEPROM_DATA; @@ -391,6 +596,34 @@ void __maybe_unused set_board_info_env(char *name) env_set("board_serial", unknown); } +void __maybe_unused set_board_info_env_am6(char *name) +{ + char *unknown = "unknown"; + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + + if (name) + env_set("board_name", name); + else if (ep->name) + env_set("board_name", ep->name); + else + env_set("board_name", unknown); + + if (ep->version) + env_set("board_rev", ep->version); + else + env_set("board_rev", unknown); + + if (ep->software_revision) + env_set("board_software_revision", ep->software_revision); + else + env_set("board_software_revision", unknown); + + if (ep->serial) + env_set("board_serial", ep->serial); + else + env_set("board_serial", unknown); +} + static u64 mac_to_u64(u8 mac[6]) { int i; @@ -453,6 +686,19 @@ void board_ti_set_ethaddr(int index) } } +void board_ti_am6_set_ethaddr(int index, int count) +{ + u8 mac_addr[6]; + int i; + + for (i = 0; i < count; i++) { + board_ti_am6_get_eth_mac_addr(i, mac_addr); + if (is_valid_ethaddr(mac_addr)) + eth_env_set_enetaddr_by_index("eth", i + index, + mac_addr); + } +} + bool __maybe_unused board_ti_was_eeprom_read(void) { struct ti_common_eeprom *ep = TI_EEPROM_DATA; diff --git a/board/ti/common/board_detect.h b/board/ti/common/board_detect.h index f8495a7a7cf..a45d8961b9a 100644 --- a/board/ti/common/board_detect.h +++ b/board/ti/common/board_detect.h @@ -43,6 +43,133 @@ struct ti_am_eeprom { char mac_addr[TI_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; } __attribute__ ((__packed__)); +/* AM6x TI EVM EEPROM Definitions */ +#define TI_AM6_EEPROM_RECORD_BOARD_ID 0x01 +#define TI_AM6_EEPROM_RECORD_BOARD_INFO 0x10 +#define TI_AM6_EEPROM_RECORD_DDR_INFO 0x11 +#define TI_AM6_EEPROM_RECORD_DDR_SPD 0x12 +#define TI_AM6_EEPROM_RECORD_MAC_INFO 0x13 +#define TI_AM6_EEPROM_RECORD_END_LIST 0xFE + +/* + * Common header for AM6x TI EVM EEPROM records. Used to encapsulate the config + * EEPROM in its entirety as well as for individual records contained within. + */ +struct ti_am6_eeprom_record_header { + u8 id; + u16 len; +} __attribute__ ((__packed__)); + +/* AM6x TI EVM EEPROM board ID structure */ +struct ti_am6_eeprom_record_board_id { + u32 magic_number; + struct ti_am6_eeprom_record_header header; +} __attribute__ ((__packed__)); + +/* AM6x TI EVM EEPROM board info structure */ +#define AM6_EEPROM_HDR_NAME_LEN 16 +#define AM6_EEPROM_HDR_VERSION_LEN 2 +#define AM6_EEPROM_HDR_PROC_NR_LEN 4 +#define AM6_EEPROM_HDR_VARIANT_LEN 2 +#define AM6_EEPROM_HDR_PCB_REV_LEN 2 +#define AM6_EEPROM_HDR_SCH_BOM_REV_LEN 2 +#define AM6_EEPROM_HDR_SW_REV_LEN 2 +#define AM6_EEPROM_HDR_VID_LEN 2 +#define AM6_EEPROM_HDR_BLD_WK_LEN 2 +#define AM6_EEPROM_HDR_BLD_YR_LEN 2 +#define AM6_EEPROM_HDR_4P_NR_LEN 6 +#define AM6_EEPROM_HDR_SERIAL_LEN 4 + +struct ti_am6_eeprom_record_board_info { + char name[AM6_EEPROM_HDR_NAME_LEN]; + char version[AM6_EEPROM_HDR_VERSION_LEN]; + char proc_number[AM6_EEPROM_HDR_PROC_NR_LEN]; + char variant[AM6_EEPROM_HDR_VARIANT_LEN]; + char pcb_revision[AM6_EEPROM_HDR_PCB_REV_LEN]; + char schematic_bom_revision[AM6_EEPROM_HDR_SCH_BOM_REV_LEN]; + char software_revision[AM6_EEPROM_HDR_SW_REV_LEN]; + char vendor_id[AM6_EEPROM_HDR_VID_LEN]; + char build_week[AM6_EEPROM_HDR_BLD_WK_LEN]; + char build_year[AM6_EEPROM_HDR_BLD_YR_LEN]; + char board_4p_number[AM6_EEPROM_HDR_4P_NR_LEN]; + char serial[AM6_EEPROM_HDR_SERIAL_LEN]; +} __attribute__ ((__packed__)); + +/* Memory location to keep a copy of the AM6 board info record */ +#define TI_AM6_EEPROM_BD_INFO_DATA ((struct ti_am6_eeprom_record_board_info *) \ + TI_SRAM_SCRATCH_BOARD_EEPROM_START) + +/* AM6x TI EVM EEPROM DDR info structure */ +#define TI_AM6_EEPROM_DDR_CTRL_INSTANCE_MASK GENMASK(1, 0) +#define TI_AM6_EEPROM_DDR_CTRL_INSTANCE_SHIFT 0 +#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_MASK GENMASK(3, 2) +#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_NA (0 << 2) +#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_BOARDID (2 << 2) +#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_I2C51 (3 << 2) +#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_MASK GENMASK(5, 4) +#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_DDR3 (0 << 4) +#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_DDR4 (1 << 4) +#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_LPDDR4 (2 << 4) +#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_MASK GENMASK(7, 6) +#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_16 (0 << 6) +#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_32 (1 << 6) +#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_64 (2 << 6) +#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_MASK GENMASK(9, 8) +#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_8 (0 << 8) +#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_16 (1 << 8) +#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_32 (2 << 8) +#define TI_AM6_EEPROM_DDR_CTRL_RANKS_2 BIT(10) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_MASK GENMASK(13, 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_1GB (0 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_2GB (1 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_4GB (2 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_8GB (3 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_12GB (4 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_16GB (5 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_24GB (6 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_32GB (7 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_ECC BIT(14) + +struct ti_am6_eeprom_record_ddr_info { + u16 ddr_control; +} __attribute__ ((__packed__)); + +/* AM6x TI EVM EEPROM DDR SPD structure */ +#define TI_AM6_EEPROM_DDR_SPD_INSTANCE_MASK GENMASK(1, 0) +#define TI_AM6_EEPROM_DDR_SPD_INSTANCE_SHIFT 0 +#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_MASK GENMASK(4, 3) +#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_DDR3 (0 << 3) +#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_DDR4 (1 << 3) +#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_LPDDR4 (2 << 3) +#define TI_AM6_EEPROM_DDR_SPD_DATA_LEN 512 + +struct ti_am6_eeprom_record_ddr_spd { + u16 spd_control; + u8 data[TI_AM6_EEPROM_DDR_SPD_DATA_LEN]; +} __attribute__ ((__packed__)); + +/* AM6x TI EVM EEPROM MAC info structure */ +#define TI_AM6_EEPROM_MAC_INFO_INSTANCE_MASK GENMASK(2, 0) +#define TI_AM6_EEPROM_MAC_INFO_INSTANCE_SHIFT 0 +#define TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK GENMASK(7, 3) +#define TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT 3 +#define TI_AM6_EEPROM_MAC_ADDR_MAX_COUNT 32 + +struct ti_am6_eeprom_record_mac_info { + u16 mac_control; + u8 mac_addr[TI_AM6_EEPROM_MAC_ADDR_MAX_COUNT][TI_EEPROM_HDR_ETH_ALEN]; +} __attribute__ ((__packed__)); + +struct ti_am6_eeprom_record { + struct ti_am6_eeprom_record_header header; + union { + struct ti_am6_eeprom_record_board_info board_info; + struct ti_am6_eeprom_record_ddr_info ddr_info; + struct ti_am6_eeprom_record_ddr_spd ddr_spd; + struct ti_am6_eeprom_record_mac_info mac_info; + } data; +} __attribute__ ((__packed__)); + /* DRA7 EEPROM MAGIC Header identifier */ #define DRA7_EEPROM_HEADER_MAGIC 0xAA5533EE #define DRA7_EEPROM_HDR_NAME_LEN 16 @@ -99,6 +226,37 @@ struct ti_common_eeprom { #define TI_EEPROM_DATA ((struct ti_common_eeprom *)\ TI_SRAM_SCRATCH_BOARD_EEPROM_START) +/* + * Maximum number of Ethernet MAC addresses extracted from the AM6x on-board + * EEPROM during the initial probe and carried forward in SRAM. + */ +#define AM6_EEPROM_HDR_NO_OF_MAC_ADDR 8 + +/** + * struct ti_am6_eeprom - Null terminated, usable EEPROM contents, as extracted + * from the AM6 on-board EEPROM. Note that we only carry a subset of data + * at this time to be considerate about memory consumption. + * @header: Magic number for data validity indication + * @name: NULL terminated name + * @version: NULL terminated version + * @software_revision: NULL terminated software revision + * @serial: Board serial number + * @mac_addr_cnt: Number of MAC addresses stored in this object + * @mac_addr: MAC addresses + */ +struct ti_am6_eeprom { + u32 header; + char name[AM6_EEPROM_HDR_NAME_LEN + 1]; + char version[AM6_EEPROM_HDR_VERSION_LEN + 1]; + char software_revision[AM6_EEPROM_HDR_SW_REV_LEN + 1]; + char serial[AM6_EEPROM_HDR_SERIAL_LEN + 1]; + u8 mac_addr_cnt; + char mac_addr[AM6_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; +}; + +#define TI_AM6_EEPROM_DATA ((struct ti_am6_eeprom *) \ + TI_SRAM_SCRATCH_BOARD_EEPROM_START) + /** * ti_i2c_eeprom_am_get() - Consolidated eeprom data collection for AM* TI EVMs * @bus_addr: I2C bus address @@ -117,6 +275,33 @@ int ti_i2c_eeprom_am_get(int bus_addr, int dev_addr); int ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr); /** + * ti_i2c_eeprom_am6_get() - Consolidated eeprom data for AM6x TI EVMs and + * associated daughter cards, parsed into user- + * provided data structures + * @bus_addr: I2C bus address + * @dev_addr: I2C slave address + * @ep: Pointer to structure receiving AM6-specific header data + * @mac_addr: Pointer to memory receiving parsed MAC addresses. May be + * NULL to skip MAC parsing. + * @mac_addr_max_cnt: Maximum number of MAC addresses that can be stored into + * mac_addr. May be NULL to skip MAC parsing. + * @mac_addr_cnt: Pointer to a location returning how many MAC addressed got + * actually parsed. + */ +int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr, + struct ti_am6_eeprom *ep, + char **mac_addr, + u8 mac_addr_max_cnt, + u8 *mac_addr_cnt); + +/** + * ti_i2c_eeprom_am6_get_base() - Consolidated eeprom data for AM6x TI EVMs + * @bus_addr: I2C bus address + * @dev_addr: I2C slave address + */ +int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr); + +/** * board_ti_is() - Board detection logic for TI EVMs * @name_tag: Tag used in eeprom for the board * @@ -193,6 +378,15 @@ u64 board_ti_get_emif2_size(void); void set_board_info_env(char *name); /** + * set_board_info_env_am6() - Setup commonly used board information environment + * vars for AM6-type boards + * @name: Name of the board + * + * If name is NULL, default_name is used. + */ +void set_board_info_env_am6(char *name); + +/** * board_ti_set_ethaddr- Sets the ethaddr environment from EEPROM * @index: The first eth<index>addr environment variable to set * @@ -205,6 +399,18 @@ void set_board_info_env(char *name); void board_ti_set_ethaddr(int index); /** + * board_ti_am6_set_ethaddr- Sets the ethaddr environment from EEPROM + * @index: The first eth<index>addr environment variable to set + * @count: The number of MAC addresses to process + * + * EEPROM should be already read before calling this function. The EEPROM + * contains n dedicated MAC addresses. This function sets the ethaddr + * environment variable for all the available MAC addresses starting + * from eth<index>addr. + */ +void board_ti_am6_set_ethaddr(int index, int count); + +/** * board_ti_was_eeprom_read() - Check to see if the eeprom contents have been read * * This function is useful to determine if the eeprom has already been read and diff --git a/board/ti/ti816x/evm.c b/board/ti/ti816x/evm.c index 07a084bab8a..240df8cbe13 100644 --- a/board/ti/ti816x/evm.c +++ b/board/ti/ti816x/evm.c @@ -9,7 +9,6 @@ #include <common.h> #include <environment.h> #include <spl.h> -#include <netdev.h> #include <asm/cache.h> #include <asm/io.h> #include <asm/arch/clock.h> @@ -56,7 +55,7 @@ int board_eth_init(bd_t *bis) printf("Unable to read MAC address. Set <ethaddr>\n"); } - return davinci_emac_initialize(); + return 0; } #ifdef CONFIG_SPL_BUILD diff --git a/board/vamrs/rock960_rk3399/MAINTAINERS b/board/vamrs/rock960_rk3399/MAINTAINERS index 22b2db925ac..5ee52564953 100644 --- a/board/vamrs/rock960_rk3399/MAINTAINERS +++ b/board/vamrs/rock960_rk3399/MAINTAINERS @@ -1,11 +1,11 @@ ROCK960-RK3399 -M: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org +M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> S: Maintained F: board/rockchip/rock960_rk3399 F: include/configs/rock960_rk3399.h F: configs/rock960-rk3399_defconfig FICUS EE -M: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org +M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> S: Maintained F: configs/ficus-rk3399_defconfig |
