forked from dlink-dir_819/openwrt
		
	Add u-boot bootloader based on 2023.01 to support D1-based boards, currently: - Dongshan Nezha STU - LicheePi RV Dock - MangoPi MQ-Pro - Nezha D1 Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
		
			
				
	
	
		
			726 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			726 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From e3152c690732fb141500379f32fbe2203fa47059 Mon Sep 17 00:00:00 2001
 | |
| From: Samuel Holland <samuel@sholland.org>
 | |
| Date: Sat, 6 Aug 2022 00:48:38 -0500
 | |
| Subject: [PATCH 87/90] sunxi: Add temporary RISC-V version of board code
 | |
| 
 | |
| Signed-off-by: Samuel Holland <samuel@sholland.org>
 | |
| ---
 | |
|  board/sunxi/Makefile           |   3 +-
 | |
|  board/sunxi/board-riscv.c      | 687 +++++++++++++++++++++++++++++++++
 | |
|  include/configs/sunxi-common.h |   1 -
 | |
|  3 files changed, 689 insertions(+), 2 deletions(-)
 | |
|  create mode 100644 board/sunxi/board-riscv.c
 | |
| 
 | |
| --- a/board/sunxi/Makefile
 | |
| +++ b/board/sunxi/Makefile
 | |
| @@ -6,7 +6,8 @@
 | |
|  #
 | |
|  # (C) Copyright 2000-2003
 | |
|  # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 | |
| -obj-y	+= board.o
 | |
| +obj-$(CONFIG_ARM)		+= board.o
 | |
| +obj-$(CONFIG_RISCV)		+= board-riscv.o
 | |
|  obj-$(CONFIG_SUN7I_GMAC)	+= gmac.o
 | |
|  obj-$(CONFIG_MACH_SUN4I)	+= dram_sun4i_auto.o
 | |
|  obj-$(CONFIG_MACH_SUN5I)	+= dram_sun5i_auto.o
 | |
| --- /dev/null
 | |
| +++ b/board/sunxi/board-riscv.c
 | |
| @@ -0,0 +1,687 @@
 | |
| +// SPDX-License-Identifier: GPL-2.0+
 | |
| +/*
 | |
| + * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
 | |
| + * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 | |
| + *
 | |
| + * (C) Copyright 2007-2011
 | |
| + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
 | |
| + * Tom Cubie <tangliang@allwinnertech.com>
 | |
| + *
 | |
| + * Some board init for the Allwinner A10-evb board.
 | |
| + */
 | |
| +
 | |
| +#include <dm.h>
 | |
| +#include <cpu.h>
 | |
| +#include <env.h>
 | |
| +#include <env_internal.h>
 | |
| +#include <fdt_support.h>
 | |
| +#include <generic-phy.h>
 | |
| +#include <image.h>
 | |
| +#include <init.h>
 | |
| +#include <net.h>
 | |
| +#include <phy-sun4i-usb.h>
 | |
| +#include <ram.h>
 | |
| +#include <remoteproc.h>
 | |
| +#include <spl.h>
 | |
| +#include <status_led.h>
 | |
| +#include <sunxi_image.h>
 | |
| +#include <u-boot/crc.h>
 | |
| +#include <asm/csr.h>
 | |
| +#include <asm/global_data.h>
 | |
| +#include <asm/io.h>
 | |
| +
 | |
| +#ifdef CONFIG_RISCV
 | |
| +int board_init(void)
 | |
| +{
 | |
| +	/* https://lore.kernel.org/u-boot/31587574-4cd1-02da-9761-0134ac82b94b@sholland.org/ */
 | |
| +	return cpu_probe_all();
 | |
| +}
 | |
| +
 | |
| +int sunxi_get_sid(unsigned int *sid)
 | |
| +{
 | |
| +	return -ENODEV;
 | |
| +}
 | |
| +
 | |
| +#define SPL_ADDR		CONFIG_SUNXI_SRAM_ADDRESS
 | |
| +
 | |
| +/* The low 8-bits of the 'boot_media' field in the SPL header */
 | |
| +#define SUNXI_BOOTED_FROM_MMC0	0
 | |
| +#define SUNXI_BOOTED_FROM_NAND	1
 | |
| +#define SUNXI_BOOTED_FROM_MMC2	2
 | |
