diff options
Diffstat (limited to 'roms/u-boot/board/synopsys')
37 files changed, 3192 insertions, 0 deletions
diff --git a/roms/u-boot/board/synopsys/MAINTAINERS b/roms/u-boot/board/synopsys/MAINTAINERS new file mode 100644 index 000000000..b9bfd3c2e --- /dev/null +++ b/roms/u-boot/board/synopsys/MAINTAINERS @@ -0,0 +1,8 @@ +- BOARD +M: Alexey Brodkin <abrodkin@synopsys.com> +S: Maintained +F: include/configs/nsim.h +F: configs/nsim_700_defconfig +F: configs/nsim_700be_defconfig +F: configs/nsim_hs38_defconfig +F: configs/nsim_hs38be_defconfig diff --git a/roms/u-boot/board/synopsys/axs10x/Kconfig b/roms/u-boot/board/synopsys/axs10x/Kconfig new file mode 100644 index 000000000..dd1305adc --- /dev/null +++ b/roms/u-boot/board/synopsys/axs10x/Kconfig @@ -0,0 +1,12 @@ +if TARGET_AXS101 || TARGET_AXS103 + +config SYS_BOARD + default "axs10x" + +config SYS_VENDOR + default "synopsys" + +config SYS_CONFIG_NAME + default "axs10x" + +endif diff --git a/roms/u-boot/board/synopsys/axs10x/MAINTAINERS b/roms/u-boot/board/synopsys/axs10x/MAINTAINERS new file mode 100644 index 000000000..abb890b71 --- /dev/null +++ b/roms/u-boot/board/synopsys/axs10x/MAINTAINERS @@ -0,0 +1,7 @@ +AXS10X BOARD +M: Alexey Brodkin <abrodkin@synopsys.com> +S: Maintained +F: board/synopsys/axs10x/ +F: include/configs/axs10x.h +F: configs/axs101_defconfig +F: configs/axs103_defconfig diff --git a/roms/u-boot/board/synopsys/axs10x/Makefile b/roms/u-boot/board/synopsys/axs10x/Makefile new file mode 100644 index 000000000..dd5ee680e --- /dev/null +++ b/roms/u-boot/board/synopsys/axs10x/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2013-2016 Synopsys, Inc. All rights reserved. + +obj-y += axs10x.o diff --git a/roms/u-boot/board/synopsys/axs10x/axs10x.c b/roms/u-boot/board/synopsys/axs10x/axs10x.c new file mode 100644 index 000000000..75e4d0376 --- /dev/null +++ b/roms/u-boot/board/synopsys/axs10x/axs10x.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#include <common.h> +#include <cpu_func.h> +#include <dwmmc.h> +#include <init.h> +#include <malloc.h> +#include <asm/arcregs.h> +#include <asm/global_data.h> +#include "axs10x.h" +#include <asm/cache.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define AXS_MB_CREG 0xE0011000 + +int board_early_init_f(void) +{ + if (readl((void __iomem *)AXS_MB_CREG + 0x234) & (1 << 28)) + gd->board_type = AXS_MB_V3; + else + gd->board_type = AXS_MB_V2; + + return 0; +} + +#ifdef CONFIG_ISA_ARCV2 + +void board_jump_and_run(ulong entry, int zero, int arch, uint params) +{ + void (*kernel_entry)(int zero, int arch, uint params); + + kernel_entry = (void (*)(int, int, uint))entry; + + smp_set_core_boot_addr(entry, -1); + smp_kick_all_cpus(); + kernel_entry(zero, arch, params); +} + +#define RESET_VECTOR_ADDR 0x0 + +void smp_set_core_boot_addr(unsigned long addr, int corenr) +{ + /* All cores have reset vector pointing to 0 */ + writel(addr, (void __iomem *)RESET_VECTOR_ADDR); + + /* Make sure other cores see written value in memory */ + flush_dcache_all(); +} + +void smp_kick_all_cpus(void) +{ +/* CPU start CREG */ +#define AXC003_CREG_CPU_START 0xF0001400 +/* Bits positions in CPU start CREG */ +#define BITS_START 0 +#define BITS_START_MODE 4 +#define BITS_CORE_SEL 9 + +/* + * In axs103 v1.1 START bits semantics has changed quite a bit. + * We used to have a generic START bit for all cores selected by CORE_SEL mask. + * But now we don't touch CORE_SEL at all because we have a dedicated START bit + * for each core: + * bit 0: Core 0 (master) + * bit 1: Core 1 (slave) + */ +#define BITS_START_CORE1 1 + +#define ARCVER_HS38_3_0 0x53 + + int core_family = read_aux_reg(ARC_AUX_IDENTITY) & 0xff; + int cmd = readl((void __iomem *)AXC003_CREG_CPU_START); + + if (core_family < ARCVER_HS38_3_0) { + cmd |= (1 << BITS_CORE_SEL) | (1 << BITS_START); + cmd &= ~(1 << BITS_START_MODE); + } else { + cmd |= (1 << BITS_START_CORE1); + } + writel(cmd, (void __iomem *)AXC003_CREG_CPU_START); +} +#endif + +int checkboard(void) +{ + printf("Board: ARC Software Development Platform AXS%s\n", + is_isa_arcv2() ? "103" : "101"); + + return 0; +}; diff --git a/roms/u-boot/board/synopsys/axs10x/axs10x.h b/roms/u-boot/board/synopsys/axs10x/axs10x.h new file mode 100644 index 000000000..69541cc57 --- /dev/null +++ b/roms/u-boot/board/synopsys/axs10x/axs10x.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015 Synopsys, Inc. All rights reserved. + */ + +#ifndef _BOARD_SYNOPSYS_AXS10X_H +#define _BOARD_SYNOPSYS_AXS10X_H + +enum { + AXS_MB_V2, + AXS_MB_V3 +}; + +#endif /* _BOARD_SYNOPSYS_AXS10X_H */ + diff --git a/roms/u-boot/board/synopsys/axs10x/config.mk b/roms/u-boot/board/synopsys/axs10x/config.mk new file mode 100644 index 000000000..ccac54429 --- /dev/null +++ b/roms/u-boot/board/synopsys/axs10x/config.mk @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. + +ifdef CONFIG_TARGET_AXS103 + PLATFORM_CPPFLAGS += -mcpu=archs +else + PLATFORM_CPPFLAGS += -mcpu=arc700 -mlock -mswape +endif + +bsp-generate: u-boot u-boot.bin +ifdef CONFIG_ISA_ARCV2 + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-axs.py \ + --header-type v2 \ + --arc-id 0x53 \ + --spi-flash-offset 0x200000 \ + --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot +else + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-axs.py \ + --header-type v1 \ + --arc-id 0x434 \ + --spi-flash-offset 0x0 \ + --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot +endif + $(Q)tools/mkimage -T script -C none -n 'uboot update script' \ + -d $(srctree)/u-boot-update.txt \ + $(srctree)/u-boot-update.img &> /dev/null diff --git a/roms/u-boot/board/synopsys/axs10x/headerize-axs.py b/roms/u-boot/board/synopsys/axs10x/headerize-axs.py new file mode 100644 index 000000000..fa6aaf350 --- /dev/null +++ b/roms/u-boot/board/synopsys/axs10x/headerize-axs.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 + +#we can use binascii instead of zlib +import os, getopt, sys, zlib +from elftools.elf.elffile import ELFFile + + +def usage(exit_code): + print("typical usage:") + print("AXS101:") + print(sys.argv[0] + \ + " --header-type v1 --arc-id 0x434 --spi-flash-offset 0x0 --image u-boot.bin --elf u-boot") + print("AXS103:") + print(sys.argv[0] + \ + " --header-type v2 --arc-id 0x53 --spi-flash-offset 0x200000 --image u-boot.bin --elf u-boot") + sys.exit(exit_code) + + +def elf_get_entry(filename): + with open(filename, 'rb') as f: + elffile = ELFFile(f) + return elffile.header['e_entry'] + + +def calc_check_sum(filename): + # Calculate u-boot image check_sum: it is sum of all u-boot binary bytes + with open(filename, "rb") as file: + ba = bytearray(file.read()) + return sum(ba) & 0xFF + + +def arg_verify(uboot_bin_filename, uboot_elf_filename, header_type): + if not os.path.isfile(uboot_bin_filename): + print("uboot bin file not exists: " + uboot_bin_filename) + sys.exit(2) + + if not os.path.isfile(uboot_elf_filename): + print("uboot elf file not exists: " + uboot_elf_filename) + sys.exit(2) + + if header_type not in ("v1", "v2"): + print("unknown header type: " + header_type) + print("choose between 'v1' (most likely AXS101) and 'v2' (most likely AXS103)") + sys.exit(2) + + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], + "ht:a:s:i:l:e:", + ["help", "header-type=", "arc-id=", "spi-flash-offset=", "image=", "elf="]) + except getopt.GetoptError as err: + print(err) + usage(2) + + # default filenames + uboot_elf_filename = "u-boot" + uboot_bin_filename = "u-boot.bin" + headerised_filename = "u-boot.head" + uboot_scrypt_file = "u-boot-update.txt" + + # default values + spi_flash_offset = 0x200000 + header_type = "v2" + arc_id = 0x53 + + # initial header values: place where preloader will store u-boot binary, + # should be equal to CONFIG_SYS_TEXT_BASE + image_copy_adr = 0x81000000 + + # initial constant header values, do not change these values + magic1 = 0xdeadbeafaf # big endian byte order + magic2 = [ # big endian byte order + 0x20202a2020202020202020202a20202020207c5c2e20202020202e2f7c20202020207c2d, + 0x2e5c2020202f2e2d7c20202020205c2020602d2d2d6020202f20202020202f205f202020, + 0x205f20205c20202020207c205f60712070205f207c2020202020272e5f3d2f205c3d5f2e, + 0x272020202020202020605c202f60202020202020202020202020206f2020202020202020] + + for opt, arg in opts: + if opt in ('-h', "--help"): usage(0) + if opt in ('-t', "--header-type"): header_type = arg + if opt in ('-a', "--arc-id"): arc_id = int(arg, 16) + if opt in ('-s', "--spi-flash-offset"): spi_flash_offset = int(arg, 16) + if opt in ('-i', "--image"): uboot_bin_filename = arg + if opt in ('-e', "--elf"): uboot_elf_filename = arg + + arg_verify(uboot_bin_filename, uboot_elf_filename, header_type) + + uboot_img_size = os.path.getsize(uboot_bin_filename) + jump_address = elf_get_entry(uboot_elf_filename) + check_sum = calc_check_sum(uboot_bin_filename) + + # Calculate header adresses depend on header type + if header_type == "v2": + image_copy_adr -= 0x4 + uboot_img_size += 0x4 + # we append image so we need to append checksum + jmpchk_sum = sum(jump_address.to_bytes(4, byteorder='big')) + check_sum = (check_sum + jmpchk_sum) & 0xFF + imade_jump_append = True + else: + imade_jump_append = False + + # write header to file + with open(headerised_filename, "wb") as file: + file.write(arc_id.to_bytes(2, byteorder='little')) + file.write(uboot_img_size.to_bytes(4, byteorder='little')) + file.write(check_sum.to_bytes(1, byteorder='little')) + file.write(image_copy_adr.to_bytes(4, byteorder='little')) + file.write(magic1.to_bytes(5, byteorder='big')) + for i in range(16): file.write(0x00.to_bytes(1, byteorder='little')) + for byte in magic2: file.write(byte.to_bytes(36, byteorder='big')) + for i in range(224 - len(magic2) * 36): + file.write(0x00.to_bytes(1, byteorder='little')) + if imade_jump_append: + file.write(jump_address.to_bytes(4, byteorder='little')) + + # append u-boot image to header + with open(headerised_filename, "ab") as fo: + with open(uboot_bin_filename,'rb') as fi: + fo.write(fi.read()) + + # calc u-boot headerised image CRC32 (will be used by uboot update + # command for check) + headerised_image_crc = "" + with open(headerised_filename, "rb") as fi: + headerised_image_crc = hex(zlib.crc32(fi.read()) & 0xffffffff) + + load_addr = 0x81000000 + crc_store_adr = load_addr - 0x8 + crc_calc_adr = crc_store_adr - 0x4 + load_size = os.path.getsize(headerised_filename) + crc_calc_cmd = \ + "crc32 " + hex(load_addr) + " " + hex(load_size) + " " + hex(crc_calc_adr) + crc_check_cmd = \ + "mw.l " + hex(crc_store_adr) + " " + headerised_image_crc + " && " + \ + crc_calc_cmd + " && " + \ + "cmp.l " + hex(crc_store_adr) + " " + hex(crc_calc_adr) + " 1" + + # make errase size to be allighned by 64K + if load_size & 0xFFFF == 0: + errase_size = load_size + else: + errase_size = load_size - (load_size & 0xFFFF) + 0x10000 + + # Hack to handle n25*** flash protect ops weirdness: + # protect unlock return fail status is region is already unlock (entire or + # partially). Same for lock ops. + # As there is no possibility to check current flash status pretend + # unlock & lock always success. + sf_unlock_cmd = \ + "if sf protect unlock 0x0 0x4000000 ; then true ; else true ; fi" + sf_lock_cmd = \ + "if sf protect lock 0x0 0x4000000 ; then true ; else true ; fi" + + # u-bood CMD to load u-bood with header to SPI flash + sf_load_image_cmd = \ + "fatload mmc 0:1 " + hex(load_addr) + " " + headerised_filename + " && " + \ + "sf probe 0:0 && " + \ + sf_unlock_cmd + " && " + \ + "sf erase " + hex(spi_flash_offset) + " " + hex(errase_size) + " && " + \ + "sf write " + hex(load_addr) + " " + hex(spi_flash_offset) + " " + hex(load_size) + " && " + \ + sf_lock_cmd + + update_uboot_cmd = sf_load_image_cmd + " && echo \"u-boot update: OK\"" + + with open(uboot_scrypt_file, "wb") as fo: + fo.write(update_uboot_cmd.encode('ascii')) + + +if __name__ == "__main__": + try: + main() + except Exception as err: + print(err) + sys.exit(2) diff --git a/roms/u-boot/board/synopsys/emsdp/Kconfig b/roms/u-boot/board/synopsys/emsdp/Kconfig new file mode 100644 index 000000000..8228bb5c7 --- /dev/null +++ b/roms/u-boot/board/synopsys/emsdp/Kconfig @@ -0,0 +1,12 @@ +if TARGET_EMSDP + +config SYS_BOARD + default "emsdp" + +config SYS_VENDOR + default "synopsys" + +config SYS_CONFIG_NAME + default "emsdp" + +endif diff --git a/roms/u-boot/board/synopsys/emsdp/MAINTAINERS b/roms/u-boot/board/synopsys/emsdp/MAINTAINERS new file mode 100644 index 000000000..640401395 --- /dev/null +++ b/roms/u-boot/board/synopsys/emsdp/MAINTAINERS @@ -0,0 +1,6 @@ +EM DEVELOPMENT KIT BOARD +M: Alexey Brodkin <abrodkin@synopsys.com> +S: Maintained +F: arch/arc/dts/emsdp.dts +F: board/synopsys/emsdp/ +F: configs/emsdp_defconfig diff --git a/roms/u-boot/board/synopsys/emsdp/Makefile b/roms/u-boot/board/synopsys/emsdp/Makefile new file mode 100644 index 000000000..733a48c46 --- /dev/null +++ b/roms/u-boot/board/synopsys/emsdp/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += emsdp.o diff --git a/roms/u-boot/board/synopsys/emsdp/README b/roms/u-boot/board/synopsys/emsdp/README new file mode 100644 index 000000000..036554c4d --- /dev/null +++ b/roms/u-boot/board/synopsys/emsdp/README @@ -0,0 +1,83 @@ +================================================================================ +Useful notes on bulding and using of U-Boot on +ARC EM Software Development Platform (AKA EMSDP) +================================================================================ + + BOARD OVERVIEW + + The DesignWare ARC EM Software Development Platform is FPGA-bases platform + for rapid software development on the ARC EM family of processors. + + Since this board is based on FPGA it's possible to load and use different + versions of ARC EM CPUs. U-Boot is built to be run on the simplest + possible configuration which means the same one binary will work on more + advanced configurations as well. + + The board has the following features useful for U-Boot: + * On-board 2-channel FTDI TTL-to-USB converter + - The first channel is used for serial debug port (which makes it possible + to use a serial connection on pretty much any host machine be it + Windows, Linux or Mac). + On Linux machine typucally FTDI serial port would be /dev/ttyUSB0. + There's no HW flow-control and baud-rate is 115200. + + - The second channel is used for built-in Digilent USB JTAG probe. + That means no extra hardware is required to access ARC core from a + debugger on development host. Both proprietary MetaWare debugger and + open source OpenOCD + GDB client are supported. + + - Also with help of this FTDI chip it is possible to reset entire + board with help of a special `rff-ftdi-reset` utility, see: + https://github.com/foss-for-synopsys-dwc-arc-processors/rff-ftdi-reset + + * Micro SD-card slot + - U-Boot expects to see the very first partition on the card formatted as + FAT file-system and uses it for keeping its environment in `uboot.env` + file. Note uboot.env is not just a text file but it is auto-generated + file created by U-Boot on invocation of `saveenv` command. + It contains a checksum which makes this saved environment invalid in + case of maual modification. + + - There might be more useful files on that first FAT partition like + user applications, data files etc. + + * 256 KiB of "ROM" + - This so-called "ROM" is a part of FPGA image and even though it + might be unlocked for writes its initial content will be restored + on the next power-on. + + + BUILDING U-BOOT + + 1. Configure U-Boot: + ------------------------->8---------------------- + make emsdp_defconfig + ------------------------->8---------------------- + + 2. To build Elf file (for example to be used with host debugger via JTAG + connection to the target board): + ------------------------->8---------------------- + make mdbtrick + ------------------------->8---------------------- + + This will produce `u-boot` Elf file. + + 3. To build binary image to be put in "ROM": + ------------------------->8---------------------- + make u-boot.bin + ------------------------->8---------------------- + + + EXECUTING U-BOOT + + 1. The EMSDP board is supposed to auto-start U-Boot image stored in ROM on + power-on. For that make sure VCCIO DIP-switches are all in "off" state. + + 2. Though it is possible to load U-Boot as a simple Elf file via JTAG right + in "ROM" and start it from the debugger. One important note here we first + need to enable writes into "ROM" by writing 1 to 0xf0001000. + + 2.1. In case of proprietary MetaWare debugger run: + ------------------------->8---------------------- + mdb -digilent -OK -preloadexec="eval *(int*)0xf0001000=0" u-boot + ------------------------->8---------------------- diff --git a/roms/u-boot/board/synopsys/emsdp/config.mk b/roms/u-boot/board/synopsys/emsdp/config.mk new file mode 100644 index 000000000..5bd10442a --- /dev/null +++ b/roms/u-boot/board/synopsys/emsdp/config.mk @@ -0,0 +1,2 @@ +PLATFORM_CPPFLAGS += -mcpu=arcem -mlittle-endian -mnorm -mswap -mmpy-option=3 \ + -mbarrel-shifter -mfpu=fpuda_all -mcode-density diff --git a/roms/u-boot/board/synopsys/emsdp/emsdp.c b/roms/u-boot/board/synopsys/emsdp/emsdp.c new file mode 100644 index 000000000..a3cee2341 --- /dev/null +++ b/roms/u-boot/board/synopsys/emsdp/emsdp.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + */ + +#include <common.h> +#include <command.h> +#include <cpu_func.h> +#include <dwmmc.h> +#include <init.h> +#include <malloc.h> +#include <asm/global_data.h> +#include <linux/bitops.h> + +#include <asm/arcregs.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define ARC_PERIPHERAL_BASE 0xF0000000 + +#define CGU_ARC_FMEAS_ARC (void *)(ARC_PERIPHERAL_BASE + 0x84) +#define CGU_ARC_FMEAS_ARC_START BIT(31) +#define CGU_ARC_FMEAS_ARC_DONE BIT(30) +#define CGU_ARC_FMEAS_ARC_CNT_MASK GENMASK(14, 0) +#define CGU_ARC_FMEAS_ARC_RCNT_OFFSET 0 +#define CGU_ARC_FMEAS_ARC_FCNT_OFFSET 15 + +#define SDIO_BASE (void *)(ARC_PERIPHERAL_BASE + 0x10000) + +int mach_cpu_init(void) +{ + int rcnt, fcnt; + u32 data; + + /* Start frequency measurement */ + writel(CGU_ARC_FMEAS_ARC_START, CGU_ARC_FMEAS_ARC); + + /* Poll DONE bit */ + do { + data = readl(CGU_ARC_FMEAS_ARC); + } while (!(data & CGU_ARC_FMEAS_ARC_DONE)); + + /* Amount of reference 100 MHz clocks */ + rcnt = ((data >> CGU_ARC_FMEAS_ARC_RCNT_OFFSET) & + CGU_ARC_FMEAS_ARC_CNT_MASK); + + /* Amount of CPU clocks */ + fcnt = ((data >> CGU_ARC_FMEAS_ARC_FCNT_OFFSET) & + CGU_ARC_FMEAS_ARC_CNT_MASK); + + gd->cpu_clk = ((100 * fcnt) / rcnt) * 1000000; + + return 0; +} + +int board_early_init_r(void) +{ +#define EMSDP_PSRAM_BASE 0xf2001000 +#define PSRAM_FLASH_CONFIG_REG_0 (void *)(EMSDP_PSRAM_BASE + 0x10) +#define PSRAM_FLASH_CONFIG_REG_1 (void *)(EMSDP_PSRAM_BASE + 0x14) +#define CRE_ENABLE BIT(31) +#define CRE_DRIVE_CMD BIT(6) + +#define PSRAM_RCR_DPD BIT(1) +#define PSRAM_RCR_PAGE_MODE BIT(7) + +/* + * PSRAM_FLASH_CONFIG_REG_x[30:15] to the address lines[16:1] of flash, + * thus "<< 1". + */ +#define PSRAM_RCR_SETUP ((PSRAM_RCR_DPD | PSRAM_RCR_PAGE_MODE) << 1) + + // Switch PSRAM controller to command mode + writel(CRE_ENABLE | CRE_DRIVE_CMD, PSRAM_FLASH_CONFIG_REG_0); + // Program Refresh Configuration Register (RCR) for BANK0 + writew(0, (void *)(0x10000000 + PSRAM_RCR_SETUP)); + // Switch PSRAM controller back to memory mode + writel(0, PSRAM_FLASH_CONFIG_REG_0); + + + // Switch PSRAM controller to command mode + writel(CRE_ENABLE | CRE_DRIVE_CMD, PSRAM_FLASH_CONFIG_REG_1); + // Program Refresh Configuration Register (RCR) for BANK1 + writew(0, (void *)(0x10800000 + PSRAM_RCR_SETUP)); + // Switch PSRAM controller back to memory mode + writel(0, PSRAM_FLASH_CONFIG_REG_1); + + printf("PSRAM initialized.\n"); + + return 0; +} + +#define CREG_BASE 0xF0001000 +#define CREG_BOOT (void *)(CREG_BASE + 0x0FF0) +#define CREG_IP_SW_RESET (void *)(CREG_BASE + 0x0FF0) +#define CREG_IP_VERSION (void *)(CREG_BASE + 0x0FF8) + +/* Bits in CREG_BOOT register */ +#define CREG_BOOT_WP_BIT BIT(8) + +void reset_cpu(void) +{ + writel(1, CREG_IP_SW_RESET); + while (1) + ; /* loop forever till reset */ +} + +static int do_emsdp_rom(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + u32 creg_boot = readl(CREG_BOOT); + + if (!strcmp(argv[1], "unlock")) + creg_boot &= ~CREG_BOOT_WP_BIT; + else if (!strcmp(argv[1], "lock")) + creg_boot |= CREG_BOOT_WP_BIT; + else + return CMD_RET_USAGE; + + writel(creg_boot, CREG_BOOT); + + return CMD_RET_SUCCESS; +} + +struct cmd_tbl cmd_emsdp[] = { + U_BOOT_CMD_MKENT(rom, 2, 0, do_emsdp_rom, "", ""), +}; + +static int do_emsdp(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct cmd_tbl *c; + + c = find_cmd_tbl(argv[1], cmd_emsdp, ARRAY_SIZE(cmd_emsdp)); + + /* Strip off leading 'emsdp' command */ + argc--; + argv++; + + if (c == NULL || argc > c->maxargs) + return CMD_RET_USAGE; + + return c->cmd(cmdtp, flag, argc, argv); +} + +U_BOOT_CMD( + emsdp, CONFIG_SYS_MAXARGS, 0, do_emsdp, + "Synopsys EMSDP specific commands", + "rom unlock - Unlock non-volatile memory for writing\n" + "emsdp rom lock - Lock non-volatile memory to prevent writing\n" +); + +int checkboard(void) +{ + int version = readl(CREG_IP_VERSION); + + printf("Board: ARC EM Software Development Platform v%d.%d\n", + (version >> 16) & 0xff, version & 0xff); + return 0; +}; diff --git a/roms/u-boot/board/synopsys/hsdk/Kconfig b/roms/u-boot/board/synopsys/hsdk/Kconfig new file mode 100644 index 000000000..d9c0e27a4 --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/Kconfig @@ -0,0 +1,30 @@ +if TARGET_HSDK + +config SYS_BOARD + default "hsdk" + +config SYS_VENDOR + default "synopsys" + +config SYS_CONFIG_NAME + default "hsdk" if BOARD_HSDK + default "hsdk-4xd" if BOARD_HSDK_4XD + +choice + prompt "HSDK board type" + default BOARD_HSDK + +config BOARD_HSDK + bool "ARC HS Development Kit" + help + ARC HS Development Kit based on quard core ARC HS38 processor + +config BOARD_HSDK_4XD + bool "ARC HS4x/HS4xD Development Kit" + help + ARC HS4x/HS4xD Development Kit based on quard core ARC HS48/HS47D + processor + +endchoice + +endif diff --git a/roms/u-boot/board/synopsys/hsdk/MAINTAINERS b/roms/u-boot/board/synopsys/hsdk/MAINTAINERS new file mode 100644 index 000000000..73f71fd06 --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/MAINTAINERS @@ -0,0 +1,8 @@ +HSDK BOARDs +M: Eugeniy Paltsev <paltsev@synopsys.com> +S: Maintained +F: board/synopsys/hsdk/ +F: configs/hsdk_defconfig +F: configs/hsdk_4xd_defconfig +F: include/configs/hsdk-4xd.h +F: include/configs/hsdk.h diff --git a/roms/u-boot/board/synopsys/hsdk/Makefile b/roms/u-boot/board/synopsys/hsdk/Makefile new file mode 100644 index 000000000..e9cd6a63e --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2017 Synopsys, Inc. All rights reserved. + +obj-y += hsdk.o +obj-y += env-lib.o +obj-y += clk-lib.o diff --git a/roms/u-boot/board/synopsys/hsdk/README b/roms/u-boot/board/synopsys/hsdk/README new file mode 100644 index 000000000..9155f17c6 --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/README @@ -0,0 +1,128 @@ +================================================================================ +Useful notes on bulding and using of U-Boot on ARC HS Development Kit (AKA HSDK) +================================================================================ + + BOARD OVERVIEW + + The DesignWare ARC HS Development Kit is a ready-to-use platform for rapid + software development on the ARC HS3x family of processors. + + For more information please visit: + https://www.synopsys.com/dw/ipdir.php?ds=arc-hs-development-kit + + User guide is availalble here: + https://github.com/foss-for-synopsys-dwc-arc-processors/ARC-Development-Systems-Forum/wiki/docs/ARC_HSDK_User_Guide.pdf + + It has the following features useful for U-Boot: + * On-board 2-channel FTDI TTL-to-USB converter + - The first channel is used for serial debug port (which makes it possible + to use a serial connection on pretty much any host machine be it + Windows, Linux or Mac). + On Linux machine typucally FTDI serial port would be /dev/ttyUSB0. + There's no HW flow-control and baud-rate is 115200. + + - The second channel is used for built-in Digilent USB JTAG probe. + That means no extra hardware is required to access ARC core from a + debugger on development host. Both proprietary MetaWare debugger and + open source OpenOCD + GDB client are supported. + + - Also with help of this FTDI chip it is possible to reset entire + board with help of a special `rff-ftdi-reset` utility, see: + https://github.com/foss-for-synopsys-dwc-arc-processors/rff-ftdi-reset + + * Micro SD-card slot + - U-Boot expects to see the very first partition on the card formatted as + FAT file-system and uses it for keeping its environment in `uboot.env` + file. Note uboot.env is not just a text file but it is auto-generated + file created by U-Boot on invocation of `saveenv` command. + It contains a checksum which makes this saved environment invalid in + case of maual modification. + + - There might be more useful files on that first FAT partition like + Linux kernl image in form of uImage (with or without built-in + initramfs), device tree blob (.dtb) etc. + + - Except FAT partition there might be others following the first FAT one + like Ext file-system with rootfs etc. + + * 1 Gb Ethernet socket + - U-Boot might get payload from TFTP server. This might be uImage, rootfs + image and anything else. + + * 2 MiB of SPI-flash + - SPI-flahs is used as a storage for image of an application auto-executed + by bootROM on power-on. Typically U-Boot gets programmed there but + there might be other uses. But note bootROM expects to find a special + header preceeding application image itself so before flashing anything + make sure required image is prepended. In case of U-Boot this is done + by invocation of `headerize-hsdk.py` with `make bsp-generate` command. + + + BUILDING U-BOOT + + 1. Configure U-Boot: + ------------------------->8---------------------- + make hsdk_defconfig + ------------------------->8---------------------- + + 2. To build Elf file (for example to be used with host debugger via JTAG + connection to the target board): + ------------------------->8---------------------- + make mdbtrick + ------------------------->8---------------------- + + This will produce `u-boot` Elf file. + + 3. To build artifacts required for U-Boot update in n-board SPI-flash: + ------------------------->8---------------------- + make bsp-generate + ------------------------->8---------------------- + + This will produce `u-boot.head` and `u-boot-update.scr` which should + be put on the first FAT partition of micro SD-card to be inserted in the + HSDK board. + + Note that Python3 script is used for generation of a header, thus + to get that done it's required to have Python3 with "pyelftools" installed. + + "pyelftools" could be installed with help of "pip" even w/o root rights: + ------------------------->8---------------------- + python3 -m pip install --user pyelftools + ------------------------->8---------------------- + + EXECUTING U-BOOT + + 1. The HSDK board is supposed to auto-start U-Boot image stored in on-board + SPI-flash on power-on. For that make sure DIP-switches in the corner of + the board are in their default positions: BIM in 1:off, 2:on state + while both BMC and BCS should be in 1:on, 2:on state. + + 2. Though it is possible to load U-Boot as a simple Elf file via JTAG right + in DDR and start it from the debugger. + + 2.1. In case of proprietary MetaWare debugger run: + ------------------------->8---------------------- + mdb -digilent -run -cl u-boot + ------------------------->8---------------------- + + + UPDATION U-BOOT IMAGE IN ON-BOARD SPI-FLASH + + 1. Create `u-boot.head` and `u-boot-update.scr` as discribed above with + `make bsp-generate` command. + + 2. Copy `u-boot.head` and `u-boot-update.scr` to the first FAT partition + of micro SD-card. + + 3. Connect USB cable from the HSDK board to the developemnt host and + fire-up serial terminal. + + 3. Insert prepared micro SD-card in the HSDK board, press reset button + and stop auto-execution of existing `bootcmd` pressing any key in serial + terminal and enter the following command: + ------------------------->8---------------------- + mmc rescan && fatload mmc 0:1 ${loadaddr} u-boot-update.scr && source ${loadaddr} + ------------------------->8---------------------- + Wait before you see "u-boot update: OK" message. + + 4. Press RESET button and enjoy updated U-Boot version. diff --git a/roms/u-boot/board/synopsys/hsdk/clk-lib.c b/roms/u-boot/board/synopsys/hsdk/clk-lib.c new file mode 100644 index 000000000..bd43179fc --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/clk-lib.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> + */ + +#include <clk.h> +#include <log.h> +#include <malloc.h> +#include <dm/device.h> + +#include "clk-lib.h" + +#define HZ_IN_MHZ 1000000 +#define ceil(x, y) ({ ulong __x = (x), __y = (y); (__x + __y - 1) / __y; }) + +int soc_clk_ctl(const char *name, ulong *rate, enum clk_ctl_ops ctl) +{ + int ret; + ulong mhz_rate, priv_rate; + struct clk clk; + + /* Dummy fmeas device, just to be able to use standard clk_* api */ + struct udevice fmeas = { + .name = "clk-fmeas", + }; + dev_set_ofnode(&fmeas, ofnode_path("/clk-fmeas")); + + ret = clk_get_by_name(&fmeas, name, &clk); + if (ret) { + pr_err("clock '%s' not found, err=%d\n", name, ret); + return ret; + } + + if (ctl & CLK_ON) { + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) + return ret; + } + + if ((ctl & CLK_SET) && rate) { + priv_rate = ctl & CLK_MHZ ? (*rate) * HZ_IN_MHZ : *rate; + ret = clk_set_rate(&clk, priv_rate); + if (ret) + return ret; + } + + if (ctl & CLK_OFF) { + ret = clk_disable(&clk); + if (ret) { + pr_err("clock '%s' can't be disabled, err=%d\n", name, ret); + return ret; + } + } + + priv_rate = clk_get_rate(&clk); + + clk_free(&clk); + + mhz_rate = ceil(priv_rate, HZ_IN_MHZ); + + if (ctl & CLK_MHZ) + priv_rate = mhz_rate; + + if ((ctl & CLK_GET) && rate) + *rate = priv_rate; + + if ((ctl & CLK_PRINT) && (ctl & CLK_MHZ)) + printf("HSDK: clock '%s' rate %lu MHz\n", name, priv_rate); + else if (ctl & CLK_PRINT) + printf("HSDK: clock '%s' rate %lu Hz\n", name, priv_rate); + else + debug("HSDK: clock '%s' rate %lu MHz\n", name, mhz_rate); + + return 0; +} diff --git a/roms/u-boot/board/synopsys/hsdk/clk-lib.h b/roms/u-boot/board/synopsys/hsdk/clk-lib.h new file mode 100644 index 000000000..970bcd4a1 --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/clk-lib.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> + */ + +#ifndef __BOARD_CLK_LIB_H +#define __BOARD_CLK_LIB_H + +#include <common.h> +#include <linux/bitops.h> + +enum clk_ctl_ops { + CLK_SET = BIT(0), /* set frequency */ + CLK_GET = BIT(1), /* get frequency */ + CLK_ON = BIT(2), /* enable clock */ + CLK_OFF = BIT(3), /* disable clock */ + CLK_PRINT = BIT(4), /* print frequency */ + CLK_MHZ = BIT(5) /* all values in MHZ instead of HZ */ +}; + +/* + * Depending on the clk_ctl_ops enable / disable / + * set clock rate from 'rate' argument / read clock to 'rate' argument / + * print clock rate. If CLK_MHZ flag set in clk_ctl_ops 'rate' is in MHz, + * otherwise - in Hz. + * + * This function expects "clk-fmeas" node in device tree: + * / { + * clk-fmeas { + * clocks = <&cpu_pll>, <&sys_pll>; + * clock-names = "cpu-pll", "sys-pll"; + * }; + * }; + */ +int soc_clk_ctl(const char *name, ulong *rate, enum clk_ctl_ops ctl); + +#endif /* __BOARD_CLK_LIB_H */ diff --git a/roms/u-boot/board/synopsys/hsdk/config.mk b/roms/u-boot/board/synopsys/hsdk/config.mk new file mode 100644 index 000000000..def944aad --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/config.mk @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. + +ifdef CONFIG_BOARD_HSDK +PLATFORM_CPPFLAGS += -mcpu=hs38_linux -mlittle-endian -matomic -mll64 \ + -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ + -mfpu=fpud_all + +bsp-generate: u-boot u-boot.bin + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ + --arc-id 0x52 --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot + $(Q)tools/mkimage -T script -C none -n 'uboot update script' \ + -d $(srctree)/u-boot-update.txt \ + $(srctree)/u-boot-update.scr &> /dev/null +endif + +ifdef CONFIG_BOARD_HSDK_4XD +PLATFORM_CPPFLAGS += -mcpu=hs4x_rel31 -mlittle-endian -matomic -mll64 \ + -mdiv-rem -mswap -mnorm -mmpy-option=9 -mbarrel-shifter \ + -mfpu=fpud_all + +bsp-generate: u-boot u-boot.bin + $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \ + --arc-id 0x54 --image $(srctree)/u-boot.bin \ + --elf $(srctree)/u-boot + $(Q)tools/mkimage -T script -C none -n 'uboot update script' \ + -d $(srctree)/u-boot-update.txt \ + $(srctree)/u-boot-update.scr &> /dev/null +endif diff --git a/roms/u-boot/board/synopsys/hsdk/env-lib.c b/roms/u-boot/board/synopsys/hsdk/env-lib.c new file mode 100644 index 000000000..235f29565 --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/env-lib.c @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> + */ + +#include "env-lib.h" +#include <env.h> +#include <log.h> + +#define MAX_CMD_LEN 25 + +static void env_clear_common(u32 index, const struct env_map_common *map) +{ + map[index].val->val = 0; + map[index].val->set = false; +} + +static int env_read_common(u32 index, const struct env_map_common *map) +{ + u32 val; + + if (!env_get_yesno(map[index].env_name)) { + if (map[index].type == ENV_HEX) { + val = (u32)env_get_hex(map[index].env_name, 0); + debug("ENV: %s: = %#x\n", map[index].env_name, val); + } else { + val = (u32)env_get_ulong(map[index].env_name, 10, 0); + debug("ENV: %s: = %d\n", map[index].env_name, val); + } + + map[index].val->val = val; + map[index].val->set = true; + } + + return 0; +} + +static void env_clear_core(u32 index, const struct env_map_percpu *map) +{ + for (u32 i = 0; i < NR_CPUS; i++) { + (*map[index].val)[i].val = 0; + (*map[index].val)[i].set = false; + } +} + +static int env_read_core(u32 index, const struct env_map_percpu *map) +{ + u32 val; + char command[MAX_CMD_LEN]; + + for (u32 i = 0; i < NR_CPUS; i++) { + sprintf(command, "%s_%u", map[index].env_name, i); + if (!env_get_yesno(command)) { + if (map[index].type == ENV_HEX) { + val = (u32)env_get_hex(command, 0); + debug("ENV: %s: = %#x\n", command, val); + } else { + val = (u32)env_get_ulong(command, 10, 0); + debug("ENV: %s: = %d\n", command, val); + } + + (*map[index].val)[i].val = val; + (*map[index].val)[i].set = true; + } + } + + return 0; +} + +static int env_validate_common(u32 index, const struct env_map_common *map) +{ + u32 value = map[index].val->val; + bool set = map[index].val->set; + u32 min = map[index].min; + u32 max = map[index].max; + + /* Check if environment is mandatory */ + if (map[index].mandatory && !set) { + pr_err("Variable \'%s\' is mandatory, but it is not defined\n", + map[index].env_name); + + return -EINVAL; + } + + /* Check environment boundary */ + if (set && (value < min || value > max)) { + if (map[index].type == ENV_HEX) + pr_err("Variable \'%s\' must be between %#x and %#x\n", + map[index].env_name, min, max); + else + pr_err("Variable \'%s\' must be between %u and %u\n", + map[index].env_name, min, max); + + return -EINVAL; + } + + return 0; +} + +static int env_validate_core(u32 index, const struct env_map_percpu *map, + bool (*cpu_used)(u32)) +{ + u32 value; + bool set; + bool mandatory = map[index].mandatory; + u32 min, max; + + for (u32 i = 0; i < NR_CPUS; i++) { + set = (*map[index].val)[i].set; + value = (*map[index].val)[i].val; + + /* Check if environment is mandatory */ + if (cpu_used(i) && mandatory && !set) { + pr_err("CPU %u is used, but \'%s_%u\' is not defined\n", + i, map[index].env_name, i); + + return -EINVAL; + } + + min = map[index].min[i]; + max = map[index].max[i]; + + /* Check environment boundary */ + if (set && (value < min || value > max)) { + if (map[index].type == ENV_HEX) + pr_err("Variable \'%s_%u\' must be between %#x and %#x\n", + map[index].env_name, i, min, max); + else + pr_err("Variable \'%s_%u\' must be between %d and %d\n", + map[index].env_name, i, min, max); + + return -EINVAL; + } + } + + return 0; +} + +void envs_cleanup_core(const struct env_map_percpu *map) +{ + /* Cleanup env struct first */ + for (u32 i = 0; map[i].env_name; i++) + env_clear_core(i, map); +} + +void envs_cleanup_common(const struct env_map_common *map) +{ + /* Cleanup env struct first */ + for (u32 i = 0; map[i].env_name; i++) + env_clear_common(i, map); +} + +int envs_read_common(const struct env_map_common *map) +{ + int ret; + + for (u32 i = 0; map[i].env_name; i++) { + ret = env_read_common(i, map); + if (ret) + return ret; + } + + return 0; +} + +int envs_validate_common(const struct env_map_common *map) +{ + int ret; + + for (u32 i = 0; map[i].env_name; i++) { + ret = env_validate_common(i, map); + if (ret) + return ret; + } + + return 0; +} + +int envs_read_validate_common(const struct env_map_common *map) +{ + int ret; + + envs_cleanup_common(map); + + ret = envs_read_common(map); + if (ret) + return ret; + + ret = envs_validate_common(map); + if (ret) + return ret; + + return 0; +} + +int envs_read_validate_core(const struct env_map_percpu *map, + bool (*cpu_used)(u32)) +{ + int ret; + + envs_cleanup_core(map); + + for (u32 i = 0; map[i].env_name; i++) { + ret = env_read_core(i, map); + if (ret) + return ret; + } + + for (u32 i = 0; map[i].env_name; i++) { + ret = env_validate_core(i, map, cpu_used); + if (ret) + return ret; + } + + return 0; +} + +int envs_process_and_validate(const struct env_map_common *common, + const struct env_map_percpu *core, + bool (*cpu_used)(u32)) +{ + int ret; + + ret = envs_read_validate_common(common); + if (ret) + return ret; + + ret = envs_read_validate_core(core, cpu_used); + if (ret) + return ret; + + return 0; +} + +static int args_envs_read_search(const struct env_map_common *map, + int argc, char *const argv[]) +{ + for (int i = 0; map[i].env_name; i++) { + if (!strcmp(argv[0], map[i].env_name)) + return i; + } + + pr_err("Unexpected argument '%s', can't parse\n", argv[0]); + + return -ENOENT; +} + +static int arg_read_set(const struct env_map_common *map, u32 i, int argc, + char *const argv[]) +{ + char *endp = argv[1]; + + if (map[i].type == ENV_HEX) + map[i].val->val = simple_strtoul(argv[1], &endp, 16); + else + map[i].val->val = simple_strtoul(argv[1], &endp, 10); + + map[i].val->set = true; + + if (*endp == '\0') + return 0; + + pr_err("Unexpected argument '%s', can't parse\n", argv[1]); + + map[i].val->set = false; + + return -EINVAL; +} + +int args_envs_enumerate(const struct env_map_common *map, int enum_by, + int argc, char *const argv[]) +{ + u32 i; + + if (argc % enum_by) { + pr_err("unexpected argument number: %d\n", argc); + return -EINVAL; + } + + while (argc > 0) { + i = args_envs_read_search(map, argc, argv); + if (i < 0) + return i; + + debug("ARG: found '%s' with index %d\n", map[i].env_name, i); + + if (i < 0) { + pr_err("unknown arg: %s\n", argv[0]); + return -EINVAL; + } + + if (arg_read_set(map, i, argc, argv)) + return -EINVAL; + + debug("ARG: value.s '%s' == %#x\n", argv[1], map[i].val->val); + + argc -= enum_by; + argv += enum_by; + } + + return 0; +} diff --git a/roms/u-boot/board/synopsys/hsdk/env-lib.h b/roms/u-boot/board/synopsys/hsdk/env-lib.h new file mode 100644 index 000000000..48c17c4d4 --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/env-lib.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> + */ + +#ifndef __BOARD_ENV_LIB_H +#define __BOARD_ENV_LIB_H + +#include <common.h> +#include <config.h> +#include <linux/kernel.h> + +enum env_type { + ENV_DEC, + ENV_HEX +}; + +typedef struct { + u32 val; + bool set; +} u32_env; + +struct env_map_common { + const char *const env_name; + enum env_type type; + bool mandatory; + u32 min; + u32 max; + u32_env *val; +}; + +struct env_map_percpu { + const char *const env_name; + enum env_type type; + bool mandatory; + u32 min[NR_CPUS]; + u32 max[NR_CPUS]; + u32_env (*val)[NR_CPUS]; +}; + +void envs_cleanup_common(const struct env_map_common *map); +int envs_read_common(const struct env_map_common *map); +int envs_validate_common(const struct env_map_common *map); +int envs_read_validate_common(const struct env_map_common *map); + +void envs_cleanup_core(const struct env_map_percpu *map); +int envs_read_validate_core(const struct env_map_percpu *map, + bool (*cpu_used)(u32)); +int envs_process_and_validate(const struct env_map_common *common, + const struct env_map_percpu *core, + bool (*cpu_used)(u32)); + +int args_envs_enumerate(const struct env_map_common *map, + int enum_by, int argc, char *const argv[]); + +#endif /* __BOARD_ENV_LIB_H */ diff --git a/roms/u-boot/board/synopsys/hsdk/headerize-hsdk.py b/roms/u-boot/board/synopsys/hsdk/headerize-hsdk.py new file mode 100644 index 000000000..7b047cf4a --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/headerize-hsdk.py @@ -0,0 +1,149 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. +# Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> + +import os, getopt, sys, zlib +from elftools.elf.elffile import ELFFile + + +def usage(exit_code): + print("usage:") + print(sys.argv[0] + " --arc-id 0x52 --image u-boot.bin --elf u-boot") + sys.exit(exit_code) + + +def elf_get_entry(filename): + with open(filename, 'rb') as f: + elffile = ELFFile(f) + return elffile.header['e_entry'] + + +def calc_check_sum(filename): + # u-boot.head check_sum for preloader - it is sum of all u-boot binary bytes + with open(filename, "rb") as file: + ba = bytearray(file.read()) + return sum(ba) & 0xFF + + +def arg_verify(uboot_bin_filename, uboot_elf_filename, arc_id): + if arc_id not in [0x52, 0x53, 0x54]: + print("unknown ARC ID: " + hex(arc_id)) + sys.exit(2) + + if not os.path.isfile(uboot_bin_filename): + print("uboot bin file not exists: " + uboot_bin_filename) + sys.exit(2) + + if not os.path.isfile(uboot_elf_filename): + print("uboot elf file not exists: " + uboot_elf_filename) + sys.exit(2) + + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], + "ha:i:l:e:", ["help", "arc-id=", "image=", "elf="]) + except getopt.GetoptError as err: + print(err) + usage(2) + + # default filenames + uboot_elf_filename = "u-boot" + uboot_bin_filename = "u-boot.bin" + headerised_filename = "u-boot.head" + uboot_scrypt_file = "u-boot-update.txt" + + # initial header values: place where preloader will store u-boot binary, + # should be equal to CONFIG_SYS_TEXT_BASE + image_copy_adr = 0x81000000 + + # initial constant header values, do not change these values + arc_id = 0x52 # 0x52 for 1st HSDK release (hardcoded in RTL) + magic1 = 0xdeadbeafaf # big endian byte order + flash_address = 0x0 + flash_type = 0x0 # 0 - SPI flash, 1 - NOR flash + magic2 = [ # big endian byte order + 0x20202a2020202020202020202a20202020207c5c2e20202020202e2f7c20202020207c2d, + 0x2e5c2020202f2e2d7c20202020205c2020602d2d2d6020202f20202020202f205f202020, + 0x205f20205c20202020207c205f60712070205f207c2020202020272e5f3d2f205c3d5f2e, + 0x272020202020202020605c202f60202020202020202020202020206f2020202020202020] + + for opt, arg in opts: + if opt in ('-h', "--help"): usage(0) + if opt in ('-a', "--arc-id"): arc_id = int(arg, 16) + if opt in ('-i', "--image"): uboot_bin_filename = arg + if opt in ('-e', "--elf"): uboot_elf_filename = arg + + arg_verify(uboot_bin_filename, uboot_elf_filename, arc_id) + + uboot_img_size = os.path.getsize(uboot_bin_filename) + jump_address = elf_get_entry(uboot_elf_filename) + check_sum = calc_check_sum(uboot_bin_filename) + + # write header to file + with open(headerised_filename, "wb") as file: + file.write(arc_id.to_bytes(2, byteorder='little')) + file.write(uboot_img_size.to_bytes(4, byteorder='little')) + file.write(check_sum.to_bytes(1, byteorder='little')) + file.write(image_copy_adr.to_bytes(4, byteorder='little')) + file.write(magic1.to_bytes(5, byteorder='big')) + file.write(jump_address.to_bytes(4, byteorder='little')) + for i in range(12): file.write(0xFF.to_bytes(1, byteorder='little')) + for byte in magic2: file.write(byte.to_bytes(36, byteorder='big')) + for i in range(208 - len(magic2) * 36): + file.write(0xFF.to_bytes(1, byteorder='little')) + file.write(flash_address.to_bytes(4, byteorder='little')) + for i in range(11): file.write(0xFF.to_bytes(1, byteorder='little')) + file.write(flash_type.to_bytes(1, byteorder='little')) + + # append u-boot image to header + with open(headerised_filename, "ab") as fo: + with open(uboot_bin_filename,'rb') as fi: + fo.write(fi.read()) + + # calc u-boot headerized image CRC32 (will be used by uboot update + # command for check) + headerised_image_crc = "" + with open(headerised_filename, "rb") as fi: + headerised_image_crc = hex(zlib.crc32(fi.read()) & 0xffffffff) + + load_addr = 0x81000000 + crc_store_adr = load_addr - 0x8 + crc_calc_adr = crc_store_adr - 0x4 + load_size = os.path.getsize(headerised_filename) + crc_calc_cmd = \ + "crc32 " + hex(load_addr) + " " + hex(load_size) + " " + hex(crc_calc_adr) + crc_check_cmd = \ + "mw.l " + hex(crc_store_adr) + " " + headerised_image_crc + " && " + \ + crc_calc_cmd + " && " + \ + "cmp.l " + hex(crc_store_adr) + " " + hex(crc_calc_adr) + " 1" + + # make errase size to be allighned by 64K + if load_size & 0xFFFF == 0: + errase_size = load_size + else: + errase_size = load_size - (load_size & 0xFFFF) + 0x10000 + + # u-bood CMD to load u-bood with header to SPI flash + sf_load_image_cmd = \ + "fatload mmc 0:1 " + hex(load_addr) + " " + headerised_filename + " && " + \ + "sf probe 0:0 && " + \ + crc_check_cmd + " && " + \ + "sf protect unlock 0x0 " + hex(errase_size) + " && " + \ + "sf erase 0x0 " + hex(errase_size) + " && " + \ + "sf write " + hex(load_addr) + " 0x0 " + hex(load_size) + " && " + \ + "sf protect lock 0x0 " + hex(errase_size) + + update_uboot_cmd = sf_load_image_cmd + " && echo \"u-boot update: OK\"" + + with open(uboot_scrypt_file, "wb") as fo: + fo.write(update_uboot_cmd.encode('ascii')) + + +if __name__ == "__main__": + try: + main() + except Exception as err: + print(err) + sys.exit(2) diff --git a/roms/u-boot/board/synopsys/hsdk/hsdk.c b/roms/u-boot/board/synopsys/hsdk/hsdk.c new file mode 100644 index 000000000..892b94bb0 --- /dev/null +++ b/roms/u-boot/board/synopsys/hsdk/hsdk.c @@ -0,0 +1,1268 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> + */ + +#include <common.h> +#include <command.h> +#include <config.h> +#include <cpu_func.h> +#include <env.h> +#include <image.h> +#include <init.h> +#include <irq_func.h> +#include <log.h> +#include <asm/cache.h> +#include <asm/global_data.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/printk.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <asm/arcregs.h> +#include <fdt_support.h> +#include <dwmmc.h> +#include <malloc.h> +#include <usb.h> + +#include "clk-lib.h" +#include "env-lib.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define ALL_CPU_MASK GENMASK(NR_CPUS - 1, 0) +#define MASTER_CPU_ID 0 +#define APERTURE_SHIFT 28 +#define NO_CCM 0x10 +#define SLAVE_CPU_READY 0x12345678 +#define BOOTSTAGE_1 1 /* after SP, FP setup, before HW init */ +#define BOOTSTAGE_2 2 /* after HW init, before self halt */ +#define BOOTSTAGE_3 3 /* after self halt */ +#define BOOTSTAGE_4 4 /* before app launch */ +#define BOOTSTAGE_5 5 /* after app launch, unreachable */ + +#define RESET_VECTOR_ADDR 0x0 + +#define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000) +#define CREG_CPU_START (CREG_BASE + 0x400) +#define CREG_CPU_START_MASK 0xF +#define CREG_CPU_START_POL BIT(4) + +#define CREG_CORE_BOOT_IMAGE GENMASK(5, 4) + +#define CREG_CPU_0_ENTRY (CREG_BASE + 0x404) + +#define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000) +#define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108) +#define SDIO_UHS_REG_EXT_DIV_2 (2 << 30) + +/* Uncached access macros */ +#define arc_read_uncached_32(ptr) \ +({ \ + unsigned int __ret; \ + __asm__ __volatile__( \ + " ld.di %0, [%1] \n" \ + : "=r"(__ret) \ + : "r"(ptr)); \ + __ret; \ +}) + +#define arc_write_uncached_32(ptr, data)\ +({ \ + __asm__ __volatile__( \ + " st.di %0, [%1] \n" \ + : \ + : "r"(data), "r"(ptr)); \ +}) + +struct hsdk_env_core_ctl { + u32_env entry[NR_CPUS]; + u32_env iccm[NR_CPUS]; + u32_env dccm[NR_CPUS]; +}; + +struct hsdk_env_common_ctl { + bool halt_on_boot; + u32_env core_mask; + u32_env cpu_freq; + u32_env axi_freq; + u32_env tun_freq; + u32_env nvlim; + u32_env icache; + u32_env dcache; + u32_env csm_location; + u32_env l2_cache; + u32_env haps_apb; +}; + +/* + * Uncached cross-cpu structure. All CPUs must access to this structure fields + * only with arc_read_uncached_32() / arc_write_uncached_32() accessors (which + * implement ld.di / st.di instructions). Simultaneous cached and uncached + * access to this area will lead to data loss. + * We flush all data caches in board_early_init_r() as we don't want to have + * any dirty line in L1d$ or SL$ in this area. + */ +struct hsdk_cross_cpu { + /* slave CPU ready flag */ + u32 ready_flag; + /* address of the area, which can be used for stack by slave CPU */ + u32 stack_ptr; + /* slave CPU status - bootstage number */ + s32 status[NR_CPUS]; + + /* + * Slave CPU data - it is copy of corresponding fields in + * hsdk_env_core_ctl and hsdk_env_common_ctl structures which are + * required for slave CPUs initialization. + * This fields can be populated by copying from hsdk_env_core_ctl + * and hsdk_env_common_ctl structures with sync_cross_cpu_data() + * function. + */ + u32 entry[NR_CPUS]; + u32 iccm[NR_CPUS]; + u32 dccm[NR_CPUS]; + + u32 core_mask; + u32 icache; + u32 dcache; + + u8 cache_padding[ARCH_DMA_MINALIGN]; +} __aligned(ARCH_DMA_MINALIGN); + +/* Place for slave CPUs temporary stack */ +static u32 slave_stack[256 * NR_CPUS] __aligned(ARCH_DMA_MINALIGN); + +static struct hsdk_env_common_ctl env_common = {}; +static struct hsdk_env_core_ctl env_core = {}; +static struct hsdk_cross_cpu cross_cpu_data; + +static const struct env_map_common env_map_common[] = { + { "core_mask", ENV_HEX, true, 0x1, 0xF, &env_common.core_mask }, + { "non_volatile_limit", ENV_HEX, true, 0, 0xF, &env_common.nvlim }, + { "icache_ena", ENV_HEX, true, 0, 1, &env_common.icache }, + { "dcache_ena", ENV_HEX, true, 0, 1, &env_common.dcache }, +#if defined(CONFIG_BOARD_HSDK_4XD) + { "l2_cache_ena", ENV_HEX, true, 0, 1, &env_common.l2_cache }, + { "csm_location", ENV_HEX, true, 0, NO_CCM, &env_common.csm_location }, + { "haps_apb_location", ENV_HEX, true, 0, 1, &env_common.haps_apb }, +#endif /* CONFIG_BOARD_HSDK_4XD */ + {} +}; + +static const struct env_map_common env_map_clock[] = { + { "cpu_freq", ENV_DEC, false, 100, 1000, &env_common.cpu_freq }, + { "axi_freq", ENV_DEC, false, 200, 800, &env_common.axi_freq }, + { "tun_freq", ENV_DEC, false, 0, 150, &env_common.tun_freq }, + {} +}; + +static const struct env_map_percpu env_map_core[] = { + { "core_iccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.iccm }, + { "core_dccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.dccm }, + {} +}; + +static const struct env_map_common env_map_mask[] = { + { "core_mask", ENV_HEX, false, 0x1, 0xF, &env_common.core_mask }, + {} +}; + +static const struct env_map_percpu env_map_go[] = { + { "core_entry", ENV_HEX, true, {0, 0, 0, 0}, {U32_MAX, U32_MAX, U32_MAX, U32_MAX}, &env_core.entry }, + {} +}; + +enum board_type { + T_BOARD_NONE, + T_BOARD_HSDK, + T_BOARD_HSDK_4XD +}; + +static inline enum board_type get_board_type_runtime(void) +{ + u32 arc_id = read_aux_reg(ARC_AUX_IDENTITY) & 0xFF; + + if (arc_id == 0x52) + return T_BOARD_HSDK; + else if (arc_id == 0x54) + return T_BOARD_HSDK_4XD; + else + return T_BOARD_NONE; +} + +static inline enum board_type get_board_type_config(void) +{ + if (IS_ENABLED(CONFIG_BOARD_HSDK)) + return T_BOARD_HSDK; + else if (IS_ENABLED(CONFIG_BOARD_HSDK_4XD)) + return T_BOARD_HSDK_4XD; + else + return T_BOARD_NONE; +} + +static bool is_board_match_runtime(enum board_type type_req) +{ + return get_board_type_runtime() == type_req; +} + +static bool is_board_match_config(enum board_type type_req) +{ + return get_board_type_config() == type_req; +} + +static const char * board_name(enum board_type type) +{ + switch (type) { + case T_BOARD_HSDK: + return "ARC HS Development Kit"; + case T_BOARD_HSDK_4XD: + return "ARC HS4x/HS4xD Development Kit"; + default: + return "?"; + } +} + +static bool board_mismatch(void) +{ + return get_board_type_config() != get_board_type_runtime(); +} + +static void sync_cross_cpu_data(void) +{ + u32 value; + + for (u32 i = 0; i < NR_CPUS; i++) { + value = env_core.entry[i].val; + arc_write_uncached_32(&cross_cpu_data.entry[i], value); + } + + for (u32 i = 0; i < NR_CPUS; i++) { + value = env_core.iccm[i].val; + arc_write_uncached_32(&cross_cpu_data.iccm[i], value); + } + + for (u32 i = 0; i < NR_CPUS; i++) { + value = env_core.dccm[i].val; + arc_write_uncached_32(&cross_cpu_data.dccm[i], value); + } + + value = env_common.core_mask.val; + arc_write_uncached_32(&cross_cpu_data.core_mask, value); + + value = env_common.icache.val; + arc_write_uncached_32(&cross_cpu_data.icache, value); + + value = env_common.dcache.val; + arc_write_uncached_32(&cross_cpu_data.dcache, value); +} + +/* Can be used only on master CPU */ +static bool is_cpu_used(u32 cpu_id) +{ + return !!(env_common.core_mask.val & BIT(cpu_id)); +} + +/* TODO: add ICCM BCR and DCCM BCR runtime check */ +static void init_slave_cpu_func(u32 core) +{ + u32 val; + + /* Remap ICCM to another memory region if it exists */ + val = arc_read_uncached_32(&cross_cpu_data.iccm[core]); + if (val != NO_CCM) + write_aux_reg(ARC_AUX_ICCM_BASE, val << APERTURE_SHIFT); + + /* Remap DCCM to another memory region if it exists */ + val = arc_read_uncached_32(&cross_cpu_data.dccm[core]); + if (val != NO_CCM) + write_aux_reg(ARC_AUX_DCCM_BASE, val << APERTURE_SHIFT); + + if (arc_read_uncached_32(&cross_cpu_data.icache)) + icache_enable(); + else + icache_disable(); + + if (arc_read_uncached_32(&cross_cpu_data.dcache)) + dcache_enable(); + else + dcache_disable(); +} + +static void init_cluster_nvlim(void) +{ + u32 val = env_common.nvlim.val << APERTURE_SHIFT; + + flush_dcache_all(); + write_aux_reg(ARC_AUX_NON_VOLATILE_LIMIT, val); + /* AUX_AUX_CACHE_LIMIT reg is missing starting from HS48 */ + if (is_board_match_runtime(T_BOARD_HSDK)) + write_aux_reg(AUX_AUX_CACHE_LIMIT, val); + flush_n_invalidate_dcache_all(); +} + +static void init_cluster_slc(void) +{ + /* ARC HS38 doesn't support SLC disabling */ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.l2_cache.val) + slc_enable(); + else + slc_disable(); +} + +#define CREG_CSM_BASE (CREG_BASE + 0x210) + +static void init_cluster_csm(void) +{ + /* ARC HS38 in HSDK SoC doesn't include CSM */ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.csm_location.val == NO_CCM) { + write_aux_reg(ARC_AUX_CSM_ENABLE, 0); + } else { + /* + * CSM base address is 256kByte aligned but we allow to map + * CSM only to aperture start (256MByte aligned) + * The field in CREG_CSM_BASE is in 17:2 bits itself so we need + * to shift it. + */ + u32 csm_base = (env_common.csm_location.val * SZ_1K) << 2; + + write_aux_reg(ARC_AUX_CSM_ENABLE, 1); + writel(csm_base, (void __iomem *)CREG_CSM_BASE); + } +} + +static void init_master_icache(void) +{ + if (icache_status()) { + /* I$ is enabled - we need to disable it */ + if (!env_common.icache.val) + icache_disable(); + } else { + /* I$ is disabled - we need to enable it */ + if (env_common.icache.val) { + icache_enable(); + + /* invalidate I$ right after enable */ + invalidate_icache_all(); + } + } +} + +static void init_master_dcache(void) +{ + if (dcache_status()) { + /* D$ is enabled - we need to disable it */ + if (!env_common.dcache.val) + dcache_disable(); + } else { + /* D$ is disabled - we need to enable it */ + if (env_common.dcache.val) + dcache_enable(); + + /* TODO: probably we need ti invalidate D$ right after enable */ + } +} + +static int cleanup_before_go(void) +{ + disable_interrupts(); + sync_n_cleanup_cache_all(); + + return 0; +} + +void slave_cpu_set_boot_addr(u32 addr) +{ + /* All cores have reset vector pointing to 0 */ + writel(addr, (void __iomem *)RESET_VECTOR_ADDR); + + /* Make sure other cores see written value in memory */ + sync_n_cleanup_cache_all(); +} + +static inline void halt_this_cpu(void) +{ + __builtin_arc_flag(1); +} + +static u32 get_masked_cpu_ctart_reg(void) +{ + int cmd = readl((void __iomem *)CREG_CPU_START); + + /* + * Quirk for HSDK-4xD - due to HW issues HSDK can use any pulse polarity + * and HSDK-4xD require active low polarity of cpu_start pulse. + */ + cmd &= ~CREG_CPU_START_POL; + + cmd &= ~CREG_CPU_START_MASK; + + return cmd; +} + +static void smp_kick_cpu_x(u32 cpu_id) +{ + int cmd; + + if (cpu_id > NR_CPUS) + return; + + cmd = get_masked_cpu_ctart_reg(); + cmd |= (1 << cpu_id); + writel(cmd, (void __iomem *)CREG_CPU_START); +} + +static u32 prepare_cpu_ctart_reg(void) +{ + return get_masked_cpu_ctart_reg() | env_common.core_mask.val; +} + +/* slave CPU entry for configuration */ +__attribute__((naked, noreturn, flatten)) noinline void hsdk_core_init_f(void) +{ + __asm__ __volatile__( + "ld.di r8, [%0]\n" + "mov %%sp, r8\n" + "mov %%fp, %%sp\n" + : /* no output */ + : "r" (&cross_cpu_data.stack_ptr)); + + invalidate_icache_all(); + + arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_1); + init_slave_cpu_func(CPU_ID_GET()); + + arc_write_uncached_32(&cross_cpu_data.ready_flag, SLAVE_CPU_READY); + arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_2); + + /* Halt the processor until the master kick us again */ + halt_this_cpu(); + + /* + * 3 NOPs after FLAG 1 instruction are no longer required for ARCv2 + * cores but we leave them for gebug purposes. + */ + __builtin_arc_nop(); + __builtin_arc_nop(); + __builtin_arc_nop(); + + arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_3); + + /* get the updated entry - invalidate i$ */ + invalidate_icache_all(); + + arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_4); + + /* Run our program */ + ((void (*)(void))(arc_read_uncached_32(&cross_cpu_data.entry[CPU_ID_GET()])))(); + + /* This bootstage is unreachable as we don't return from app we launch */ + arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_5); + + /* Something went terribly wrong */ + while (true) + halt_this_cpu(); +} + +static void clear_cross_cpu_data(void) +{ + arc_write_uncached_32(&cross_cpu_data.ready_flag, 0); + arc_write_uncached_32(&cross_cpu_data.stack_ptr, 0); + + for (u32 i = 0; i < NR_CPUS; i++) + arc_write_uncached_32(&cross_cpu_data.status[i], 0); +} + +static noinline void do_init_slave_cpu(u32 cpu_id) +{ + /* attempts number for check clave CPU ready_flag */ + u32 attempts = 100; + u32 stack_ptr = (u32)(slave_stack + (64 * cpu_id)); + + if (cpu_id >= NR_CPUS) + return; + + arc_write_uncached_32(&cross_cpu_data.ready_flag, 0); + + /* Use global unique place for each slave cpu stack */ + arc_write_uncached_32(&cross_cpu_data.stack_ptr, stack_ptr); + + debug("CPU %u: stack pool base: %p\n", cpu_id, slave_stack); + debug("CPU %u: current slave stack base: %x\n", cpu_id, stack_ptr); + slave_cpu_set_boot_addr((u32)hsdk_core_init_f); + + smp_kick_cpu_x(cpu_id); + + debug("CPU %u: cross-cpu flag: %x [before timeout]\n", cpu_id, + arc_read_uncached_32(&cross_cpu_data.ready_flag)); + + while (!arc_read_uncached_32(&cross_cpu_data.ready_flag) && attempts--) + mdelay(10); + + /* Just to be sure that slave cpu is halted after it set ready_flag */ + mdelay(20); + + /* + * Only print error here if we reach timeout as there is no option to + * halt slave cpu (or check that slave cpu is halted) + */ + if (!attempts) + pr_err("CPU %u is not responding after init!\n", cpu_id); + + /* Check current stage of slave cpu */ + if (arc_read_uncached_32(&cross_cpu_data.status[cpu_id]) != BOOTSTAGE_2) + pr_err("CPU %u status is unexpected: %d\n", cpu_id, + arc_read_uncached_32(&cross_cpu_data.status[cpu_id])); + + debug("CPU %u: cross-cpu flag: %x [after timeout]\n", cpu_id, + arc_read_uncached_32(&cross_cpu_data.ready_flag)); + debug("CPU %u: status: %d [after timeout]\n", cpu_id, + arc_read_uncached_32(&cross_cpu_data.status[cpu_id])); +} + +static void do_init_slave_cpus(void) +{ + clear_cross_cpu_data(); + sync_cross_cpu_data(); + + debug("cross_cpu_data location: %#x\n", (u32)&cross_cpu_data); + + for (u32 i = MASTER_CPU_ID + 1; i < NR_CPUS; i++) + if (is_cpu_used(i)) + do_init_slave_cpu(i); +} + +static void do_init_master_cpu(void) +{ + /* + * Setup master caches even if master isn't used as we want to use + * same cache configuration on all running CPUs + */ + init_master_icache(); + init_master_dcache(); +} + +enum hsdk_axi_masters { + M_HS_CORE = 0, + M_HS_RTT, + M_AXI_TUN, + M_HDMI_VIDEO, + M_HDMI_AUDIO, + M_USB_HOST, + M_ETHERNET, + M_SDIO, + M_GPU, + M_DMAC_0, + M_DMAC_1, + M_DVFS +}; + +#define UPDATE_VAL 1 + +/* + * m master AXI_M_m_SLV0 AXI_M_m_SLV1 AXI_M_m_OFFSET0 AXI_M_m_OFFSET1 + * 0 HS (CBU) 0x11111111 0x63111111 0xFEDCBA98 0x0E543210 + * 1 HS (RTT) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 2 AXI Tunnel 0x88888888 0x88888888 0xFEDCBA98 0x76543210 + * 3 HDMI-VIDEO 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 4 HDMI-ADUIO 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 5 USB-HOST 0x77777777 0x77999999 0xFEDCBA98 0x76DCBA98 + * 6 ETHERNET 0x77777777 0x77999999 0xFEDCBA98 0x76DCBA98 + * 7 SDIO 0x77777777 0x77999999 0xFEDCBA98 0x76DCBA98 + * 8 GPU 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 9 DMAC (port #1) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 10 DMAC (port #2) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 11 DVFS 0x00000000 0x60000000 0x00000000 0x00000000 + * + * Please read ARC HS Development IC Specification, section 17.2 for more + * information about apertures configuration. + * NOTE: we intentionally modify default settings in U-boot. Default settings + * are specified in "Table 111 CREG Address Decoder register reset values". + */ + +#define CREG_AXI_M_SLV0(m) ((void __iomem *)(CREG_BASE + 0x020 * (m))) +#define CREG_AXI_M_SLV1(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x004)) +#define CREG_AXI_M_OFT0(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x008)) +#define CREG_AXI_M_OFT1(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x00C)) +#define CREG_AXI_M_UPDT(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x014)) + +#define CREG_AXI_M_HS_CORE_BOOT ((void __iomem *)(CREG_BASE + 0x010)) + +#define CREG_PAE ((void __iomem *)(CREG_BASE + 0x180)) +#define CREG_PAE_UPDT ((void __iomem *)(CREG_BASE + 0x194)) + +void init_memory_bridge(void) +{ + u32 reg; + + /* + * M_HS_CORE has one unic register - BOOT. + * We need to clean boot mirror (BOOT[1:0]) bits in them. + */ + reg = readl(CREG_AXI_M_HS_CORE_BOOT) & (~0x3); + writel(reg, CREG_AXI_M_HS_CORE_BOOT); + writel(0x11111111, CREG_AXI_M_SLV0(M_HS_CORE)); + writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_CORE)); + writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_HS_RTT)); + writel(0x77777777, CREG_AXI_M_SLV1(M_HS_RTT)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_RTT)); + writel(0x76543210, CREG_AXI_M_OFT1(M_HS_RTT)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_RTT)); + + writel(0x88888888, CREG_AXI_M_SLV0(M_AXI_TUN)); + writel(0x88888888, CREG_AXI_M_SLV1(M_AXI_TUN)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_AXI_TUN)); + writel(0x76543210, CREG_AXI_M_OFT1(M_AXI_TUN)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_AXI_TUN)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_VIDEO)); + writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_VIDEO)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_VIDEO)); + writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_VIDEO)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_VIDEO)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_AUDIO)); + writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_AUDIO)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_AUDIO)); + writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_AUDIO)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_AUDIO)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_USB_HOST)); + writel(0x77999999, CREG_AXI_M_SLV1(M_USB_HOST)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_USB_HOST)); + writel(0x76DCBA98, CREG_AXI_M_OFT1(M_USB_HOST)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_ETHERNET)); + writel(0x77999999, CREG_AXI_M_SLV1(M_ETHERNET)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_ETHERNET)); + writel(0x76DCBA98, CREG_AXI_M_OFT1(M_ETHERNET)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_SDIO)); + writel(0x77999999, CREG_AXI_M_SLV1(M_SDIO)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_SDIO)); + writel(0x76DCBA98, CREG_AXI_M_OFT1(M_SDIO)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_GPU)); + writel(0x77777777, CREG_AXI_M_SLV1(M_GPU)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_GPU)); + writel(0x76543210, CREG_AXI_M_OFT1(M_GPU)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0)); + writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0)); + writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0)); + + writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1)); + writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1)); + writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1)); + writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1)); + + writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS)); + writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS)); + writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS)); + writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS)); + + writel(0x00000000, CREG_PAE); + writel(UPDATE_VAL, CREG_PAE_UPDT); +} + +/* + * For HSDK-4xD we do additional AXI bridge tweaking in hsdk_init command: + * - we shrink IOC region. + * - we configure HS CORE SLV1 aperture depending on haps_apb_location + * environment variable. + * + * As we've already configured AXI bridge in init_memory_bridge we don't + * do full configuration here but reconfigure changed part. + * + * m master AXI_M_m_SLV0 AXI_M_m_SLV1 AXI_M_m_OFFSET0 AXI_M_m_OFFSET1 + * 0 HS (CBU) 0x11111111 0x63111111 0xFEDCBA98 0x0E543210 [haps_apb_location = 0] + * 0 HS (CBU) 0x11111111 0x61111111 0xFEDCBA98 0x06543210 [haps_apb_location = 1] + * 1 HS (RTT) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 2 AXI Tunnel 0x88888888 0x88888888 0xFEDCBA98 0x76543210 + * 3 HDMI-VIDEO 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 4 HDMI-ADUIO 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 5 USB-HOST 0x77777777 0x77779999 0xFEDCBA98 0x7654BA98 + * 6 ETHERNET 0x77777777 0x77779999 0xFEDCBA98 0x7654BA98 + * 7 SDIO 0x77777777 0x77779999 0xFEDCBA98 0x7654BA98 + * 8 GPU 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 9 DMAC (port #1) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 10 DMAC (port #2) 0x77777777 0x77777777 0xFEDCBA98 0x76543210 + * 11 DVFS 0x00000000 0x60000000 0x00000000 0x00000000 + */ +void tweak_memory_bridge_cfg(void) +{ + /* + * Only HSDK-4xD requre additional AXI bridge tweaking depending on + * haps_apb_location environment variable + */ + if (!is_board_match_config(T_BOARD_HSDK_4XD)) + return; + + if (env_common.haps_apb.val) { + writel(0x61111111, CREG_AXI_M_SLV1(M_HS_CORE)); + writel(0x06543210, CREG_AXI_M_OFT1(M_HS_CORE)); + } else { + writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE)); + writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE)); + } + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE)); + + writel(0x77779999, CREG_AXI_M_SLV1(M_USB_HOST)); + writel(0x7654BA98, CREG_AXI_M_OFT1(M_USB_HOST)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST)); + + writel(0x77779999, CREG_AXI_M_SLV1(M_ETHERNET));; + writel(0x7654BA98, CREG_AXI_M_OFT1(M_ETHERNET)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET)); + + writel(0x77779999, CREG_AXI_M_SLV1(M_SDIO)); + writel(0x7654BA98, CREG_AXI_M_OFT1(M_SDIO)); + writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO)); +} + +static void setup_clocks(void) +{ + ulong rate; + + /* Setup CPU clock */ + if (env_common.cpu_freq.set) { + rate = env_common.cpu_freq.val; + soc_clk_ctl("cpu-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ); + } + + /* Setup TUN clock */ + if (env_common.tun_freq.set) { + rate = env_common.tun_freq.val; + if (rate) + soc_clk_ctl("tun-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ); + else + soc_clk_ctl("tun-clk", NULL, CLK_OFF); + } + + if (env_common.axi_freq.set) { + rate = env_common.axi_freq.val; + soc_clk_ctl("axi-clk", &rate, CLK_SET | CLK_ON | CLK_MHZ); + } +} + +static void do_init_cluster(void) +{ + /* + * A multi-core ARC HS configuration always includes only one + * ARC_AUX_NON_VOLATILE_LIMIT register, which is shared by all the + * cores. + */ + init_cluster_nvlim(); + init_cluster_csm(); + init_cluster_slc(); + tweak_memory_bridge_cfg(); +} + +static int check_master_cpu_id(void) +{ + if (CPU_ID_GET() == MASTER_CPU_ID) + return 0; + + pr_err("u-boot runs on non-master cpu with id: %lu\n", CPU_ID_GET()); + + return -ENOENT; +} + +static noinline int prepare_cpus(void) +{ + int ret; + + ret = check_master_cpu_id(); + if (ret) + return ret; + + ret = envs_process_and_validate(env_map_common, env_map_core, is_cpu_used); + if (ret) + return ret; + + printf("CPU start mask is %#x\n", env_common.core_mask.val); + + do_init_slave_cpus(); + do_init_master_cpu(); + do_init_cluster(); + + return 0; +} + +static int hsdk_go_run(u32 cpu_start_reg) +{ + /* Cleanup caches, disable interrupts */ + cleanup_before_go(); + + if (env_common.halt_on_boot) + halt_this_cpu(); + + /* + * 3 NOPs after FLAG 1 instruction are no longer required for ARCv2 + * cores but we leave them for gebug purposes. + */ + __builtin_arc_nop(); + __builtin_arc_nop(); + __builtin_arc_nop(); + + /* Kick chosen slave CPUs */ + writel(cpu_start_reg, (void __iomem *)CREG_CPU_START); + + if (is_cpu_used(MASTER_CPU_ID)) + ((void (*)(void))(env_core.entry[MASTER_CPU_ID].val))(); + else + halt_this_cpu(); + + pr_err("u-boot still runs on cpu [%ld]\n", CPU_ID_GET()); + + /* + * We will never return after executing our program if master cpu used + * otherwise halt master cpu manually. + */ + while (true) + halt_this_cpu(); + + return 0; +} + +int board_prep_linux(bootm_headers_t *images) +{ + int ret, ofst; + char mask[15]; + + ret = envs_read_validate_common(env_map_mask); + if (ret) + return ret; + + /* Rollback to default values */ + if (!env_common.core_mask.set) { + env_common.core_mask.val = ALL_CPU_MASK; + env_common.core_mask.set = true; + } + + printf("CPU start mask is %#x\n", env_common.core_mask.val); + + if (!is_cpu_used(MASTER_CPU_ID)) + pr_err("ERR: try to launch linux with CPU[0] disabled! It doesn't work for ARC.\n"); + + /* + * If we want to launch linux on all CPUs we don't need to patch + * linux DTB as it is default configuration + */ + if (env_common.core_mask.val == ALL_CPU_MASK) + return 0; + + if (!IMAGE_ENABLE_OF_LIBFDT || !images->ft_len) { + pr_err("WARN: core_mask setup will work properly only with external DTB!\n"); + return 0; + } + + /* patch '/possible-cpus' property according to cpu mask */ + ofst = fdt_path_offset(images->ft_addr, "/"); + sprintf(mask, "%s%s%s%s", + is_cpu_used(0) ? "0," : "", + is_cpu_used(1) ? "1," : "", + is_cpu_used(2) ? "2," : "", + is_cpu_used(3) ? "3," : ""); + ret = fdt_setprop_string(images->ft_addr, ofst, "possible-cpus", mask); + /* + * If we failed to patch '/possible-cpus' property we don't need break + * linux loading process: kernel will handle it but linux will print + * warning like "Timeout: CPU1 FAILED to comeup !!!". + * So warn here about error, but return 0 like no error had occurred. + */ + if (ret) + pr_err("WARN: failed to patch '/possible-cpus' property, ret=%d\n", + ret); + + return 0; +} + +void board_jump_and_run(ulong entry, int zero, int arch, uint params) +{ + void (*kernel_entry)(int zero, int arch, uint params); + u32 cpu_start_reg; + + kernel_entry = (void (*)(int, int, uint))entry; + + /* Prepare CREG_CPU_START for kicking chosen CPUs */ + cpu_start_reg = prepare_cpu_ctart_reg(); + + /* In case of run without hsdk_init */ + slave_cpu_set_boot_addr(entry); + + /* In case of run with hsdk_init */ + for (u32 i = 0; i < NR_CPUS; i++) { + env_core.entry[i].val = entry; + env_core.entry[i].set = true; + } + /* sync cross_cpu struct as we updated core-entry variables */ + sync_cross_cpu_data(); + + /* Kick chosen slave CPUs */ + writel(cpu_start_reg, (void __iomem *)CREG_CPU_START); + + if (is_cpu_used(0)) + kernel_entry(zero, arch, params); +} + +static int hsdk_go_prepare_and_run(void) +{ + /* Prepare CREG_CPU_START for kicking chosen CPUs */ + u32 reg = prepare_cpu_ctart_reg(); + + if (env_common.halt_on_boot) + printf("CPU will halt before application start, start application with debugger.\n"); + + return hsdk_go_run(reg); +} + +static int do_hsdk_go(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + if (board_mismatch()) { + printf("ERR: U-boot is not configured for this board!\n"); + return CMD_RET_FAILURE; + } + + /* + * Check for 'halt' parameter. 'halt' = enter halt-mode just before + * starting the application; can be used for debug. + */ + if (argc > 1) { + env_common.halt_on_boot = !strcmp(argv[1], "halt"); + if (!env_common.halt_on_boot) { + pr_err("Unrecognised parameter: \'%s\'\n", argv[1]); + return CMD_RET_FAILURE; + } + } + + ret = check_master_cpu_id(); + if (ret) + return ret; + + ret = envs_process_and_validate(env_map_mask, env_map_go, is_cpu_used); + if (ret) + return ret; + + /* sync cross_cpu struct as we updated core-entry variables */ + sync_cross_cpu_data(); + + ret = hsdk_go_prepare_and_run(); + + return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + hsdk_go, 3, 0, do_hsdk_go, + "Synopsys HSDK specific command", + " - Boot stand-alone application on HSDK\n" + "hsdk_go halt - Boot stand-alone application on HSDK, halt CPU just before application run\n" +); + +/* + * We may simply use static variable here to store init status, but we also want + * to avoid the situation when we reload U-boot via MDB after previous + * init is done but HW reset (board reset) isn't done. So let's store the + * init status in any unused register (i.e CREG_CPU_0_ENTRY) so status will + * survive after U-boot is reloaded via MDB. + */ +#define INIT_MARKER_REGISTER ((void __iomem *)CREG_CPU_0_ENTRY) +/* must be equal to INIT_MARKER_REGISTER reset value */ +#define INIT_MARKER_PENDING 0 + +static bool init_marker_get(void) +{ + return readl(INIT_MARKER_REGISTER) != INIT_MARKER_PENDING; +} + +static void init_mark_done(void) +{ + writel(~INIT_MARKER_PENDING, INIT_MARKER_REGISTER); +} + +static int do_hsdk_init(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + if (board_mismatch()) { + printf("ERR: U-boot is not configured for this board!\n"); + return CMD_RET_FAILURE; + } + + /* hsdk_init can be run only once */ + if (init_marker_get()) { + printf("HSDK HW is already initialized! Please reset the board if you want to change the configuration.\n"); + return CMD_RET_FAILURE; + } + + ret = prepare_cpus(); + if (!ret) + init_mark_done(); + + return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + hsdk_init, 1, 0, do_hsdk_init, + "Synopsys HSDK specific command", + "- Init HSDK HW\n" +); + +static int do_hsdk_clock_set(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret = 0; + + /* Strip off leading subcommand argument */ + argc--; + argv++; + + envs_cleanup_common(env_map_clock); + + if (!argc) { + printf("Set clocks to values specified in environment\n"); + ret = envs_read_common(env_map_clock); + } else { + printf("Set clocks to values specified in args\n"); + ret = args_envs_enumerate(env_map_clock, 2, argc, argv); + } + + if (ret) + return CMD_RET_FAILURE; + + ret = envs_validate_common(env_map_clock); + if (ret) + return CMD_RET_FAILURE; + + /* Setup clock tree HW */ + setup_clocks(); + + return CMD_RET_SUCCESS; +} + +static int do_hsdk_clock_get(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + ulong rate; + + if (soc_clk_ctl("cpu-clk", &rate, CLK_GET | CLK_MHZ)) + return CMD_RET_FAILURE; + + if (env_set_ulong("cpu_freq", rate)) + return CMD_RET_FAILURE; + + if (soc_clk_ctl("tun-clk", &rate, CLK_GET | CLK_MHZ)) + return CMD_RET_FAILURE; + + if (env_set_ulong("tun_freq", rate)) + return CMD_RET_FAILURE; + + if (soc_clk_ctl("axi-clk", &rate, CLK_GET | CLK_MHZ)) + return CMD_RET_FAILURE; + + if (env_set_ulong("axi_freq", rate)) + return CMD_RET_FAILURE; + + printf("Clock values are saved to environment\n"); + + return CMD_RET_SUCCESS; +} + +static int do_hsdk_clock_print(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + /* Main clocks */ + soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ); + + return CMD_RET_SUCCESS; +} + +static int do_hsdk_clock_print_all(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + /* + * NOTE: as of today we don't use some peripherals like HDMI / EBI + * so we don't want to print their clocks ("hdmi-sys-clk", "hdmi-pll", + * "hdmi-clk", "ebi-clk"). Nevertheless their clock subsystems is fully + * functional and we can print their clocks if it is required + */ + + /* CPU clock domain */ + soc_clk_ctl("cpu-pll", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ); + printf("\n"); + + /* SYS clock domain */ + soc_clk_ctl("sys-pll", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("apb-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("eth-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("usb-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("sdio-clk", NULL, CLK_PRINT | CLK_MHZ); + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) + soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ); + if (is_board_match_runtime(T_BOARD_HSDK)) { + soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); + } + soc_clk_ctl("dmac-core-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("dmac-cfg-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("sdio-ref-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("spi-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("i2c-clk", NULL, CLK_PRINT | CLK_MHZ); +/* soc_clk_ctl("ebi-clk", NULL, CLK_PRINT | CLK_MHZ); */ + soc_clk_ctl("uart-clk", NULL, CLK_PRINT | CLK_MHZ); + printf("\n"); + + /* DDR clock domain */ + soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ); + printf("\n"); + + /* HDMI clock domain */ + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) { + soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ); + printf("\n"); + } + + /* TUN clock domain */ + soc_clk_ctl("tun-pll", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("rom-clk", NULL, CLK_PRINT | CLK_MHZ); + soc_clk_ctl("pwm-clk", NULL, CLK_PRINT | CLK_MHZ); + if (is_board_match_runtime(T_BOARD_HSDK_4XD)) + soc_clk_ctl("timer-clk", NULL, CLK_PRINT | CLK_MHZ); + printf("\n"); + + return CMD_RET_SUCCESS; +} + +struct cmd_tbl cmd_hsdk_clock[] = { + U_BOOT_CMD_MKENT(set, 3, 0, do_hsdk_clock_set, "", ""), + U_BOOT_CMD_MKENT(get, 3, 0, do_hsdk_clock_get, "", ""), + U_BOOT_CMD_MKENT(print, 4, 0, do_hsdk_clock_print, "", ""), + U_BOOT_CMD_MKENT(print_all, 4, 0, do_hsdk_clock_print_all, "", ""), +}; + +static int do_hsdk_clock(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct cmd_tbl *c; + + if (argc < 2) + return CMD_RET_USAGE; + + /* Strip off leading 'hsdk_clock' command argument */ + argc--; + argv++; + + c = find_cmd_tbl(argv[0], cmd_hsdk_clock, ARRAY_SIZE(cmd_hsdk_clock)); + if (!c) + return CMD_RET_USAGE; + + return c->cmd(cmdtp, flag, argc, argv); +} + +U_BOOT_CMD( + hsdk_clock, CONFIG_SYS_MAXARGS, 0, do_hsdk_clock, + "Synopsys HSDK specific clock command", + "set - Set clock to values specified in environment / command line arguments\n" + "hsdk_clock get - Save clock values to environment\n" + "hsdk_clock print - Print main clock values to console\n" + "hsdk_clock print_all - Print all clock values to console\n" +); + +/* init calls */ +int board_early_init_f(void) +{ + /* + * Setup AXI apertures unconditionally as we want to have DDR + * in 0x00000000 region when we are kicking slave cpus. + */ + init_memory_bridge(); + + /* + * Switch SDIO external ciu clock divider from default div-by-8 to + * minimum possible div-by-2. + */ + writel(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *)SDIO_UHS_REG_EXT); + + return 0; +} + +int board_early_init_r(void) +{ + /* + * TODO: Init USB here to be able read environment from USB MSD. + * It can be done with usb_init() call. We can't do it right now + * due to brocken USB IP SW reset and lack of USB IP HW reset in + * linux kernel (if we init USB here we will break USB in linux) + */ + + /* + * Flush all d$ as we want to use uncached area with st.di / ld.di + * instructions and we don't want to have any dirty line in L1d$ or SL$ + * in this area. It is enough to flush all d$ once here as we access to + * uncached area with regular st (non .di) instruction only when we copy + * data during u-boot relocation. + */ + flush_dcache_all(); + + printf("Relocation Offset is: %08lx\n", gd->reloc_off); + + return 0; +} + +int board_late_init(void) +{ + /* + * Populate environment with clock frequency values - + * run hsdk_clock get callback without uboot command run. + */ + do_hsdk_clock_get(NULL, 0, 0, NULL); + + return 0; +} + +int checkboard(void) +{ + u32 reg; + + printf("Board: Synopsys %s\n", board_name(get_board_type_runtime())); + + if (board_mismatch()) + printf("WARN: U-boot is configured NOT for this board but for %s!\n", + board_name(get_board_type_config())); + + reg = readl(CREG_AXI_M_HS_CORE_BOOT) & CREG_CORE_BOOT_IMAGE; + printf("U-boot autostart: %s\n", reg ? "enabled" : "disabled"); + + return 0; +}; diff --git a/roms/u-boot/board/synopsys/iot_devkit/Kconfig b/roms/u-boot/board/synopsys/iot_devkit/Kconfig new file mode 100644 index 000000000..ad956b20f --- /dev/null +++ b/roms/u-boot/board/synopsys/iot_devkit/Kconfig @@ -0,0 +1,12 @@ +if TARGET_IOT_DEVKIT + +config SYS_BOARD + default "iot_devkit" + +config SYS_VENDOR + default "synopsys" + +config SYS_CONFIG_NAME + default "iot_devkit" + +endif diff --git a/roms/u-boot/board/synopsys/iot_devkit/MAINTAINERS b/roms/u-boot/board/synopsys/iot_devkit/MAINTAINERS new file mode 100644 index 000000000..06457cfa6 --- /dev/null +++ b/roms/u-boot/board/synopsys/iot_devkit/MAINTAINERS @@ -0,0 +1,5 @@ +IOT DEVKIT BOARD +M: Alexey Brodkin <abrodkin@synopsys.com> +S: Maintained +F: board/synopsys/iot_devkit/ +F: configs/iot_devkit_defconfig diff --git a/roms/u-boot/board/synopsys/iot_devkit/Makefile b/roms/u-boot/board/synopsys/iot_devkit/Makefile new file mode 100644 index 000000000..161602464 --- /dev/null +++ b/roms/u-boot/board/synopsys/iot_devkit/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2018 Synopsys, Inc. All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += iot_devkit.o diff --git a/roms/u-boot/board/synopsys/iot_devkit/README b/roms/u-boot/board/synopsys/iot_devkit/README new file mode 100644 index 000000000..20c140d93 --- /dev/null +++ b/roms/u-boot/board/synopsys/iot_devkit/README @@ -0,0 +1,145 @@ +================================================================================ +Useful notes on bulding and using of U-Boot on +ARC IoT Development Kit (AKA IoTDK) +================================================================================ + + BOARD OVERVIEW + + The DesignWare ARC IoT Development Kit is a versatile platform that includes + the necessary hardware and software to accelerate software development and + debugging of sensor fusion, voice recognition and face detection designs. + + The ARC IoT Development Kit includes a silicon implementation of the + ARC Data Fusion IP Subsystem running at 144 MHz on SMIC's + 55-nm ultra-low power process, and a rich set of peripherals commonly used + in IoT designs such as USB, UART, SPI, I2C, PWM, SDIO and ADCs. + + The board is shipped with pre-installed U-Boot in non-volatile memory + (eFlash) so on power-on user sees U-Boot start header and command line + prompt which might be used for U-Boot environment fine-tuning, manual + loading and execution of user application binaries etc. + + The board has the following features useful for U-Boot: + * On-board 2-channel FTDI TTL-to-USB converter + - The first channel is used for serial debug port (which makes it possible + to use a serial connection on pretty much any host machine be it + Windows, Linux or Mac). + On Linux machine typucally FTDI serial port would be /dev/ttyUSB0. + There's no HW flow-control and baud-rate is 115200. + + - The second channel is used for built-in Digilent USB JTAG probe. + That means no extra hardware is required to access ARC core from a + debugger on development host. Both proprietary MetaWare debugger and + open source OpenOCD + GDB client are supported. + + - Also with help of this FTDI chip it is possible to reset entire + board with help of a special `rff-ftdi-reset` utility, see: + https://github.com/foss-for-synopsys-dwc-arc-processors/rff-ftdi-reset + + * Micro SD-card slot + - U-Boot expects to see the very first partition on the card formatted as + FAT file-system and uses it for keeping its environment in `uboot.env` + file. Note uboot.env is not just a text file but it is auto-generated + file created by U-Boot on invocation of `saveenv` command. + It contains a checksum which makes this saved environment invalid in + case of maual modification. + + - There might be more useful files on that first FAT partition like + user applications, data files etc. + + * USB OTG connector + - U-Boot may access USB mass-storage devices attached to this connector. + Note only FAT file-system is supported. It might be used for storing + user application binaries as well as micro SD-card mentioned above. + + * The following memories are avaialble on the board: + - eFlash: 256 KiB @ 0x0000_0000 + A non-volatile memory from which ARC core may execute code directly. + Still is is not direcly writable, thus this is not an ordinary RAM. + + - ICCM: 256 KiB @ 0x2000_0000 + Instruction Closely Coupled Memory - fast on-chip memory primary used + for code being executed, still data could be placed in this memory too. + In that sense it's just a general purpose RAM. + + - SRAM: 128 KiB @ 0x3000_0000 + On-chip SRAM. From user perspective is the same as ICCM above. + + - DCCM: 128 KiB @ 0x8000_0000 + Data Closely Coupled Memory is similar to ICCM with a major difference - + ARC core cannot execute code from DCCM. So this is very special RAM + only suitable for data. + + BUILDING U-BOOT + + 1. Configure U-Boot: + ------------------------->8---------------------- + make iot_devkit_defconfig + ------------------------->8---------------------- + + 2. To build Elf file (for example to be used with host debugger via JTAG + connection to the target board): + ------------------------->8---------------------- + make mdbtrick + ------------------------->8---------------------- + + This will produce `u-boot` Elf file. + + 3. To build binary image to be put in "ROM": + ------------------------->8---------------------- + make u-boot.bin + ------------------------->8---------------------- + + + EXECUTING U-BOOT + + 1. The IoTDK board is supposed to auto-start U-Boot image stored in eFlash on + power-on. Note it's possible to update that image - follow instructions in + user's manual. + + 2. Though it is possible to load and start U-Boot as a simple Elf file + via JTAG right in ICCM. For that it's required to re-configure U-Boot + so it gets linked to ICCM address 0x2000_0000 (remember eFlash is not + direcly writable). + Run U-Boot's configuration utility with "make menuconfig", go to + "Boot images" and change "Text Base" from default 0x00000000 to + 0x20000000. Exit & save new configuration. Now run "make mdbtrick" to + build new Elf. + + 2.1. In case of proprietary MetaWare debugger run: + ------------------------->8---------------------- + mdb -digilent u-boot + ------------------------->8---------------------- + + USING U-BOOT + + Note due to limited memory size it's supposed that user will run binary + images of their applications instead of loading Elf files. + + 1. To load and start application binary from micro SD-card execute + the following commands in U-Boot's shell: + ------------------------->8---------------------- + fatload mmc 0 0x20000000 yourapp.bin + go 0x20000000 + ------------------------->8---------------------- + + 2. To load and start application binary from USB mass-storage device execute + the following commands in U-Boot's shell: + ------------------------->8---------------------- + usb start + fatload usb 0x20000000 yourapp.bin + go 0x20000000 + ------------------------->8---------------------- + + 3. To have a sequence of commands executed on U-Boot start put those + commands in "bootcmd" with semicolon between them. + For example to get (1) done automatically: + ------------------------->8---------------------- + setenv bootcmd fatload mmc 0 0x20000000 yourapp.bin\; go 0x20000000 + saveenv + ------------------------->8---------------------- + + 4. To reboot the board just run: + ------------------------->8---------------------- + reset + ------------------------->8---------------------- diff --git a/roms/u-boot/board/synopsys/iot_devkit/config.mk b/roms/u-boot/board/synopsys/iot_devkit/config.mk new file mode 100644 index 000000000..bd8f09ec7 --- /dev/null +++ b/roms/u-boot/board/synopsys/iot_devkit/config.mk @@ -0,0 +1,3 @@ +PLATFORM_CPPFLAGS += -mcpu=arcem -mlittle-endian -mcode-density -mdiv-rem \ + -mswap -mnorm -mmpy-option=6 -mbarrel-shifter +LDSCRIPT = $(srctree)/board/synopsys/iot_devkit/u-boot.lds diff --git a/roms/u-boot/board/synopsys/iot_devkit/iot_devkit.c b/roms/u-boot/board/synopsys/iot_devkit/iot_devkit.c new file mode 100644 index 000000000..650958f94 --- /dev/null +++ b/roms/u-boot/board/synopsys/iot_devkit/iot_devkit.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + */ + +#include <common.h> +#include <cpu_func.h> +#include <init.h> +#include <malloc.h> +#include <dwmmc.h> +#include <asm/global_data.h> +#include <linux/bitops.h> +#include <linux/libfdt.h> +#include <fdtdec.h> + +#include <asm/arcregs.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define SYSCON_BASE 0xf000a000 +#define AHBCKDIV (void *)(SYSCON_BASE + 0x04) +#define APBCKDIV (void *)(SYSCON_BASE + 0x08) +#define APBCKEN (void *)(SYSCON_BASE + 0x0C) +#define RESET_REG (void *)(SYSCON_BASE + 0x18) +#define CLKSEL (void *)(SYSCON_BASE + 0x24) +#define CLKSTAT (void *)(SYSCON_BASE + 0x28) +#define PLLCON (void *)(SYSCON_BASE + 0x2C) +#define APBCKSEL (void *)(SYSCON_BASE + 0x30) +#define AHBCKEN (void *)(SYSCON_BASE + 0x34) +#define USBPHY_PLL (void *)(SYSCON_BASE + 0x78) +#define USBCFG (void *)(SYSCON_BASE + 0x7c) + +#define PLL_MASK_0 0xffcfffff +#define PLL_MASK_1 0xffcfff00 +#define PLL_MASK_2 0xfbcfff00 + +#define CLKSEL_DEFAULT 0x5a690000 + +static int set_cpu_freq(unsigned int clk) +{ + clk /= 1000000; + + /* Set clk to ext Xtal (LSN value 0) */ + writel(CLKSEL_DEFAULT, CLKSEL); + + switch (clk) { + case 16: + /* Bypass mode */ + return 0; + + case 50: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1, M=25, N=1, OD=3, PLL_OUT_CLK=50M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x300191, PLLCON); + /* pll_off=0, M=25, N=1, OD=3, PLL_OUT_CLK=50M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x300191, PLLCON); + break; + + case 72: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1, M=18, N=1, OD=2, PLL_OUT_CLK=72M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x200121, PLLCON); + /* pll_off=0, M=18, N=1, OD=2, PLL_OUT_CLK=72M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x200121, PLLCON); + break; + + case 100: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1,M=25, N=1, OD=2, PLL_OUT_CLK=100M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x200191, PLLCON); + /* pll_off=0,M=25, N=1, OD=2, PLL_OUT_CLK=100M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x200191, PLLCON); + break; + + case 136: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1, M=17, N=1, OD=1, PLL_OUT_CLK=136M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x100111, PLLCON); + /* pll_off=0, M=17, N=1, OD=1, PLL_OUT_CLK=136M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x100111, PLLCON); + break; + + case 144: + writel(readl(PLLCON) & PLL_MASK_0, PLLCON); + /* pll_off=1, M=18, N=1, OD=1, PLL_OUT_CLK=144M */ + writel((readl(PLLCON) & PLL_MASK_1) | 0x100121, PLLCON); + /* pll_off=0, M=18, N=1, OD=1, PLL_OUT_CLK=144M */ + writel((readl(PLLCON) & PLL_MASK_2) | 0x100121, PLLCON); + break; + + default: + return -EINVAL; + } + + while (!(readl(CLKSTAT) & 0x4)) + ; + + /* Set clk from PLL on bus (LSN = 1) */ + writel(CLKSEL_DEFAULT | BIT(0), CLKSEL); + + return 0; +} + +extern u8 __rom_end[]; +extern u8 __ram_start[]; +extern u8 __ram_end[]; + +/* + * Use mach_cpu_init() for .data section copy as board_early_init_f() will be + * too late: initf_dm() will use a value of "av_" variable from not yet + * initialized (by copy) area. + */ +int mach_cpu_init(void) +{ + int offset; + + /* Don't relocate U-Boot */ + gd->flags |= GD_FLG_SKIP_RELOC; + + /* Copy data from ROM to RAM */ + u8 *src = __rom_end; + u8 *dst = __ram_start; + + while (dst < __ram_end) + *dst++ = *src++; + + /* Enable debug uart */ +#define DEBUG_UART_BASE 0x80014000 +#define DEBUG_UART_DLF_OFFSET 0xc0 + write_aux_reg(DEBUG_UART_BASE + DEBUG_UART_DLF_OFFSET, 1); + + offset = fdt_path_offset(gd->fdt_blob, "/cpu_card/core_clk"); + if (offset < 0) + return offset; + + gd->cpu_clk = fdtdec_get_int(gd->fdt_blob, offset, "clock-frequency", 0); + if (!gd->cpu_clk) + return -EINVAL; + + /* If CPU freq > 100 MHz, divide eFLASH clock by 2 */ + if (gd->cpu_clk > 100000000) { + u32 reg = readl(AHBCKDIV); + + reg &= ~(0xF << 8); + reg |= 2 << 8; + writel(reg, AHBCKDIV); + } + + return set_cpu_freq(gd->cpu_clk); +} + +#define IOTDK_RESET_SEQ 0x55AA6699 + +void reset_cpu(void) +{ + writel(IOTDK_RESET_SEQ, RESET_REG); +} + +int checkboard(void) +{ + puts("Board: Synopsys IoT Development Kit\n"); + return 0; +}; diff --git a/roms/u-boot/board/synopsys/iot_devkit/u-boot.lds b/roms/u-boot/board/synopsys/iot_devkit/u-boot.lds new file mode 100644 index 000000000..d08316870 --- /dev/null +++ b/roms/u-boot/board/synopsys/iot_devkit/u-boot.lds @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> + +MEMORY { + ROM : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE + RAM : ORIGIN = RAM_DATA_BASE, LENGTH = RAM_DATA_SIZE +} + +OUTPUT_FORMAT("elf32-littlearc", "elf32-littlearc", "elf32-littlearc") +OUTPUT_ARCH(arc) +ENTRY(_start) +SECTIONS +{ + . = CONFIG_SYS_MONITOR_BASE; + __image_copy_start = .; + .ivt : + { + __ivt_start = .; + KEEP(*(.ivt)); + __ivt_end = .; + } > ROM + + . = ALIGN(1024); + .text : { + __text_start = .; + arch/arc/lib/start.o (.text*) + *(.text*) + __text_end = .; + } > ROM + + . = ALIGN(4); + .rodata : { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } > ROM + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + + /* Mark RAM's LMA */ + . = ALIGN(4); + __rom_end = .; + } > ROM + + .data : { + /* Mark RAM's VMA */ + . = ALIGN(4); + + /* + * Everything between __ram_start and __ram_start will be + * copied from ROM to RAM in board_early_init_f(). + */ + __ram_start = .; + + *(.data*) + + __ram_end = .; + } > RAM AT > ROM + + .bss : { + . = ALIGN(1024); + __bss_start = .; + *(.bss*) + __bss_end = .; + } > RAM + + /* Keep relocation-related symbols to make linker happy */ + __rel_dyn_start = .; + __rel_dyn_end = .; + __image_copy_end = .; + __init_end = .; +} diff --git a/roms/u-boot/board/synopsys/nsim/Kconfig b/roms/u-boot/board/synopsys/nsim/Kconfig new file mode 100644 index 000000000..b6966b299 --- /dev/null +++ b/roms/u-boot/board/synopsys/nsim/Kconfig @@ -0,0 +1,21 @@ +if TARGET_NSIM + +config SYS_BOARD + default "nsim" + +config SYS_VENDOR + default "synopsys" + +config SYS_CONFIG_NAME + default "nsim" + +config NSIM_BOARD_CPPFLAGS + string "board arc-specific compiler options" + help + For nSIM we allow to set custom arc-specific compiler options + (like -mcpu=) instead of hardcoding them in its makefile as nSIM + target is used for representing targets without fixed CPU version + like FPGA-based boards and software simulators. + This variable takes space separated compiler options list. + +endif diff --git a/roms/u-boot/board/synopsys/nsim/MAINTAINERS b/roms/u-boot/board/synopsys/nsim/MAINTAINERS new file mode 100644 index 000000000..ad23c8338 --- /dev/null +++ b/roms/u-boot/board/synopsys/nsim/MAINTAINERS @@ -0,0 +1,6 @@ +ARC SIMULATION & PROTOTYPING PLATFORMS +M: Alexey Brodkin <abrodkin@synopsys.com> +S: Maintained +F: arch/arc/dts/nsim.dts +F: board/synopsys/nsim/ +F: configs/nsim_*_defconfig diff --git a/roms/u-boot/board/synopsys/nsim/Makefile b/roms/u-boot/board/synopsys/nsim/Makefile new file mode 100644 index 000000000..6aaffffa7 --- /dev/null +++ b/roms/u-boot/board/synopsys/nsim/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2020 Synopsys, Inc. All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += nsim.o diff --git a/roms/u-boot/board/synopsys/nsim/config.mk b/roms/u-boot/board/synopsys/nsim/config.mk new file mode 100644 index 000000000..40f9578a2 --- /dev/null +++ b/roms/u-boot/board/synopsys/nsim/config.mk @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Synopsys, Inc. All rights reserved. + +# CONFIG_NSIM_BOARD_CPPFLAGS is a string variable which comes from defconfig +# with double quotes. We use echo to remove them so CONFIG_NSIM_BOARD_CPPFLAGS +# won't be treated by compiler as a single option. +PLATFORM_CPPFLAGS += $(shell echo $(CONFIG_NSIM_BOARD_CPPFLAGS)) diff --git a/roms/u-boot/board/synopsys/nsim/nsim.c b/roms/u-boot/board/synopsys/nsim/nsim.c new file mode 100644 index 000000000..00e5cc364 --- /dev/null +++ b/roms/u-boot/board/synopsys/nsim/nsim.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Synopsys, Inc. All rights reserved. + */ + +#include <common.h> +#include <init.h> +#include <dm/device.h> +#include <virtio_types.h> +#include <virtio.h> + +int board_early_init_r(void) +{ + /* + * Make sure virtio bus is enumerated so that peripherals + * on the virtio bus can be discovered by their drivers + */ + virtio_init(); + + return 0; +} + +int checkboard(void) +{ + printf("Board: ARC virtual or prototyping platform\n"); + return 0; +}; |