| +#define SUNXI_BOOTED_FROM_SPI	3
 | |
| +#define SUNXI_BOOTED_FROM_MMC0_HIGH	0x10
 | |
| +#define SUNXI_BOOTED_FROM_MMC2_HIGH	0x12
 | |
| +
 | |
| +#define SUNXI_INVALID_BOOT_SOURCE	-1
 | |
| +
 | |
| +static int sunxi_egon_valid(struct boot_file_head *egon_head)
 | |
| +{
 | |
| +	return !memcmp(egon_head->magic, BOOT0_MAGIC, 8); /* eGON.BT0 */
 | |
| +}
 | |
| +
 | |
| +static int sunxi_toc0_valid(struct toc0_main_info *toc0_info)
 | |
| +{
 | |
| +	return !memcmp(toc0_info->name, TOC0_MAIN_INFO_NAME, 8); /* TOC0.GLH */
 | |
| +}
 | |
| +
 | |
| +static int sunxi_get_boot_source(void)
 | |
| +{
 | |
| +	struct boot_file_head *egon_head = (void *)SPL_ADDR;
 | |
| +	struct toc0_main_info *toc0_info = (void *)SPL_ADDR;
 | |
| +
 | |
| +	/*
 | |
| +	 * On the ARMv5 SoCs, the SPL header in SRAM is overwritten by the
 | |
| +	 * exception vectors in U-Boot proper, so we won't find any
 | |
| +	 * information there. Also the FEL stash is only valid in the SPL,
 | |
| +	 * so we can't use that either. So if this is called from U-Boot
 | |
| +	 * proper, just return MMC0 as a placeholder, for now.
 | |
| +	 */
 | |
| +	if (IS_ENABLED(CONFIG_MACH_SUNIV) &&
 | |
| +	    !IS_ENABLED(CONFIG_SPL_BUILD))
 | |
| +		return SUNXI_BOOTED_FROM_MMC0;
 | |
| +
 | |
| +	if (sunxi_egon_valid(egon_head))
 | |
| +		return readb(&egon_head->boot_media);
 | |
| +	if (sunxi_toc0_valid(toc0_info))
 | |
| +		return readb(&toc0_info->platform[0]);
 | |
| +
 | |
| +	/* Not a valid image, so we must have been booted via FEL. */
 | |
| +	return SUNXI_INVALID_BOOT_SOURCE;
 | |
| +}
 | |
| +
 | |
| +/* The sunxi internal brom will try to loader external bootloader
 | |
| + * from mmc0, nand flash, mmc2.
 | |
| + */
 | |
| +uint32_t sunxi_get_boot_device(void)
 | |
| +{
 | |
| +	int boot_source = sunxi_get_boot_source();
 | |
| +
 | |
| +	/*
 | |
| +	 * When booting from the SD card or NAND memory, the "eGON.BT0"
 | |
| +	 * signature is expected to be found in memory at the address 0x0004
 | |
| +	 * (see the "mksunxiboot" tool, which generates this header).
 | |
| +	 *
 | |
| +	 * When booting in the FEL mode over USB, this signature is patched in
 | |
| +	 * memory and replaced with something else by the 'fel' tool. This other
 | |
| +	 * signature is selected in such a way, that it can't be present in a
 | |
| +	 * valid bootable SD card image (because the BROM would refuse to
 | |
| +	 * execute the SPL in this case).
 | |
| +	 *
 | |
| +	 * This checks for the signature and if it is not found returns to
 | |
| +	 * the FEL code in the BROM to wait and receive the main u-boot
 | |
| +	 * binary over USB. If it is found, it determines where SPL was
 | |
| +	 * read from.
 | |
| +	 */
 | |
| +	switch (boot_source) {
 | |
| +	case SUNXI_INVALID_BOOT_SOURCE:
 | |
| +		return BOOT_DEVICE_BOARD;
 | |
| +	case SUNXI_BOOTED_FROM_MMC0:
 | |
| +	case SUNXI_BOOTED_FROM_MMC0_HIGH:
 | |
| +		return BOOT_DEVICE_MMC1;
 | |
| +	case SUNXI_BOOTED_FROM_NAND:
 | |
| +		return BOOT_DEVICE_NAND;
 | |
| +	case SUNXI_BOOTED_FROM_MMC2:
 | |
| +	case SUNXI_BOOTED_FROM_MMC2_HIGH:
 | |
| +		return BOOT_DEVICE_MMC2;
 | |
| +	case SUNXI_BOOTED_FROM_SPI:
 | |
| +		return BOOT_DEVICE_SPI;
 | |
| +	}
 | |
| +
 | |
| +	panic("Unknown boot source %d\n", boot_source);
 | |
| +	return -1;		/* Never reached */
 | |
| +}
 | |
| +
 | |
| +uint32_t sunxi_get_spl_size(void)
 | |
| +{
 | |
| +	struct boot_file_head *egon_head = (void *)SPL_ADDR;
 | |
| +	struct toc0_main_info *toc0_info = (void *)SPL_ADDR;
 | |
| +
 | |
| +	if (sunxi_egon_valid(egon_head))
 | |
| +		return readl(&egon_head->length);
 | |
| +	if (sunxi_toc0_valid(toc0_info))
 | |
| +		return readl(&toc0_info->length);
 | |
| +
 | |
| +	/* Not a valid image, so use the default U-Boot offset. */
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +/*
 | |
| + * The eGON SPL image can be located at 8KB or at 128KB into an SD card or
 | |
| + * an eMMC device. The boot source has bit 4 set in the latter case.
 | |
| + * By adding 120KB to the normal offset when booting from a "high" location
 | |
| + * we can support both cases.
 | |
| + * Also U-Boot proper is located at least 32KB after the SPL, but will
 | |
| + * immediately follow the SPL if that is bigger than that.
 | |
| + */
 | |
| +unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
 | |
| +					   unsigned long raw_sect)
 | |
| +{
 | |
| +	unsigned long spl_size = sunxi_get_spl_size();
 | |
| +	unsigned long sector;
 | |
| +
 | |
| +	sector = max(raw_sect, spl_size / 512);
 | |
| +
 | |
| +	switch (sunxi_get_boot_source()) {
 | |
| +	case SUNXI_BOOTED_FROM_MMC0_HIGH:
 | |
| +	case SUNXI_BOOTED_FROM_MMC2_HIGH:
 | |
| +		sector += (128 - 8) * 2;
 | |
| +		break;
 | |
| +	}
 | |
| +
 | |
| +	printf("SPL size = %lu, sector = %lu\n", spl_size, sector);
 | |
| +
 | |
| +	return sector;
 | |
| +}
 | |
| +
 | |
| +u32 spl_boot_device(void)
 | |
| +{
 | |
| +	return sunxi_get_boot_device();
 | |
| +}
 | |
| +
 | |
| +#define CSR_MXSTATUS		0x7c0
 | |
| +#define CSR_MHCR		0x7c1
 | |
| +#define CSR_MCOR		0x7c2
 | |
| +#define CSR_MHINT		0x7c5
 | |
| +
 | |
| +int spl_board_init_f(void)
 | |
| +{
 | |
| +	int ret;
 | |
| +	struct udevice *dev;
 | |
| +
 | |
| +	/* DDR init */
 | |
| +	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 | |
| +	if (ret) {
 | |
| +		debug("DRAM init failed: %d\n", ret);
 | |
| +		return ret;
 | |
| +	}
 | |
| +
 | |
| +	/* Initialize extension CSRs. */
 | |
| +	printf("mxstatus=0x%08lx mhcr=0x%08lx mcor=0x%08lx mhint=0x%08lx\n",
 | |
| +	       csr_read(CSR_MXSTATUS),
 | |
| +	       csr_read(CSR_MHCR),
 | |
| +	       csr_read(CSR_MCOR),
 | |
| +	       csr_read(CSR_MHINT));
 | |
| +
 | |
| +	csr_set(CSR_MXSTATUS, 0x638000);
 | |
| +	csr_write(CSR_MCOR, 0x70013);
 | |
| +	csr_write(CSR_MHCR, 0x11ff);
 | |
| +	csr_write(CSR_MHINT, 0x16e30c);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +#ifdef CONFIG_SPL_BUILD
 | |
| +void spl_perform_fixups(struct spl_image_info *spl_image)
 | |
| +{
 | |
| +	struct ram_info info;
 | |
| +	struct udevice *dev;
 | |
| +	int ret;
 | |
| +
 | |
| +	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 | |
| +	if (ret)
 | |
| +		panic("No RAM device");
 | |
| +
 | |
| +	ret = ram_get_info(dev, &info);
 | |
| +	if (ret)
 | |
| +		panic("No RAM info");
 | |
| +
 | |
| +	ret = fdt_fixup_memory(spl_image->fdt_addr, info.base, info.size);
 | |
| +	if (ret)
 | |
| +		panic("Failed to update DTB");
 | |
| +}
 | |
| +#endif
 | |
| +#endif
 | |
| +
 | |
| +DECLARE_GLOBAL_DATA_PTR;
 | |
| +
 | |
| +/*
 | |
| + * Try to use the environment from the boot source first.
 | |
| + * For MMC, this means a FAT partition on the boot device (SD or eMMC).
 | |
| + * If the raw MMC environment is also enabled, this is tried next.
 | |
| + * When booting from NAND we try UBI first, then NAND directly.
 | |
| + * SPI flash falls back to FAT (on SD card).
 | |
| + */
 | |
| +enum env_location env_get_location(enum env_operation op, int prio)
 | |
| +{
 | |
| +	if (prio > 1)
 | |
| +		return ENVL_UNKNOWN;
 | |
| +
 | |
| +	/* NOWHERE is exclusive, no other option can be defined. */
 | |
| +	if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
 | |
| +		return ENVL_NOWHERE;
 | |
| +
 | |
| +	switch (sunxi_get_boot_device()) {
 | |
| +	case BOOT_DEVICE_MMC1:
 | |
| +	case BOOT_DEVICE_MMC2:
 | |
| +		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
 | |
| +			return ENVL_FAT;
 | |
| +		if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
 | |
| +			return ENVL_MMC;
 | |
| +		break;
 | |
| +	case BOOT_DEVICE_NAND:
 | |
| +		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_UBI))
 | |
| +			return ENVL_UBI;
 | |
| +		if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
 | |
| +			return ENVL_NAND;
 | |
| +		break;
 | |
| +	case BOOT_DEVICE_SPI:
 | |
| +		if (prio == 0 && IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
 | |
| +			return ENVL_SPI_FLASH;
 | |
| +		if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
 | |
| +			return ENVL_FAT;
 | |
| +		break;
 | |
| +	case BOOT_DEVICE_BOARD:
 | |
| +		break;
 | |
| +	default:
 | |
| +		break;
 | |
| +	}
 | |
| +
 | |
| +	/*
 | |
| +	 * If we come here for the first time, we *must* return a valid
 | |
| +	 * environment location other than ENVL_UNKNOWN, or the setup sequence
 | |
| +	 * in board_f() will silently hang. This is arguably a bug in
 | |
| +	 * env_init(), but for now pick one environment for which we know for
 | |
| +	 * sure to have a driver for. For all defconfigs this is either FAT
 | |
| +	 * or UBI, or NOWHERE, which is already handled above.
 | |
| +	 */
 | |
| +	if (prio == 0) {
 | |
| +		if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
 | |
| +			return ENVL_FAT;
 | |
| +		if (IS_ENABLED(CONFIG_ENV_IS_IN_UBI))
 | |
| +			return ENVL_UBI;
 | |
| +	}
 | |
| +
 | |
| +	return ENVL_UNKNOWN;
 | |
| +}
 | |
| +
 | |
| +/*
 | |
| + * On older SoCs the SPL is actually at address zero, so using NULL as
 | |
| + * an error value does not work.
 | |
| + */
 | |
| +#define INVALID_SPL_HEADER ((void *)~0UL)
 | |
| +
 | |
| +static struct boot_file_head * get_spl_header(uint8_t req_version)
 | |
| +{
 | |
| +	struct boot_file_head *spl = (void *)(ulong)SPL_ADDR;
 | |
| +	uint8_t spl_header_version = spl->spl_signature[3];
 | |
| +
 | |
| +	/* Is there really the SPL header (still) there? */
 | |
| +	if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) != 0)
 | |
| +		return INVALID_SPL_HEADER;
 | |
| +
 | |
| +	if (spl_header_version < req_version) {
 | |
| +		printf("sunxi SPL version mismatch: expected %u, got %u\n",
 | |
| +		       req_version, spl_header_version);
 | |
| +		return INVALID_SPL_HEADER;
 | |
| +	}
 | |
| +
 | |
| +	return spl;
 | |
| +}
 | |
| +
 | |
| +static const char *get_spl_dt_name(void)
 | |
| +{
 | |
| +	struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION);
 | |
| +
 | |
| +	/* Check if there is a DT name stored in the SPL header. */
 | |
| +	if (spl != INVALID_SPL_HEADER && spl->dt_name_offset)
 | |
| +		return (char *)spl + spl->dt_name_offset;
 | |
| +
 | |
| +	return NULL;
 | |
| +}
 | |
| +
 | |
| +#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
 | |
| +int mmc_get_env_dev(void)
 | |
| +{
 | |
| +	switch (sunxi_get_boot_device()) {
 | |
| +	case BOOT_DEVICE_MMC1:
 | |
| +		return 0;
 | |
| +	case BOOT_DEVICE_MMC2:
 | |
| +		return 1;
 | |
| +	default:
 | |
| +		return CONFIG_SYS_MMC_ENV_DEV;
 | |
| +	}
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +#ifdef CONFIG_SPL_BUILD
 | |
| +void sunxi_board_init(void)
 | |
| +{
 | |
| +#ifdef CONFIG_LED_STATUS
 | |
| +	if (IS_ENABLED(CONFIG_SPL_DRIVERS_MISC))
 | |
| +		status_led_init();
 | |
| +#endif
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +#ifdef CONFIG_USB_GADGET
 | |
| +int g_dnl_board_usb_cable_connected(void)
 | |
| +{
 | |
| +	struct udevice *dev;
 | |
| +	struct phy phy;
 | |
| +	int ret;
 | |
| +
 | |
| +	ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev);
 | |
| +	if (ret) {
 | |
| +		pr_err("%s: Cannot find USB device\n", __func__);
 | |
| +		return ret;
 | |
| +	}
 | |
| +
 | |
| +	ret = generic_phy_get_by_name(dev, "usb", &phy);
 | |
| +	if (ret) {
 | |
| +		pr_err("failed to get %s USB PHY\n", dev->name);
 | |
| +		return ret;
 | |
| +	}
 | |
| +
 | |
| +	ret = generic_phy_init(&phy);
 | |
| +	if (ret) {
 | |
| +		pr_debug("failed to init %s USB PHY\n", dev->name);
 | |
| +		return ret;
 | |
| +	}
 | |
| +
 | |
| +	return sun4i_usb_phy_vbus_detect(&phy);
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +#ifdef CONFIG_SERIAL_TAG
 | |
| +void get_board_serial(struct tag_serialnr *serialnr)
 | |
| +{
 | |
| +	char *serial_string;
 | |
| +	unsigned long long serial;
 | |
| +
 | |
| +	serial_string = env_get("serial#");
 | |
| +
 | |
| +	if (serial_string) {
 | |
| +		serial = simple_strtoull(serial_string, NULL, 16);
 | |
| +
 | |
| +		serialnr->high = (unsigned int) (serial >> 32);
 | |
| +		serialnr->low = (unsigned int) (serial & 0xffffffff);
 | |
| +	} else {
 | |
| +		serialnr->high = 0;
 | |
| +		serialnr->low = 0;
 | |
| +	}
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +/*
 | |
| + * Check the SPL header for the "sunxi" variant. If found: parse values
 | |
| + * that might have been passed by the loader ("fel" utility), and update
 | |
| + * the environment accordingly.
 | |
| + */
 | |
| +static void parse_spl_header(const uint32_t spl_addr)
 | |
| +{
 | |
| +	struct boot_file_head *spl = get_spl_header(SPL_ENV_HEADER_VERSION);
 | |
| +
 | |
| +	if (spl == INVALID_SPL_HEADER)
 | |
| +		return;
 | |
| +
 | |
| +	if (!spl->fel_script_address)
 | |
| +		return;
 | |
| +
 | |
| +	if (spl->fel_uEnv_length != 0) {
 | |
| +		/*
 | |
| +		 * data is expected in uEnv.txt compatible format, so "env
 | |
| +		 * import -t" the string(s) at fel_script_address right away.
 | |
| +		 */
 | |
| +		himport_r(&env_htab, (char *)(uintptr_t)spl->fel_script_address,
 | |
| +			  spl->fel_uEnv_length, '\n', H_NOCLEAR, 0, 0, NULL);
 | |
| +		return;
 | |
| +	}
 | |
| +	/* otherwise assume .scr format (mkimage-type script) */
 | |
| +	env_set_hex("fel_scriptaddr", spl->fel_script_address);
 | |
| +}
 | |
| +
 | |
| +static bool get_unique_sid(unsigned int *sid)
 | |
| +{
 | |
| +	if (sunxi_get_sid(sid) != 0)
 | |
| +		return false;
 | |
| +
 | |
| +	if (!sid[0])
 | |
| +		return false;
 | |
| +
 | |
| +	/*
 | |
| +	 * The single words 1 - 3 of the SID have quite a few bits
 | |
| +	 * which are the same on many models, so we take a crc32
 | |
| +	 * of all 3 words, to get a more unique value.
 | |
| +	 *
 | |
| +	 * Note we only do this on newer SoCs as we cannot change
 | |
| +	 * the algorithm on older SoCs since those have been using
 | |
| +	 * fixed mac-addresses based on only using word 3 for a
 | |
| +	 * long time and changing a fixed mac-address with an
 | |
| +	 * u-boot update is not good.
 | |
| +	 */
 | |
| +#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
 | |
| +    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
 | |
| +    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
 | |
| +	sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
 | |
| +#endif
 | |
| +
 | |
| +	/* Ensure the NIC specific bytes of the mac are not all 0 */
 | |
| +	if ((sid[3] & 0xffffff) == 0)
 | |
| +		sid[3] |= 0x800000;
 | |
| +
 | |
| +	return true;
 | |
| +}
 | |
| +
 | |
| +/*
 | |
| + * Note this function gets called multiple times.
 | |
| + * It must not make any changes to env variables which already exist.
 | |
| + */
 | |
| +static void setup_environment(const void *fdt)
 | |
| +{
 | |
| +	char serial_string[17] = { 0 };
 | |
| +	unsigned int sid[4];
 | |
| +	uint8_t mac_addr[6];
 | |
| +	char ethaddr[16];
 | |
| +	int i;
 | |
| +
 | |
| +	if (!get_unique_sid(sid))
 | |
| +		return;
 | |
| +
 | |
| +	for (i = 0; i < 4; i++) {
 | |
| +		sprintf(ethaddr, "ethernet%d", i);
 | |
| +		if (!fdt_get_alias(fdt, ethaddr))
 | |
| +			continue;
 | |
| +
 | |
| +		if (i == 0)
 | |
| +			strcpy(ethaddr, "ethaddr");
 | |
| +		else
 | |
| +			sprintf(ethaddr, "eth%daddr", i);
 | |
| +
 | |
| +		if (env_get(ethaddr))
 | |
| +			continue;
 | |
| +
 | |
| +		/* Non OUI / registered MAC address */
 | |
| +		mac_addr[0] = (i << 4) | 0x02;
 | |
| +		mac_addr[1] = (sid[0] >>  0) & 0xff;
 | |
| +		mac_addr[2] = (sid[3] >> 24) & 0xff;
 | |
| +		mac_addr[3] = (sid[3] >> 16) & 0xff;
 | |
| +		mac_addr[4] = (sid[3] >>  8) & 0xff;
 | |
| +		mac_addr[5] = (sid[3] >>  0) & 0xff;
 | |
| +
 | |
| +		eth_env_set_enetaddr(ethaddr, mac_addr);
 | |
| +	}
 | |
| +
 | |
| +	if (!env_get("serial#")) {
 | |
| +		snprintf(serial_string, sizeof(serial_string),
 | |
| +			"%08x%08x", sid[0], sid[3]);
 | |
| +
 | |
| +		env_set("serial#", serial_string);
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +int misc_init_r(void)
 | |
| +{
 | |
| +	const char *spl_dt_name;
 | |
| +	uint boot;
 | |
| +
 | |
| +	env_set("fel_booted", NULL);
 | |
| +	env_set("fel_scriptaddr", NULL);
 | |
| +	env_set("mmc_bootdev", NULL);
 | |
| +
 | |
| +	boot = sunxi_get_boot_device();
 | |
| +	/* determine if we are running in FEL mode */
 | |
| +	if (boot == BOOT_DEVICE_BOARD) {
 | |
| +		env_set("fel_booted", "1");
 | |
| +		parse_spl_header(SPL_ADDR);
 | |
| +	/* or if we booted from MMC, and which one */
 | |
| +	} else if (boot == BOOT_DEVICE_MMC1) {
 | |
| +		env_set("mmc_bootdev", "0");
 | |
| +	} else if (boot == BOOT_DEVICE_MMC2) {
 | |
| +		env_set("mmc_bootdev", "1");
 | |
| +	}
 | |
| +
 | |
| +	/* Set fdtfile to match the FIT configuration chosen in SPL. */
 | |
| +	spl_dt_name = get_spl_dt_name();
 | |
| +	if (spl_dt_name) {
 | |
| +		char *prefix = IS_ENABLED(CONFIG_ARM64) ? "allwinner/" : "";
 | |
| +		char str[64];
 | |
| +
 | |
| +		snprintf(str, sizeof(str), "%s%s.dtb", prefix, spl_dt_name);
 | |
| +		env_set("fdtfile", str);
 | |
| +	}
 | |
| +
 | |
| +	setup_environment(gd->fdt_blob);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +int board_late_init(void)
 | |
| +{
 | |
| +#ifdef CONFIG_USB_ETHER
 | |
| +	usb_ether_init();
 | |
| +#endif
 | |
| +
 | |
| +#ifdef SUNXI_SCP_BASE
 | |
| +	if (!rproc_load(0, SUNXI_SCP_BASE, SUNXI_SCP_MAX_SIZE)) {
 | |
| +		puts("Starting SCP...\n");
 | |
| +		rproc_start(0);
 | |
| +	}
 | |
| +#endif
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static void bluetooth_dt_fixup(void *blob)
 | |
| +{
 | |
| +	/* Some devices ship with a Bluetooth controller default address.
 | |
| +	 * Set a valid address through the device tree.
 | |
| +	 */
 | |
| +	uchar tmp[ETH_ALEN], bdaddr[ETH_ALEN];
 | |
| +	unsigned int sid[4];
 | |
| +	int i;
 | |
| +
 | |
| +	if (!CONFIG_BLUETOOTH_DT_DEVICE_FIXUP[0])
 | |
| +		return;
 | |
| +
 | |
| +	if (eth_env_get_enetaddr("bdaddr", tmp)) {
 | |
| +		/* Convert between the binary formats of the corresponding stacks */
 | |
| +		for (i = 0; i < ETH_ALEN; ++i)
 | |
| +			bdaddr[i] = tmp[ETH_ALEN - i - 1];
 | |
| +	} else {
 | |
| +		if (!get_unique_sid(sid))
 | |
| +			return;
 | |
| +
 | |
| +		bdaddr[0] = ((sid[3] >>  0) & 0xff) ^ 1;
 | |
| +		bdaddr[1] = (sid[3] >>  8) & 0xff;
 | |
| +		bdaddr[2] = (sid[3] >> 16) & 0xff;
 | |
| +		bdaddr[3] = (sid[3] >> 24) & 0xff;
 | |
| +		bdaddr[4] = (sid[0] >>  0) & 0xff;
 | |
| +		bdaddr[5] = 0x02;
 | |
| +	}
 | |
| +
 | |
| +	do_fixup_by_compat(blob, CONFIG_BLUETOOTH_DT_DEVICE_FIXUP,
 | |
| +			   "local-bd-address", bdaddr, ETH_ALEN, 1);
 | |
| +}
 | |
| +
 | |
| +int ft_board_setup(void *blob, struct bd_info *bd)
 | |
| +{
 | |
| +	int __maybe_unused r;
 | |
| +
 | |
| +	/*
 | |
| +	 * Call setup_environment and fdt_fixup_ethernet again
 | |
| +	 * in case the boot fdt has ethernet aliases the u-boot
 | |
| +	 * copy does not have.
 | |
| +	 */
 | |
| +	setup_environment(blob);
 | |
| +	fdt_fixup_ethernet(blob);
 | |
| +
 | |
| +	bluetooth_dt_fixup(blob);
 | |
| +
 | |
| +#ifdef CONFIG_VIDEO_DT_SIMPLEFB
 | |
| +	r = sunxi_simplefb_setup(blob);
 | |
| +	if (r)
 | |
| +		return r;
 | |
| +#endif
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +#ifdef CONFIG_SPL_LOAD_FIT
 | |
| +
 | |
| +static void set_spl_dt_name(const char *name)
 | |
| +{
 | |
| +	struct boot_file_head *spl = get_spl_header(SPL_ENV_HEADER_VERSION);
 | |
| +
 | |
| +	if (spl == INVALID_SPL_HEADER)
 | |
| +		return;
 | |
| +
 | |
| +	/* Promote the header version for U-Boot proper, if needed. */
 | |
| +	if (spl->spl_signature[3] < SPL_DT_HEADER_VERSION)
 | |
| +		spl->spl_signature[3] = SPL_DT_HEADER_VERSION;
 | |
| +
 | |
| +	strcpy((char *)&spl->string_pool, name);
 | |
| +	spl->dt_name_offset = offsetof(struct boot_file_head, string_pool);
 | |
| +}
 | |
| +
 | |
| +int board_fit_config_name_match(const char *name)
 | |
| +{
 | |
| +	const char *best_dt_name = get_spl_dt_name();
 | |
| +	int ret;
 | |
| +
 | |
| +#ifdef CONFIG_DEFAULT_DEVICE_TREE
 | |
| +	if (best_dt_name == NULL)
 | |
| +		best_dt_name = CONFIG_DEFAULT_DEVICE_TREE;
 | |
| +#endif
 | |
| +
 | |
| +	if (best_dt_name == NULL) {
 | |
| +		/* No DT name was provided, so accept the first config. */
 | |
| +		return 0;
 | |
| +	}
 | |
| +#ifdef CONFIG_PINE64_DT_SELECTION
 | |
| +	if (strstr(best_dt_name, "-pine64-plus")) {
 | |
| +		/* Differentiate the Pine A64 boards by their DRAM size. */
 | |
| +		if ((gd->ram_size == 512 * 1024 * 1024))
 | |
| +			best_dt_name = "sun50i-a64-pine64";
 | |
| +	}
 | |
| +#endif
 | |
| +#ifdef CONFIG_PINEPHONE_DT_SELECTION
 | |
| +	if (strstr(best_dt_name, "-pinephone")) {
 | |
| +		/* Differentiate the PinePhone revisions by GPIO inputs. */
 | |
| +		prcm_apb0_enable(PRCM_APB0_GATE_PIO);
 | |
| +		sunxi_gpio_set_pull(SUNXI_GPL(6), SUNXI_GPIO_PULL_UP);
 | |
| +		sunxi_gpio_set_cfgpin(SUNXI_GPL(6), SUNXI_GPIO_INPUT);
 | |
| +		udelay(100);
 | |
| +
 | |
| +		/* PL6 is pulled low by the modem on v1.2. */
 | |
| +		if (gpio_get_value(SUNXI_GPL(6)) == 0)
 | |
| +			best_dt_name = "sun50i-a64-pinephone-1.2";
 | |
| +		else
 | |
| +			best_dt_name = "sun50i-a64-pinephone-1.1";
 | |
| +
 | |
| +		sunxi_gpio_set_cfgpin(SUNXI_GPL(6), SUNXI_GPIO_DISABLE);
 | |
| +		sunxi_gpio_set_pull(SUNXI_GPL(6), SUNXI_GPIO_PULL_DISABLE);
 | |
| +		prcm_apb0_disable(PRCM_APB0_GATE_PIO);
 | |
| +	}
 | |
| +#endif
 | |
| +
 | |
| +	ret = strcmp(name, best_dt_name);
 | |
| +
 | |
| +	/*
 | |
| +	 * If one of the FIT configurations matches the most accurate DT name,
 | |
| +	 * update the SPL header to provide that DT name to U-Boot proper.
 | |
| +	 */
 | |
| +	if (ret == 0)
 | |
| +		set_spl_dt_name(best_dt_name);
 | |
| +
 | |
| +	return ret;
 | |
| +}
 | |
| +#endif
 | |
| --- a/include/configs/sunxi-common.h
 | |
| +++ b/include/configs/sunxi-common.h
 | |
| @@ -12,7 +12,6 @@
 | |
|  #ifndef _SUNXI_COMMON_CONFIG_H
 | |
|  #define _SUNXI_COMMON_CONFIG_H
 | |
|  
 | |
| -#include <asm/arch/cpu.h>
 | |
|  #include <linux/stringify.h>
 | |
|  
 | |
|  /* Serial & console */
 |