diff options
Diffstat (limited to 'arch')
58 files changed, 1285 insertions, 270 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index c43787c6396..92d4b97701b 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1,6 +1,9 @@ config CREATE_ARCH_SYMLINK bool +config HAVE_ARCH_IOREMAP + bool + choice prompt "Architecture select" default SANDBOX @@ -33,6 +36,7 @@ config MICROBLAZE config MIPS bool "MIPS architecture" + select HAVE_ARCH_IOREMAP select HAVE_PRIVATE_LIBGCC select SUPPORT_OF_CONTROL diff --git a/arch/arm/cpu/arm11/cpu.c b/arch/arm/cpu/arm11/cpu.c index 1e4c2142b13..7244c2e7d79 100644 --- a/arch/arm/cpu/arm11/cpu.c +++ b/arch/arm/cpu/arm11/cpu.c @@ -69,23 +69,6 @@ void flush_dcache_all(void) asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); } -static int check_cache_range(unsigned long start, unsigned long stop) -{ - int ok = 1; - - if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (!ok) - debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", - start, stop); - - return ok; -} - void invalidate_dcache_range(unsigned long start, unsigned long stop) { if (!check_cache_range(start, stop)) diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c index 2839c863e82..2119382ab24 100644 --- a/arch/arm/cpu/arm926ejs/cache.c +++ b/arch/arm/cpu/arm926ejs/cache.c @@ -29,23 +29,6 @@ void flush_dcache_all(void) ); } -static int check_cache_range(unsigned long start, unsigned long stop) -{ - int ok = 1; - - if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (!ok) - debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", - start, stop); - - return ok; -} - void invalidate_dcache_range(unsigned long start, unsigned long stop) { if (!check_cache_range(start, stop)) diff --git a/arch/arm/cpu/armv7/am33xx/config.mk b/arch/arm/cpu/armv7/am33xx/config.mk index 6d95d327b45..ab9470820d5 100644 --- a/arch/arm/cpu/armv7/am33xx/config.mk +++ b/arch/arm/cpu/armv7/am33xx/config.mk @@ -26,6 +26,7 @@ endif else ifeq ($(CONFIG_TI_SECURE_DEVICE),y) ALL-$(CONFIG_QSPI_BOOT) += u-boot_HS_XIP_X-LOADER +ALL-y += u-boot_HS.img endif ALL-y += u-boot.img endif diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c index dc309dac909..52f18565db2 100644 --- a/arch/arm/cpu/armv7/cache_v7.c +++ b/arch/arm/cpu/armv7/cache_v7.c @@ -19,23 +19,6 @@ void v7_flush_dcache_all(void); void v7_invalidate_dcache_all(void); -static int check_cache_range(unsigned long start, unsigned long stop) -{ - int ok = 1; - - if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (!ok) - debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", - start, stop); - - return ok; -} - static u32 get_ccsidr(void) { u32 ccsidr; @@ -61,27 +44,8 @@ static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len) { u32 mva; - /* - * If start address is not aligned to cache-line do not - * invalidate the first cache-line - */ - if (start & (line_len - 1)) { - printf("ERROR: %s - start address is not aligned - 0x%08x\n", - __func__, start); - /* move to next cache line */ - start = (start + line_len - 1) & ~(line_len - 1); - } - - /* - * If stop address is not aligned to cache-line do not - * invalidate the last cache-line - */ - if (stop & (line_len - 1)) { - printf("ERROR: %s - stop address is not aligned - 0x%08x\n", - __func__, stop); - /* align to the beginning of this cache line */ - stop &= ~(line_len - 1); - } + if (!check_cache_range(start, stop)) + return; for (mva = start; mva < stop; mva = mva + line_len) { /* DCIMVAC - Invalidate data cache by MVA to PoC */ @@ -195,6 +159,14 @@ void flush_dcache_all(void) { } +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} + void arm_init_before_mmu(void) { } diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile index 87a7ac03f92..3172bae105b 100644 --- a/arch/arm/cpu/armv7/omap-common/Makefile +++ b/arch/arm/cpu/armv7/omap-common/Makefile @@ -36,3 +36,5 @@ obj-y += boot-common.o obj-y += lowlevel_init.o obj-y += mem-common.o + +obj-$(CONFIG_TI_SECURE_DEVICE) += sec-common.o diff --git a/arch/arm/cpu/armv7/omap-common/config_secure.mk b/arch/arm/cpu/armv7/omap-common/config_secure.mk index c7bb101be8e..1122439e38b 100644 --- a/arch/arm/cpu/armv7/omap-common/config_secure.mk +++ b/arch/arm/cpu/armv7/omap-common/config_secure.mk @@ -12,8 +12,8 @@ cmd_mkomapsecimg = $(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh \ $(if $(KBUILD_VERBOSE:1=), >/dev/null) else cmd_mkomapsecimg = $(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh \ - $(patsubst u-boot_HS_%,%,$(@F)) $< $@ $(CONFIG_ISW_ENTRY_ADDR) \ - $(if $(KBUILD_VERBOSE:1=), >/dev/null) + $(patsubst u-boot_HS_%,%,$(@F)) $< $@ $(CONFIG_ISW_ENTRY_ADDR) \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) endif else cmd_mkomapsecimg = echo "WARNING:" \ @@ -25,14 +25,33 @@ cmd_mkomapsecimg = echo "WARNING: TI_SECURE_DEV_PKG environment" \ "variable must be defined for TI secure devices. $@ was NOT created!" endif +ifdef CONFIG_SPL_LOAD_FIT +quiet_cmd_omapsecureimg = SECURE $@ +ifneq ($(TI_SECURE_DEV_PKG),) +ifneq ($(wildcard $(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh),) +cmd_omapsecureimg = $(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh \ + $< $@ \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) +else +cmd_omapsecureimg = echo "WARNING:" \ + "$(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh not found." \ + "$@ was NOT created!"; cp $< $@ +endif +else +cmd_omapsecureimg = echo "WARNING: TI_SECURE_DEV_PKG environment" \ + "variable must be defined for TI secure devices." \ + "$@ was NOT created!"; cp $< $@ +endif +endif + + # Standard X-LOADER target (QPSI, NOR flash) u-boot-spl_HS_X-LOADER: $(obj)/u-boot-spl.bin $(call if_changed,mkomapsecimg) -# For MLO targets (SD card boot) the final file name -# that is copied to the SD card fAT partition must -# be MLO, so we make a copy of the output file to a -# new file with that name +# For MLO targets (SD card boot) the final file name that is copied to the SD +# card FAT partition must be MLO, so we make a copy of the output file to a new +# file with that name u-boot-spl_HS_MLO: $(obj)/u-boot-spl.bin $(call if_changed,mkomapsecimg) @if [ -f $@ ]; then \ @@ -51,16 +70,44 @@ u-boot-spl_HS_ULO: $(obj)/u-boot-spl.bin u-boot-spl_HS_ISSW: $(obj)/u-boot-spl.bin $(call if_changed,mkomapsecimg) -# For SPI flash on AM335x and AM43xx, these -# require special byte swap handling so we use -# the SPI_X-LOADER target instead of X-LOADER -# and let the create-boot-image.sh script handle -# that +# For SPI flash on AM335x and AM43xx, these require special byte swap handling +# so we use the SPI_X-LOADER target instead of X-LOADER and let the +# create-boot-image.sh script handle that u-boot-spl_HS_SPI_X-LOADER: $(obj)/u-boot-spl.bin $(call if_changed,mkomapsecimg) -# For supporting single stage XiP QSPI on AM43xx, the -# image is a full u-boot file, not an SPL. In this case -# the mkomapsecimg command looks for a u-boot-HS_* prefix +# For supporting single stage XiP QSPI on AM43xx, the image is a full u-boot +# file, not an SPL. In this case the mkomapsecimg command looks for a +# u-boot-HS_* prefix u-boot_HS_XIP_X-LOADER: $(obj)/u-boot.bin $(call if_changed,mkomapsecimg) + +# For supporting the SPL loading and interpreting of FIT images whose +# components are pre-processed before being integrated into the FIT image in +# order to secure them in some way +ifdef CONFIG_SPL_LOAD_FIT + +MKIMAGEFLAGS_u-boot_HS.img = -f auto -A $(ARCH) -T firmware -C none -O u-boot \ + -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \ + -n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \ + $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) + +OF_LIST_TARGETS = $(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) +$(OF_LIST_TARGETS): dtbs + +%_HS.dtb: %.dtb + $(call if_changed,omapsecureimg) + $(Q)if [ -f $@ ]; then \ + cp -f $@ $<; \ + fi + +u-boot-nodtb_HS.bin: u-boot-nodtb.bin + $(call if_changed,omapsecureimg) + +u-boot_HS.img: u-boot-nodtb_HS.bin u-boot.img $(patsubst %.dtb,%_HS.dtb,$(OF_LIST_TARGETS)) + $(call if_changed,mkimage) + $(Q)if [ -f $@ ]; then \ + cp -f $@ u-boot.img; \ + fi + +endif diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index 9a9c764b4d1..2b790105b0b 100644 --- a/arch/arm/cpu/armv7/omap-common/emif-common.c +++ b/arch/arm/cpu/armv7/omap-common/emif-common.c @@ -37,7 +37,8 @@ void set_lpmode_selfrefresh(u32 base) void force_emif_self_refresh() { set_lpmode_selfrefresh(EMIF1_BASE); - set_lpmode_selfrefresh(EMIF2_BASE); + if (!is_dra72x()) + set_lpmode_selfrefresh(EMIF2_BASE); } inline u32 emif_num(u32 base) diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c index 2f9693f28e9..f3172939889 100644 --- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c +++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -147,8 +147,7 @@ void early_system_init(void) hw_data_init(); #ifdef CONFIG_SPL_BUILD - if (warm_reset() && - (is_omap44xx() || (omap_revision() == OMAP5430_ES1_0))) + if (warm_reset()) force_emif_self_refresh(); #endif watchdog_init(); diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S index 528313584f3..66a3b3d26c9 100644 --- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S +++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S @@ -16,9 +16,10 @@ #include <asm/arch/spl.h> #include <linux/linkage.h> +.arch_extension sec + #ifdef CONFIG_SPL ENTRY(save_boot_params) - ldr r1, =OMAP_SRAM_SCRATCH_BOOT_PARAMS str r0, [r1] b save_boot_params_ret @@ -26,14 +27,40 @@ ENDPROC(save_boot_params) #endif ENTRY(omap_smc1) - PUSH {r4-r12, lr} @ save registers - ROM code may pollute + push {r4-r12, lr} @ save registers - ROM code may pollute @ our registers - MOV r12, r0 @ Service - MOV r0, r1 @ Argument - DSB - DMB - .word 0xe1600070 @ SMC #0 - hand assembled for GCC versions - @ call ROM Code API for the service requested + mov r12, r0 @ Service + mov r0, r1 @ Argument - POP {r4-r12, pc} + dsb + dmb + smc 0 @ SMC #0 to enter monitor mode + @ call ROM Code API for the service requested + pop {r4-r12, pc} ENDPROC(omap_smc1) + +ENTRY(omap_smc_sec) + push {r4-r12, lr} @ save registers - ROM code may pollute + @ our registers + mov r6, #0xFF @ Indicate new Task call + mov r12, #0x00 @ Secure Service ID in R12 + + dsb + dmb + smc 0 @ SMC #0 to enter monitor mode + + b omap_smc_sec_end @ exit at end of the service execution + nop + + @ In case of IRQ happening in Secure, then ARM will branch here. + @ At that moment, IRQ will be pending and ARM will jump to Non Secure + @ IRQ handler + mov r12, #0xFE + + dsb + dmb + smc 0 @ SMC #0 to enter monitor mode + +omap_smc_sec_end: + pop {r4-r12, pc} +ENDPROC(omap_smc_sec) diff --git a/arch/arm/cpu/armv7/omap-common/sec-common.c b/arch/arm/cpu/armv7/omap-common/sec-common.c new file mode 100644 index 00000000000..246a2393dab --- /dev/null +++ b/arch/arm/cpu/armv7/omap-common/sec-common.c @@ -0,0 +1,139 @@ +/* + * + * Common security related functions for OMAP devices + * + * (C) Copyright 2016 + * Texas Instruments, <www.ti.com> + * + * Daniel Allred <d-allred@ti.com> + * Andreas Dannenberg <dannenberg@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <stdarg.h> + +#include <asm/arch/sys_proto.h> +#include <asm/omap_common.h> +#include <asm/omap_sec_common.h> +#include <asm/spl.h> +#include <spl.h> + +/* Index for signature verify ROM API */ +#define API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX (0x0000000E) + +static uint32_t secure_rom_call_args[5] __aligned(ARCH_DMA_MINALIGN); + +u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...) +{ + int i; + u32 num_args; + va_list ap; + + va_start(ap, flag); + + num_args = va_arg(ap, u32); + + if (num_args > 4) + return 1; + + /* Copy args to aligned args structure */ + for (i = 0; i < num_args; i++) + secure_rom_call_args[i + 1] = va_arg(ap, u32); + + secure_rom_call_args[0] = num_args; + + va_end(ap); + + /* if data cache is enabled, flush the aligned args structure */ + flush_dcache_range( + (unsigned int)&secure_rom_call_args[0], + (unsigned int)&secure_rom_call_args[0] + + roundup(sizeof(secure_rom_call_args), ARCH_DMA_MINALIGN)); + + return omap_smc_sec(service, proc_id, flag, secure_rom_call_args); +} + +static u32 find_sig_start(char *image, size_t size) +{ + char *image_end = image + size; + char *sig_start_magic = "CERT_"; + int magic_str_len = strlen(sig_start_magic); + char *ch; + + while (--image_end > image) { + if (*image_end == '_') { + ch = image_end - magic_str_len + 1; + if (!strncmp(ch, sig_start_magic, magic_str_len)) + return (u32)ch; + } + } + return 0; +} + +int secure_boot_verify_image(void **image, size_t *size) +{ + int result = 1; + u32 cert_addr, sig_addr; + size_t cert_size; + + /* Perform cache writeback on input buffer */ + flush_dcache_range( + (u32)*image, + (u32)*image + roundup(*size, ARCH_DMA_MINALIGN)); + + cert_addr = (uint32_t)*image; + sig_addr = find_sig_start((char *)*image, *size); + + if (sig_addr == 0) { + printf("No signature found in image!\n"); + result = 1; + goto auth_exit; + } + + *size = sig_addr - cert_addr; /* Subtract out the signature size */ + cert_size = *size; + + /* Check if image load address is 32-bit aligned */ + if (!IS_ALIGNED(cert_addr, 4)) { + printf("Image is not 4-byte aligned!\n"); + result = 1; + goto auth_exit; + } + + /* Image size also should be multiple of 4 */ + if (!IS_ALIGNED(cert_size, 4)) { + printf("Image size is not 4-byte aligned!\n"); + result = 1; + goto auth_exit; + } + + /* Call ROM HAL API to verify certificate signature */ + debug("%s: load_addr = %x, size = %x, sig_addr = %x\n", __func__, + cert_addr, cert_size, sig_addr); + + result = secure_rom_call( + API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX, 0, 0, + 4, cert_addr, cert_size, sig_addr, 0xFFFFFFFF); +auth_exit: + if (result != 0) { + printf("Authentication failed!\n"); + printf("Return Value = %08X\n", result); + hang(); + } + + /* + * Output notification of successful authentication as well the name of + * the signing certificate used to re-assure the user that the secure + * code is being processed as expected. However suppress any such log + * output in case of building for SPL and booting via YMODEM. This is + * done to avoid disturbing the YMODEM serial protocol transactions. + */ + if (!(IS_ENABLED(CONFIG_SPL_BUILD) && + IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) && + spl_boot_device() == BOOT_DEVICE_UART)) + printf("Authentication passed: %s\n", (char *)sig_addr); + + return result; +} diff --git a/arch/arm/cpu/armv7/omap5/config.mk b/arch/arm/cpu/armv7/omap5/config.mk index a7e55a5e244..d245572ef04 100644 --- a/arch/arm/cpu/armv7/omap5/config.mk +++ b/arch/arm/cpu/armv7/omap5/config.mk @@ -15,5 +15,8 @@ else ALL-y += MLO endif else +ifeq ($(CONFIG_TI_SECURE_DEVICE),y) +ALL-y += u-boot_HS.img +endif ALL-y += u-boot.img endif diff --git a/arch/arm/cpu/armv7m/config.mk b/arch/arm/cpu/armv7m/config.mk index 4a53006b6a7..db4660e15da 100644 --- a/arch/arm/cpu/armv7m/config.mk +++ b/arch/arm/cpu/armv7m/config.mk @@ -5,4 +5,4 @@ # SPDX-License-Identifier: GPL-2.0+ # -PLATFORM_CPPFLAGS += -march=armv7-m -mthumb +PLATFORM_CPPFLAGS += -march=armv7-m -mthumb -mno-unaligned-access diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig index 3d19bbfbe24..acf2460ede2 100644 --- a/arch/arm/cpu/armv8/Kconfig +++ b/arch/arm/cpu/armv8/Kconfig @@ -3,4 +3,22 @@ if ARM64 config ARMV8_MULTIENTRY boolean "Enable multiple CPUs to enter into U-Boot" +config ARMV8_SPIN_TABLE + bool "Support spin-table enable method" + depends on ARMV8_MULTIENTRY && OF_LIBFDT + help + Say Y here to support "spin-table" enable method for booting Linux. + + To use this feature, you must do: + - Specify enable-method = "spin-table" in each CPU node in the + Device Tree you are using to boot the kernel + - Let secondary CPUs in U-Boot (in a board specific manner) + before the master CPU jumps to the kernel + + U-Boot automatically does: + - Set "cpu-release-addr" property of each CPU node + (overwrites it if already exists). + - Reserve the code for the spin-table and the release address + via a /memreserve/ region in the Device Tree. + endif diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile index bf8644ccd2e..f6eb9f4a7fb 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -15,6 +15,9 @@ obj-y += cache.o obj-y += tlb.o obj-y += transition.o obj-y += fwcall.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o +endif obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/ obj-$(CONFIG_S32V234) += s32v234/ diff --git a/arch/arm/cpu/armv8/spin_table.c b/arch/arm/cpu/armv8/spin_table.c new file mode 100644 index 00000000000..ec1c9b8ddb6 --- /dev/null +++ b/arch/arm/cpu/armv8/spin_table.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <libfdt.h> +#include <asm/spin_table.h> + +int spin_table_update_dt(void *fdt) +{ + int cpus_offset, offset; + const char *prop; + int ret; + unsigned long rsv_addr = (unsigned long)&spin_table_reserve_begin; + unsigned long rsv_size = &spin_table_reserve_end - + &spin_table_reserve_begin; + + cpus_offset = fdt_path_offset(fdt, "/cpus"); + if (cpus_offset < 0) + return -ENODEV; + + for (offset = fdt_first_subnode(fdt, cpus_offset); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) { + prop = fdt_getprop(fdt, offset, "device_type", NULL); + if (!prop || strcmp(prop, "cpu")) + continue; + + /* + * In the first loop, we check if every CPU node specifies + * spin-table. Otherwise, just return successfully to not + * disturb other methods, like psci. + */ + prop = fdt_getprop(fdt, offset, "enable-method", NULL); + if (!prop || strcmp(prop, "spin-table")) + return 0; + } + + for (offset = fdt_first_subnode(fdt, cpus_offset); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) { + prop = fdt_getprop(fdt, offset, "device_type", NULL); + if (!prop || strcmp(prop, "cpu")) + continue; + + ret = fdt_setprop_u64(fdt, offset, "cpu-release-addr", + (unsigned long)&spin_table_cpu_release_addr); + if (ret) + return -ENOSPC; + } + + ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size); + if (ret) + return -ENOSPC; + + printf(" Reserved memory region for spin-table: addr=%lx size=%lx\n", + rsv_addr, rsv_size); + + return 0; +} diff --git a/arch/arm/cpu/armv8/spin_table_v8.S b/arch/arm/cpu/armv8/spin_table_v8.S new file mode 100644 index 00000000000..d7f78a6a673 --- /dev/null +++ b/arch/arm/cpu/armv8/spin_table_v8.S @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <linux/linkage.h> + +ENTRY(spin_table_secondary_jump) +.globl spin_table_reserve_begin +spin_table_reserve_begin: +0: wfe + ldr x0, spin_table_cpu_release_addr + cbz x0, 0b + br x0 +.globl spin_table_cpu_release_addr + .align 3 +spin_table_cpu_release_addr: + .quad 0 +.globl spin_table_reserve_end +spin_table_reserve_end: +ENDPROC(spin_table_secondary_jump) diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index 670e323b61b..67edf94520c 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -94,7 +94,11 @@ reset: /* Processor specific initialization */ bl lowlevel_init -#ifdef CONFIG_ARMV8_MULTIENTRY +#if CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE) + branch_if_master x0, x1, master_cpu + b spin_table_secondary_jump + /* never return */ +#elif defined(CONFIG_ARMV8_MULTIENTRY) branch_if_master x0, x1, master_cpu /* @@ -106,10 +110,8 @@ slave_cpu: ldr x0, [x1] cbz x0, slave_cpu br x0 /* branch to the given address */ -master_cpu: - /* On the master CPU */ #endif /* CONFIG_ARMV8_MULTIENTRY */ - +master_cpu: bl _main #ifdef CONFIG_SYS_RESET_SCTRL diff --git a/arch/arm/dts/exynos4210-origen.dts b/arch/arm/dts/exynos4210-origen.dts index 3f877615844..26c4d7f4c64 100644 --- a/arch/arm/dts/exynos4210-origen.dts +++ b/arch/arm/dts/exynos4210-origen.dts @@ -22,7 +22,7 @@ aliases { serial0 = "/serial@13800000"; console = "/serial@13820000"; - mmc2 = "sdhci@12530000"; + mmc2 = "/sdhci@12530000"; }; sdhci@12510000 { diff --git a/arch/arm/dts/exynos4210-trats.dts b/arch/arm/dts/exynos4210-trats.dts index f3fac801905..2ed38f369e4 100644 --- a/arch/arm/dts/exynos4210-trats.dts +++ b/arch/arm/dts/exynos4210-trats.dts @@ -29,8 +29,8 @@ i2c7 = "/i2c@138d0000"; serial0 = "/serial@13800000"; console = "/serial@13820000"; - mmc0 = "sdhci@12510000"; - mmc2 = "sdhci@12530000"; + mmc0 = "/sdhci@12510000"; + mmc2 = "/sdhci@12530000"; }; fimd@11c00000 { diff --git a/arch/arm/dts/exynos4210-universal_c210.dts b/arch/arm/dts/exynos4210-universal_c210.dts index ad3527ec6f1..8cac7dd752e 100644 --- a/arch/arm/dts/exynos4210-universal_c210.dts +++ b/arch/arm/dts/exynos4210-universal_c210.dts @@ -17,8 +17,8 @@ aliases { serial0 = "/serial@13800000"; console = "/serial@13820000"; - mmc0 = "sdhci@12510000"; - mmc2 = "sdhci@12530000"; + mmc0 = "/sdhci@12510000"; + mmc2 = "/sdhci@12530000"; }; sdhci@12510000 { diff --git a/arch/arm/dts/exynos4412-odroid.dts b/arch/arm/dts/exynos4412-odroid.dts index a63e8abab4a..188cb939bb8 100644 --- a/arch/arm/dts/exynos4412-odroid.dts +++ b/arch/arm/dts/exynos4412-odroid.dts @@ -25,8 +25,8 @@ i2c7 = "/i2c@138d0000"; serial0 = "/serial@13800000"; console = "/serial@13810000"; - mmc2 = "sdhci@12530000"; - mmc4 = "dwmmc@12550000"; + mmc2 = "/sdhci@12530000"; + mmc4 = "/dwmmc@12550000"; }; i2c@13860000 { diff --git a/arch/arm/dts/exynos4412-trats2.dts b/arch/arm/dts/exynos4412-trats2.dts index 2d4e522ea27..1fbcf8914fa 100644 --- a/arch/arm/dts/exynos4412-trats2.dts +++ b/arch/arm/dts/exynos4412-trats2.dts @@ -29,9 +29,9 @@ i2c7 = "/i2c@138d0000"; serial0 = "/serial@13800000"; console = "/serial@13820000"; - mmc0 = "sdhci@12510000"; - mmc2 = "sdhci@12530000"; - mmc4 = "dwmmc@12550000"; + mmc0 = "/sdhci@12510000"; + mmc2 = "/sdhci@12530000"; + mshc0 = "/dwmmc@12550000"; }; i2c@138d0000 { diff --git a/arch/arm/dts/rk3288-firefly.dts b/arch/arm/dts/rk3288-firefly.dts index aed8d3a712b..3176d5046b2 100644 --- a/arch/arm/dts/rk3288-firefly.dts +++ b/arch/arm/dts/rk3288-firefly.dts @@ -30,7 +30,8 @@ 0x5 0x0>; rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200 0xa60 0x40 0x10 0x0>; - rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>; + /* Add a dummy value to cause of-platdata think this is bytes */ + rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf 0xff>; rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>; }; diff --git a/arch/arm/include/asm/arch-rockchip/sdram.h b/arch/arm/include/asm/arch-rockchip/sdram.h index d3de42d2977..e08e28f4f0c 100644 --- a/arch/arm/include/asm/arch-rockchip/sdram.h +++ b/arch/arm/include/asm/arch-rockchip/sdram.h @@ -24,6 +24,12 @@ struct rk3288_sdram_channel { u8 row_3_4; u8 cs0_row; u8 cs1_row; + /* + * For of-platdata, which would otherwise convert this into two + * byte-swapped integers. With a size of 9 bytes, this struct will + * appear in of-platdata as a byte array. + */ + u8 dummy; }; struct rk3288_sdram_pctl_timing { @@ -81,12 +87,4 @@ struct rk3288_base_params { u32 odt; }; -struct rk3288_sdram_params { - struct rk3288_sdram_channel ch[2]; - struct rk3288_sdram_pctl_timing pctl_timing; - struct rk3288_sdram_phy_timing phy_timing; - struct rk3288_base_params base; - int num_channels; -}; - #endif diff --git a/arch/arm/include/asm/arch-stm32f7/fmc.h b/arch/arm/include/asm/arch-stm32f7/fmc.h new file mode 100644 index 00000000000..7dd5077d0c3 --- /dev/null +++ b/arch/arm/include/asm/arch-stm32f7/fmc.h @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2013 + * Pavel Boldin, Emcraft Systems, paboldin@emcraft.com + * + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _MACH_FMC_H_ +#define _MACH_FMC_H_ + +struct stm32_fmc_regs { + u32 sdcr1; /* Control register 1 */ + u32 sdcr2; /* Control register 2 */ + u32 sdtr1; /* Timing register 1 */ + u32 sdtr2; /* Timing register 2 */ + u32 sdcmr; /* Mode register */ + u32 sdrtr; /* Refresh timing register */ + u32 sdsr; /* Status register */ +}; + +/* + * FMC registers base + */ +#define STM32_SDRAM_FMC_BASE 0xA0000140 +#define STM32_SDRAM_FMC ((struct stm32_fmc_regs *)STM32_SDRAM_FMC_BASE) + +/* Control register SDCR */ +#define FMC_SDCR_RPIPE_SHIFT 13 /* RPIPE bit shift */ +#define FMC_SDCR_RBURST_SHIFT 12 /* RBURST bit shift */ +#define FMC_SDCR_SDCLK_SHIFT 10 /* SDRAM clock divisor shift */ +#define FMC_SDCR_WP_SHIFT 9 /* Write protection shift */ +#define FMC_SDCR_CAS_SHIFT 7 /* CAS latency shift */ +#define FMC_SDCR_NB_SHIFT 6 /* Number of banks shift */ +#define FMC_SDCR_MWID_SHIFT 4 /* Memory width shift */ +#define FMC_SDCR_NR_SHIFT 2 /* Number of row address bits shift */ +#define FMC_SDCR_NC_SHIFT 0 /* Number of col address bits shift */ + +/* Timings register SDTR */ +#define FMC_SDTR_TMRD_SHIFT 0 /* Load mode register to active */ +#define FMC_SDTR_TXSR_SHIFT 4 /* Exit self-refresh time */ +#define FMC_SDTR_TRAS_SHIFT 8 /* Self-refresh time */ +#define FMC_SDTR_TRC_SHIFT 12 /* Row cycle delay */ +#define FMC_SDTR_TWR_SHIFT 16 /* Recovery delay */ +#define FMC_SDTR_TRP_SHIFT 20 /* Row precharge delay */ +#define FMC_SDTR_TRCD_SHIFT 24 /* Row-to-column delay */ + + +#define FMC_SDCMR_NRFS_SHIFT 5 + +#define FMC_SDCMR_MODE_NORMAL 0 +#define FMC_SDCMR_MODE_START_CLOCK 1 +#define FMC_SDCMR_MODE_PRECHARGE 2 +#define FMC_SDCMR_MODE_AUTOREFRESH 3 +#define FMC_SDCMR_MODE_WRITE_MODE 4 +#define FMC_SDCMR_MODE_SELFREFRESH 5 +#define FMC_SDCMR_MODE_POWERDOWN 6 + +#define FMC_SDCMR_BANK_1 (1 << 4) +#define FMC_SDCMR_BANK_2 (1 << 3) + +#define FMC_SDCMR_MODE_REGISTER_SHIFT 9 + +#define FMC_SDSR_BUSY (1 << 5) + +#define FMC_BUSY_WAIT() do { \ + __asm__ __volatile__ ("dsb" : : : "memory"); \ + while (STM32_SDRAM_FMC->sdsr & FMC_SDSR_BUSY) \ + ; \ + } while (0) + + +#endif /* _MACH_FMC_H_ */ diff --git a/arch/arm/include/asm/arch-stm32f7/stm32.h b/arch/arm/include/asm/arch-stm32f7/stm32.h index 68bdab069d4..de55ae5df15 100644 --- a/arch/arm/include/asm/arch-stm32f7/stm32.h +++ b/arch/arm/include/asm/arch-stm32f7/stm32.h @@ -64,6 +64,52 @@ enum clock { }; #define STM32_BUS_MASK 0xFFFF0000 +struct stm32_rcc_regs { + u32 cr; /* RCC clock control */ + u32 pllcfgr; /* RCC PLL configuration */ + u32 cfgr; /* RCC clock configuration */ + u32 cir; /* RCC clock interrupt */ + u32 ahb1rstr; /* RCC AHB1 peripheral reset */ + u32 ahb2rstr; /* RCC AHB2 peripheral reset */ + u32 ahb3rstr; /* RCC AHB3 peripheral reset */ + u32 rsv0; + u32 apb1rstr; /* RCC APB1 peripheral reset */ + u32 apb2rstr; /* RCC APB2 peripheral reset */ + u32 rsv1[2]; + u32 ahb1enr; /* RCC AHB1 peripheral clock enable */ + u32 ahb2enr; /* RCC AHB2 peripheral clock enable */ + u32 ahb3enr; /* RCC AHB3 peripheral clock enable */ + u32 rsv2; + u32 apb1enr; /* RCC APB1 peripheral clock enable */ + u32 apb2enr; /* RCC APB2 peripheral clock enable */ + u32 rsv3[2]; + u32 ahb1lpenr; /* RCC AHB1 periph clk enable in low pwr mode */ + u32 ahb2lpenr; /* RCC AHB2 periph clk enable in low pwr mode */ + u32 ahb3lpenr; /* RCC AHB3 periph clk enable in low pwr mode */ + u32 rsv4; + u32 apb1lpenr; /* RCC APB1 periph clk enable in low pwr mode */ + u32 apb2lpenr; /* RCC APB2 periph clk enable in low pwr mode */ + u32 rsv5[2]; + u32 bdcr; /* RCC Backup domain control */ + u32 csr; /* RCC clock control & status */ + u32 rsv6[2]; + u32 sscgr; /* RCC spread spectrum clock generation */ + u32 plli2scfgr; /* RCC PLLI2S configuration */ + u32 pllsaicfgr; + u32 dckcfgr; +}; +#define STM32_RCC ((struct stm32_rcc_regs *)RCC_BASE) + +struct stm32_pwr_regs { + u32 cr1; /* power control register 1 */ + u32 csr1; /* power control/status register 2 */ + u32 cr2; /* power control register 2 */ + u32 csr2; /* power control/status register 2 */ +}; +#define STM32_PWR ((struct stm32_pwr_regs *)PWR_BASE) + int configure_clocks(void); +unsigned long clock_get(enum clock clck); +void stm32_flash_latency_cfg(int latency); #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h index 38adc4e0e2f..0bd46957274 100644 --- a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h +++ b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h @@ -17,11 +17,13 @@ enum periph_id { UART1_GPIOA_9_10 = 0, UART2_GPIOD_5_6, + UART6_GPIOC_6_7, }; enum periph_clock { USART1_CLOCK_CFG = 0, USART2_CLOCK_CFG, + USART6_CLOCK_CFG, GPIO_A_CLOCK_CFG, GPIO_B_CLOCK_CFG, GPIO_C_CLOCK_CFG, diff --git a/arch/arm/include/asm/armv7m.h b/arch/arm/include/asm/armv7m.h index 200444dda14..54d8a2bdff6 100644 --- a/arch/arm/include/asm/armv7m.h +++ b/arch/arm/include/asm/armv7m.h @@ -51,10 +51,21 @@ struct v7m_mpu { #define V7M_MPU_CTRL_ENABLE (1 << 0) #define V7M_MPU_CTRL_HFNMIENA (1 << 1) +#define V7M_MPU_CTRL_ENABLE (1 << 0) +#define V7M_MPU_CTRL_DISABLE (0 << 0) +#define V7M_MPU_CTRL_HFNMIENA (1 << 1) + #define V7M_MPU_RASR_EN (1 << 0) #define V7M_MPU_RASR_SIZE_BITS 1 #define V7M_MPU_RASR_SIZE_4GB (31 << V7M_MPU_RASR_SIZE_BITS) +#define V7M_MPU_RASR_SIZE_8MB (24 << V7M_MPU_RASR_SIZE_BITS) +#define V7M_MPU_RASR_TEX_SHIFT 19 +#define V7M_MPU_RASR_S_SHIFT 18 +#define V7M_MPU_RASR_C_SHIFT 17 +#define V7M_MPU_RASR_B_SHIFT 16 #define V7M_MPU_RASR_AP_RW_RW (3 << 24) +#define V7M_MPU_RASR_XN_ENABLE (0 << 28) +#define V7M_MPU_RASR_XN_DISABLE (1 << 28) #endif /* !defined(__ASSEMBLY__) */ #endif /* ARMV7M_H */ diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h index 1f63127bdc8..16e65c36a9a 100644 --- a/arch/arm/include/asm/cache.h +++ b/arch/arm/include/asm/cache.h @@ -29,6 +29,8 @@ static inline void invalidate_l2_cache(void) } #endif +int check_cache_range(unsigned long start, unsigned long stop); + void l2_cache_enable(void); void l2_cache_disable(void); void set_section_dcache(int section, enum dcache_option option); diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 9d185a61223..6121f1ddcac 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -292,40 +292,6 @@ static inline void __raw_readsl(unsigned long addr, void *data, int longlen) #define readsb(a, d, s) __raw_readsb((unsigned long)a, d, s) /* - * ioremap and friends. - * - * ioremap takes a PCI memory address, as specified in - * linux/Documentation/IO-mapping.txt. If you want a - * physical address, use __ioremap instead. - */ -extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags); -extern void __iounmap(void *addr); - -/* - * Generic ioremap support. - * - * Define: - * iomem_valid_addr(off,size) - * iomem_to_phys(off) - */ -#ifdef iomem_valid_addr -#define __arch_ioremap(off,sz,nocache) \ - ({ \ - unsigned long _off = (off), _size = (sz); \ - void *_ret = (void *)0; \ - if (iomem_valid_addr(_off, _size)) \ - _ret = __ioremap(iomem_to_phys(_off),_size,nocache); \ - _ret; \ - }) - -#define __arch_iounmap __iounmap -#endif - -#define ioremap(off,sz) __arch_ioremap((off),(sz),0) -#define ioremap_nocache(off,sz) __arch_ioremap((off),(sz),1) -#define iounmap(_addr) __arch_iounmap(_addr) - -/* * DMA-consistent mapping functions. These allocate/free a region of * uncached, unwrite-buffered mapped memory space for use with DMA * devices. This is the "generic" version. The PCI specific version diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h index 07f384867eb..605c549f0a5 100644 --- a/arch/arm/include/asm/omap_common.h +++ b/arch/arm/include/asm/omap_common.h @@ -627,6 +627,12 @@ void recalibrate_iodelay(void); void omap_smc1(u32 service, u32 val); +/* + * Low-level helper function used when performing secure ROM calls on high- + * security (HS) device variants by doing a specially-formed smc entry. + */ +u32 omap_smc_sec(u32 service, u32 proc_id, u32 flag, u32 *params); + void enable_edma3_clocks(void); void disable_edma3_clocks(void); diff --git a/arch/arm/include/asm/omap_sec_common.h b/arch/arm/include/asm/omap_sec_common.h new file mode 100644 index 00000000000..842f2af8d12 --- /dev/null +++ b/arch/arm/include/asm/omap_sec_common.h @@ -0,0 +1,30 @@ +/* + * (C) Copyright 2016 + * Texas Instruments, <www.ti.com> + * + * Andreas Dannenberg <dannenberg@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _OMAP_SEC_COMMON_H_ +#define _OMAP_SEC_COMMON_H_ + +#include <common.h> + +/* + * Invoke secure ROM API on high-security (HS) device variants. It formats + * the variable argument list into the format expected by the ROM code before + * triggering the actual low-level smc entry. + */ +u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...); + +/* + * Invoke a secure ROM API on high-secure (HS) device variants that can be used + * to verify a secure blob by authenticating and optionally decrypting it. The + * exact operation performed depends on how the certificate that was embedded + * into the blob during the signing/encryption step when the secure blob was + * first created. + */ +int secure_boot_verify_image(void **p_image, size_t *p_size); + +#endif /* _OMAP_SEC_COMMON_H_ */ diff --git a/arch/arm/include/asm/spin_table.h b/arch/arm/include/asm/spin_table.h new file mode 100644 index 00000000000..8b57539f8d0 --- /dev/null +++ b/arch/arm/include/asm/spin_table.h @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_SPIN_TABLE_H__ +#define __ASM_SPIN_TABLE_H__ + +extern u64 spin_table_cpu_release_addr; +extern char spin_table_reserve_begin; +extern char spin_table_reserve_end; + +int spin_table_update_dt(void *fdt); + +#endif /* __ASM_SPIN_TABLE_H__ */ diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h index d108915ff5c..9af7353f086 100644 --- a/arch/arm/include/asm/types.h +++ b/arch/arm/include/asm/types.h @@ -71,5 +71,4 @@ typedef u32 dma_addr_t; #endif /* __KERNEL__ */ -typedef unsigned long resource_size_t; #endif diff --git a/arch/arm/lib/bootm-fdt.c b/arch/arm/lib/bootm-fdt.c index 76b75d8e464..2c0b56a8f36 100644 --- a/arch/arm/lib/bootm-fdt.c +++ b/arch/arm/lib/bootm-fdt.c @@ -21,6 +21,7 @@ #include <asm/armv7.h> #endif #include <asm/psci.h> +#include <asm/spin_table.h> DECLARE_GLOBAL_DATA_PTR; @@ -45,6 +46,12 @@ int arch_fixup_fdt(void *blob) if (ret) return ret; +#ifdef CONFIG_ARMV8_SPIN_TABLE + ret = spin_table_update_dt(blob); + if (ret) + return ret; +#endif + #ifdef CONFIG_ARMV7_NONSEC ret = psci_update_dt(blob); if (ret) diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c index 3bd87105c58..d330b09434a 100644 --- a/arch/arm/lib/cache.c +++ b/arch/arm/lib/cache.c @@ -10,6 +10,10 @@ #include <common.h> #include <malloc.h> +#ifndef CONFIG_SYS_CACHELINE_SIZE +#define CONFIG_SYS_CACHELINE_SIZE 32 +#endif + /* * Flush range from all levels of d-cache/unified-cache. * Affects the range [start, start + size - 1]. @@ -46,6 +50,24 @@ __weak void flush_dcache_range(unsigned long start, unsigned long stop) /* An empty stub, real implementation should be in platform code */ } +int check_cache_range(unsigned long start, unsigned long stop) +{ + int ok = 1; + + if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (!ok) { + warn_non_spl("CACHE: Misaligned operation at range [%08lx, %08lx]\n", + start, stop); + } + + return ok; +} + #ifdef CONFIG_SYS_NONCACHED_MEMORY /* * Reserve one MMU section worth of address space below the malloc() area that diff --git a/arch/arm/mach-exynos/include/mach/dwmmc.h b/arch/arm/mach-exynos/include/mach/dwmmc.h index bd997ad47e3..ab8361f4a8b 100644 --- a/arch/arm/mach-exynos/include/mach/dwmmc.h +++ b/arch/arm/mach-exynos/include/mach/dwmmc.h @@ -28,4 +28,3 @@ #define DWMCI_DIVRATIO_MASK 0x7 int exynos_dwmmc_init(const void *blob); -int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel); diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c index 15f1266a7bf..123f58b27f2 100644 --- a/arch/arm/mach-rockchip/rk3288-board-spl.c +++ b/arch/arm/mach-rockchip/rk3288-board-spl.c @@ -29,6 +29,7 @@ DECLARE_GLOBAL_DATA_PTR; u32 spl_boot_device(void) { +#if !CONFIG_IS_ENABLED(OF_PLATDATA) const void *blob = gd->fdt_blob; struct udevice *dev; const char *bootdev; @@ -63,6 +64,7 @@ u32 spl_boot_device(void) } fallback: +#endif return BOOT_DEVICE_MMC1; } @@ -114,7 +116,6 @@ static void configure_l2ctlr(void) #ifdef CONFIG_SPL_MMC_SUPPORT static int configure_emmc(struct udevice *pinctrl) { -#if !defined(CONFIG_TARGET_ROCK2) && !defined(CONFIG_TARGET_FIREFLY_RK3288) struct gpio_desc desc; int ret; @@ -144,7 +145,6 @@ static int configure_emmc(struct udevice *pinctrl) debug("gpio value ret=%d\n", ret); return ret; } -#endif return 0; } @@ -247,15 +247,18 @@ void spl_board_init(void) goto err; } #ifdef CONFIG_SPL_MMC_SUPPORT - ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD); - if (ret) { - debug("%s: Failed to set up SD card\n", __func__); - goto err; - } - ret = configure_emmc(pinctrl); - if (ret) { - debug("%s: Failed to set up eMMC\n", __func__); - goto err; + if (!IS_ENABLED(CONFIG_TARGET_ROCK2) && + !IS_ENABLED(CONFIG_TARGET_FIREFLY_RK3288)) { + ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD); + if (ret) { + debug("%s: Failed to set up SD card\n", __func__); + goto err; + } + ret = configure_emmc(pinctrl); + if (ret) { + debug("%s: Failed to set up eMMC\n", __func__); + goto err; + } } #endif diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c index 55ac73e9d25..b36b6afcd97 100644 --- a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c +++ b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c @@ -10,6 +10,7 @@ #include <common.h> #include <clk.h> #include <dm.h> +#include <dt-structs.h> #include <errno.h> #include <ram.h> #include <regmap.h> @@ -41,6 +42,19 @@ struct dram_info { struct rk3288_grf *grf; struct rk3288_sgrf *sgrf; struct rk3288_pmu *pmu; + bool is_veyron; +}; + +struct rk3288_sdram_params { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_rockchip_rk3288_dmc of_plat; +#endif + struct rk3288_sdram_channel ch[2]; + struct rk3288_sdram_pctl_timing pctl_timing; + struct rk3288_sdram_phy_timing phy_timing; + struct rk3288_base_params base; + int num_channels; + struct regmap *map; }; #ifdef CONFIG_SPL_BUILD @@ -703,7 +717,7 @@ static int sdram_init(struct dram_info *dram, return 0; } -#endif +#endif /* CONFIG_SPL_BUILD */ size_t sdram_size_mb(struct rk3288_pmu *pmu) { @@ -779,18 +793,36 @@ static int veyron_init(struct dram_info *priv) static int setup_sdram(struct udevice *dev) { struct dram_info *priv = dev_get_priv(dev); - struct rk3288_sdram_params params; + struct rk3288_sdram_params *params = dev_get_platdata(dev); + +# ifdef CONFIG_ROCKCHIP_FAST_SPL + if (priv->is_veyron) { + int ret; + + ret = veyron_init(priv); + if (ret) + return ret; + } +# endif + + return sdram_init(priv, params); +} + +static int rk3288_dmc_ofdata_to_platdata(struct udevice *dev) +{ +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + struct rk3288_sdram_params *params = dev_get_platdata(dev); const void *blob = gd->fdt_blob; int node = dev->of_offset; int i, ret; - params.num_channels = fdtdec_get_int(blob, node, - "rockchip,num-channels", 1); - for (i = 0; i < params.num_channels; i++) { + params->num_channels = fdtdec_get_int(blob, node, + "rockchip,num-channels", 1); + for (i = 0; i < params->num_channels; i++) { ret = fdtdec_get_byte_array(blob, node, "rockchip,sdram-channel", - (u8 *)¶ms.ch[i], - sizeof(params.ch[i])); + (u8 *)¶ms->ch[i], + sizeof(params->ch[i])); if (ret) { debug("%s: Cannot read rockchip,sdram-channel\n", __func__); @@ -798,46 +830,82 @@ static int setup_sdram(struct udevice *dev) } } ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing", - (u32 *)¶ms.pctl_timing, - sizeof(params.pctl_timing) / sizeof(u32)); + (u32 *)¶ms->pctl_timing, + sizeof(params->pctl_timing) / sizeof(u32)); if (ret) { debug("%s: Cannot read rockchip,pctl-timing\n", __func__); return -EINVAL; } ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing", - (u32 *)¶ms.phy_timing, - sizeof(params.phy_timing) / sizeof(u32)); + (u32 *)¶ms->phy_timing, + sizeof(params->phy_timing) / sizeof(u32)); if (ret) { debug("%s: Cannot read rockchip,phy-timing\n", __func__); return -EINVAL; } ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params", - (u32 *)¶ms.base, - sizeof(params.base) / sizeof(u32)); + (u32 *)¶ms->base, + sizeof(params->base) / sizeof(u32)); if (ret) { debug("%s: Cannot read rockchip,sdram-params\n", __func__); return -EINVAL; } +#ifdef CONFIG_ROCKCHIP_FAST_SPL + struct dram_info *priv = dev_get_priv(dev); -# ifdef CONFIG_ROCKCHIP_FAST_SPL - if (!fdt_node_check_compatible(blob, 0, "google,veyron")) { - ret = veyron_init(priv); - if (ret) - return ret; + priv->is_veyron = !fdt_node_check_compatible(blob, 0, "google,veyron"); +#endif + ret = regmap_init_mem(dev, ¶ms->map); + if (ret) + return ret; +#endif + + return 0; +} +#endif /* CONFIG_SPL_BUILD */ + +#if CONFIG_IS_ENABLED(OF_PLATDATA) +static int conv_of_platdata(struct udevice *dev) +{ + struct rk3288_sdram_params *plat = dev_get_platdata(dev); + struct dtd_rockchip_rk3288_dmc *of_plat = &plat->of_plat; + int i, ret; + + for (i = 0; i < 2; i++) { + memcpy(&plat->ch[i], of_plat->rockchip_sdram_channel, + sizeof(plat->ch[i])); } -# endif + memcpy(&plat->pctl_timing, of_plat->rockchip_pctl_timing, + sizeof(plat->pctl_timing)); + memcpy(&plat->phy_timing, of_plat->rockchip_phy_timing, + sizeof(plat->phy_timing)); + memcpy(&plat->base, of_plat->rockchip_sdram_params, sizeof(plat->base)); + plat->num_channels = of_plat->rockchip_num_channels; + ret = regmap_init_mem_platdata(dev, of_plat->reg, + ARRAY_SIZE(of_plat->reg) / 2, + &plat->map); + if (ret) + return ret; - return sdram_init(priv, ¶ms); + return 0; } #endif static int rk3288_dmc_probe(struct udevice *dev) { +#ifdef CONFIG_SPL_BUILD + struct rk3288_sdram_params *plat = dev_get_platdata(dev); +#endif struct dram_info *priv = dev_get_priv(dev); struct regmap *map; int ret; struct udevice *dev_clk; +#if CONFIG_IS_ENABLED(OF_PLATDATA) + ret = conv_of_platdata(dev); + if (ret) + return ret; +#endif map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC); if (IS_ERR(map)) return PTR_ERR(map); @@ -849,14 +917,12 @@ static int rk3288_dmc_probe(struct udevice *dev) priv->sgrf = syscon_get_first_range(ROCKCHIP_SYSCON_SGRF); priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); - ret = regmap_init_mem(dev, &map); - if (ret) - return ret; - priv->chan[0].pctl = regmap_get_range(map, 0); - priv->chan[0].publ = regmap_get_range(map, 1); - priv->chan[1].pctl = regmap_get_range(map, 2); - priv->chan[1].publ = regmap_get_range(map, 3); - +#ifdef CONFIG_SPL_BUILD + priv->chan[0].pctl = regmap_get_range(plat->map, 0); + priv->chan[0].publ = regmap_get_range(plat->map, 1); + priv->chan[1].pctl = regmap_get_range(plat->map, 2); + priv->chan[1].publ = regmap_get_range(plat->map, 3); +#endif ret = uclass_get_device(UCLASS_CLK, 0, &dev_clk); if (ret) return ret; @@ -898,10 +964,16 @@ static const struct udevice_id rk3288_dmc_ids[] = { }; U_BOOT_DRIVER(dmc_rk3288) = { - .name = "rk3288_dmc", + .name = "rockchip_rk3288_dmc", .id = UCLASS_RAM, .of_match = rk3288_dmc_ids, .ops = &rk3288_dmc_ops, +#ifdef CONFIG_SPL_BUILD + .ofdata_to_platdata = rk3288_dmc_ofdata_to_platdata, +#endif .probe = rk3288_dmc_probe, .priv_auto_alloc_size = sizeof(struct dram_info), +#ifdef CONFIG_SPL_BUILD + .platdata_auto_alloc_size = sizeof(struct rk3288_sdram_params), +#endif }; diff --git a/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c b/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c index c9f7c4e32f4..be4b2b00c30 100644 --- a/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c +++ b/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c @@ -23,3 +23,41 @@ U_BOOT_DRIVER(syscon_rk3288) = { .id = UCLASS_SYSCON, .of_match = rk3288_syscon_ids, }; + +#if CONFIG_IS_ENABLED(OF_PLATDATA) +static int rk3288_syscon_bind_of_platdata(struct udevice *dev) +{ + dev->driver_data = dev->driver->of_match->data; + debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data); + + return 0; +} + +U_BOOT_DRIVER(rockchip_rk3288_noc) = { + .name = "rockchip_rk3288_noc", + .id = UCLASS_SYSCON, + .of_match = rk3288_syscon_ids, + .bind = rk3288_syscon_bind_of_platdata, +}; + +U_BOOT_DRIVER(rockchip_rk3288_grf) = { + .name = "rockchip_rk3288_grf", + .id = UCLASS_SYSCON, + .of_match = rk3288_syscon_ids + 1, + .bind = rk3288_syscon_bind_of_platdata, +}; + +U_BOOT_DRIVER(rockchip_rk3288_sgrf) = { + .name = "rockchip_rk3288_sgrf", + .id = UCLASS_SYSCON, + .of_match = rk3288_syscon_ids + 2, + .bind = rk3288_syscon_bind_of_platdata, +}; + +U_BOOT_DRIVER(rockchip_rk3288_pmu) = { + .name = "rockchip_rk3288_pmu", + .id = UCLASS_SYSCON, + .of_match = rk3288_syscon_ids + 3, + .bind = rk3288_syscon_bind_of_platdata, +}; +#endif diff --git a/arch/arm/mach-stm32/stm32f7/Makefile b/arch/arm/mach-stm32/stm32f7/Makefile index 40f1ad35b7e..643d4d919c2 100644 --- a/arch/arm/mach-stm32/stm32f7/Makefile +++ b/arch/arm/mach-stm32/stm32f7/Makefile @@ -5,4 +5,4 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += timer.o clock.o +obj-y += timer.o clock.o soc.o diff --git a/arch/arm/mach-stm32/stm32f7/clock.c b/arch/arm/mach-stm32/stm32f7/clock.c index 17a715bac92..ac478505516 100644 --- a/arch/arm/mach-stm32/stm32f7/clock.c +++ b/arch/arm/mach-stm32/stm32f7/clock.c @@ -11,12 +11,243 @@ #include <asm/arch/stm32.h> #include <asm/arch/stm32_periph.h> +#define RCC_CR_HSION (1 << 0) +#define RCC_CR_HSEON (1 << 16) +#define RCC_CR_HSERDY (1 << 17) +#define RCC_CR_HSEBYP (1 << 18) +#define RCC_CR_CSSON (1 << 19) +#define RCC_CR_PLLON (1 << 24) +#define RCC_CR_PLLRDY (1 << 25) + +#define RCC_PLLCFGR_PLLM_MASK 0x3F +#define RCC_PLLCFGR_PLLN_MASK 0x7FC0 +#define RCC_PLLCFGR_PLLP_MASK 0x30000 +#define RCC_PLLCFGR_PLLQ_MASK 0xF000000 +#define RCC_PLLCFGR_PLLSRC (1 << 22) +#define RCC_PLLCFGR_PLLM_SHIFT 0 +#define RCC_PLLCFGR_PLLN_SHIFT 6 +#define RCC_PLLCFGR_PLLP_SHIFT 16 +#define RCC_PLLCFGR_PLLQ_SHIFT 24 + +#define RCC_CFGR_AHB_PSC_MASK 0xF0 +#define RCC_CFGR_APB1_PSC_MASK 0x1C00 +#define RCC_CFGR_APB2_PSC_MASK 0xE000 +#define RCC_CFGR_SW0 (1 << 0) +#define RCC_CFGR_SW1 (1 << 1) +#define RCC_CFGR_SW_MASK 0x3 +#define RCC_CFGR_SW_HSI 0 +#define RCC_CFGR_SW_HSE RCC_CFGR_SW0 +#define RCC_CFGR_SW_PLL RCC_CFGR_SW1 +#define RCC_CFGR_SWS0 (1 << 2) +#define RCC_CFGR_SWS1 (1 << 3) +#define RCC_CFGR_SWS_MASK 0xC +#define RCC_CFGR_SWS_HSI 0 +#define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0 +#define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1 +#define RCC_CFGR_HPRE_SHIFT 4 +#define RCC_CFGR_PPRE1_SHIFT 10 +#define RCC_CFGR_PPRE2_SHIFT 13 + +#define RCC_APB1ENR_PWREN (1 << 28) + +/* + * RCC USART specific definitions + */ +#define RCC_ENR_USART1EN (1 << 4) +#define RCC_ENR_USART2EN (1 << 17) +#define RCC_ENR_USART3EN (1 << 18) +#define RCC_ENR_USART6EN (1 << 5) + +/* + * Offsets of some PWR registers + */ +#define PWR_CR1_ODEN (1 << 16) +#define PWR_CR1_ODSWEN (1 << 17) +#define PWR_CSR1_ODRDY (1 << 16) +#define PWR_CSR1_ODSWRDY (1 << 17) + + +/* + * RCC GPIO specific definitions + */ +#define RCC_ENR_GPIO_A_EN (1 << 0) +#define RCC_ENR_GPIO_B_EN (1 << 1) +#define RCC_ENR_GPIO_C_EN (1 << 2) +#define RCC_ENR_GPIO_D_EN (1 << 3) +#define RCC_ENR_GPIO_E_EN (1 << 4) +#define RCC_ENR_GPIO_F_EN (1 << 5) +#define RCC_ENR_GPIO_G_EN (1 << 6) +#define RCC_ENR_GPIO_H_EN (1 << 7) +#define RCC_ENR_GPIO_I_EN (1 << 8) +#define RCC_ENR_GPIO_J_EN (1 << 9) +#define RCC_ENR_GPIO_K_EN (1 << 10) + +struct pll_psc { + u8 pll_m; + u16 pll_n; + u8 pll_p; + u8 pll_q; + u8 ahb_psc; + u8 apb1_psc; + u8 apb2_psc; +}; + +#define AHB_PSC_1 0 +#define AHB_PSC_2 0x8 +#define AHB_PSC_4 0x9 +#define AHB_PSC_8 0xA +#define AHB_PSC_16 0xB +#define AHB_PSC_64 0xC +#define AHB_PSC_128 0xD +#define AHB_PSC_256 0xE +#define AHB_PSC_512 0xF + +#define APB_PSC_1 0 +#define APB_PSC_2 0x4 +#define APB_PSC_4 0x5 +#define APB_PSC_8 0x6 +#define APB_PSC_16 0x7 + +#if !defined(CONFIG_STM32_HSE_HZ) +#error "CONFIG_STM32_HSE_HZ not defined!" +#else +#if (CONFIG_STM32_HSE_HZ == 25000000) +#if (CONFIG_SYS_CLK_FREQ == 200000000) +/* 200 MHz */ +struct pll_psc sys_pll_psc = { + .pll_m = 25, + .pll_n = 400, + .pll_p = 2, + .pll_q = 8, + .ahb_psc = AHB_PSC_1, + .apb1_psc = APB_PSC_4, + .apb2_psc = APB_PSC_2 +}; +#endif +#else +#error "No PLL/Prescaler configuration for given CONFIG_STM32_HSE_HZ exists" +#endif +#endif + +int configure_clocks(void) +{ + /* Reset RCC configuration */ + setbits_le32(&STM32_RCC->cr, RCC_CR_HSION); + writel(0, &STM32_RCC->cfgr); /* Reset CFGR */ + clrbits_le32(&STM32_RCC->cr, (RCC_CR_HSEON | RCC_CR_CSSON + | RCC_CR_PLLON)); + writel(0x24003010, &STM32_RCC->pllcfgr); /* Reset value from RM */ + clrbits_le32(&STM32_RCC->cr, RCC_CR_HSEBYP); + writel(0, &STM32_RCC->cir); /* Disable all interrupts */ + + /* Configure for HSE+PLL operation */ + setbits_le32(&STM32_RCC->cr, RCC_CR_HSEON); + while (!(readl(&STM32_RCC->cr) & RCC_CR_HSERDY)) + ; + + setbits_le32(&STM32_RCC->cfgr, (( + sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT) + | (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT) + | (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT))); + + /* Configure the main PLL */ + uint32_t pllcfgr = 0; + pllcfgr = RCC_PLLCFGR_PLLSRC; /* pll source HSE */ + pllcfgr |= sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT; + pllcfgr |= sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT; + pllcfgr |= ((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT; + pllcfgr |= sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT; + writel(pllcfgr, &STM32_RCC->pllcfgr); + + /* Enable the main PLL */ + setbits_le32(&STM32_RCC->cr, RCC_CR_PLLON); + while (!(readl(&STM32_RCC->cr) & RCC_CR_PLLRDY)) + ; + + /* Enable high performance mode, System frequency up to 200 MHz */ + setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_PWREN); + setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODEN); + /* Infinite wait! */ + while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODRDY)) + ; + /* Enable the Over-drive switch */ + setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODSWEN); + /* Infinite wait! */ + while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODSWRDY)) + ; + + stm32_flash_latency_cfg(5); + clrbits_le32(&STM32_RCC->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1)); + setbits_le32(&STM32_RCC->cfgr, RCC_CFGR_SW_PLL); + + while ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) != + RCC_CFGR_SWS_PLL) + ; + + return 0; +} + +unsigned long clock_get(enum clock clck) +{ + u32 sysclk = 0; + u32 shift = 0; + /* Prescaler table lookups for clock computation */ + u8 ahb_psc_table[16] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9 + }; + u8 apb_psc_table[8] = { + 0, 0, 0, 0, 1, 2, 3, 4 + }; + + if ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) == + RCC_CFGR_SWS_PLL) { + u16 pllm, plln, pllp; + pllm = (readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLM_MASK); + plln = ((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLN_MASK) + >> RCC_PLLCFGR_PLLN_SHIFT); + pllp = ((((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLP_MASK) + >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1); + sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp; + } + + switch (clck) { + case CLOCK_CORE: + return sysclk; + break; + case CLOCK_AHB: + shift = ahb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_AHB_PSC_MASK) + >> RCC_CFGR_HPRE_SHIFT)]; + return sysclk >>= shift; + break; + case CLOCK_APB1: + shift = apb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB1_PSC_MASK) + >> RCC_CFGR_PPRE1_SHIFT)]; + return sysclk >>= shift; + break; + case CLOCK_APB2: + shift = apb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB2_PSC_MASK) + >> RCC_CFGR_PPRE2_SHIFT)]; + return sysclk >>= shift; + break; + default: + return 0; + break; + } +} + + void clock_setup(int peripheral) { switch (peripheral) { case USART1_CLOCK_CFG: setbits_le32(RCC_BASE + RCC_APB2ENR, RCC_ENR_USART1EN); break; + case USART6_CLOCK_CFG: + setbits_le32(RCC_BASE + RCC_APB2ENR, RCC_ENR_USART6EN); + break; case GPIO_A_CLOCK_CFG: setbits_le32(RCC_BASE + RCC_AHB1ENR, RCC_ENR_GPIO_A_EN); break; diff --git a/arch/arm/mach-stm32/stm32f7/soc.c b/arch/arm/mach-stm32/stm32f7/soc.c new file mode 100644 index 00000000000..8baee99a4f7 --- /dev/null +++ b/arch/arm/mach-stm32/stm32f7/soc.c @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/armv7m.h> +#include <asm/arch/stm32.h> + +u32 get_cpu_rev(void) +{ + return 0; +} + +int arch_cpu_init(void) +{ + configure_clocks(); + + /* + * Configure the memory protection unit (MPU) + * 0x00000000 - 0xffffffff: Strong-order, Shareable + * 0xC0000000 - 0xC0800000: Normal, Outer and inner Non-cacheable + */ + + /* Disable MPU */ + writel(0, &V7M_MPU->ctrl); + + writel( + 0x00000000 /* address */ + | 1 << 4 /* VALID */ + | 0 << 0 /* REGION */ + , &V7M_MPU->rbar + ); + + /* Strong-order, Shareable */ + /* TEX=000, S=1, C=0, B=0*/ + writel( + (V7M_MPU_RASR_XN_ENABLE + | V7M_MPU_RASR_AP_RW_RW + | 0x01 << V7M_MPU_RASR_S_SHIFT + | 0x00 << V7M_MPU_RASR_TEX_SHIFT + | V7M_MPU_RASR_SIZE_4GB + | V7M_MPU_RASR_EN) + , &V7M_MPU->rasr + ); + + writel( + 0xC0000000 /* address */ + | 1 << 4 /* VALID */ + | 1 << 0 /* REGION */ + , &V7M_MPU->rbar + ); + + /* Normal, Outer and inner Non-cacheable */ + /* TEX=001, S=0, C=0, B=0*/ + writel( + (V7M_MPU_RASR_XN_ENABLE + | V7M_MPU_RASR_AP_RW_RW + | 0x01 << V7M_MPU_RASR_TEX_SHIFT + | V7M_MPU_RASR_SIZE_8MB + | V7M_MPU_RASR_EN) + , &V7M_MPU->rasr + ); + + /* Enable MPU */ + writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl); + + return 0; +} + +void s_init(void) +{ +} diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h index 04708e93594..b2c4d0ef8cf 100644 --- a/arch/nds32/include/asm/io.h +++ b/arch/nds32/include/asm/io.h @@ -344,40 +344,6 @@ static inline void writesl(unsigned int *addr, const void * data, int longlen) #define insl_p(port, to, len) insl(port, to, len) /* - * ioremap and friends. - * - * ioremap takes a PCI memory address, as specified in - * linux/Documentation/IO-mapping.txt. If you want a - * physical address, use __ioremap instead. - */ -extern void *__ioremap(unsigned long offset, size_t size, unsigned long flags); -extern void __iounmap(void *addr); - -/* - * Generic ioremap support. - * - * Define: - * iomem_valid_addr(off,size) - * iomem_to_phys(off) - */ -#ifdef iomem_valid_addr -#define __arch_ioremap(off, sz, nocache) \ -({ \ - unsigned long _off = (off), _size = (sz); \ - void *_ret = (void *)0; \ - if (iomem_valid_addr(_off, _size)) \ - _ret = __ioremap(iomem_to_phys(_off), _size, 0); \ - _ret; \ -}) - -#define __arch_iounmap __iounmap -#endif - -#define ioremap(off, sz) __arch_ioremap((off), (sz), 0) -#define ioremap_nocache(off, sz) __arch_ioremap((off), (sz), 1) -#define iounmap(_addr) __arch_iounmap(_addr) - -/* * DMA-consistent mapping functions. These allocate/free a region of * uncached, unwrite-buffered mapped memory space for use with DMA * devices. This is the "generic" version. The PCI specific version diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig index a8a90cb7a4d..d4c1ee0662c 100644 --- a/arch/sandbox/Kconfig +++ b/arch/sandbox/Kconfig @@ -10,8 +10,13 @@ config SYS_BOARD config SYS_CPU default "sandbox" +config SANDBOX_SPL + bool "Enable SPL for sandbox" + select SUPPORT_SPL + config SYS_CONFIG_NAME - default "sandbox" + default "sandbox_spl" if SANDBOX_SPL + default "sandbox" if !SANDBOX_SPL config PCI bool "PCI support" diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk index 16fd6d508a9..6d62abb0352 100644 --- a/arch/sandbox/config.mk +++ b/arch/sandbox/config.mk @@ -20,4 +20,9 @@ cmd_u-boot__ = $(CC) -o $@ -Wl,-T u-boot.lds \ -Wl,--start-group $(u-boot-main) -Wl,--end-group \ $(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map +cmd_u-boot-spl = (cd $(obj) && $(CC) -o $(SPL_BIN) -Wl,-T u-boot-spl.lds \ + -Wl,--start-group $(patsubst $(obj)/%,%,$(u-boot-spl-main)) \ + $(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) -Wl,--end-group \ + $(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot-spl.map -Wl,--gc-sections) + CONFIG_ARCH_DEVICE_TREE := sandbox diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile index 1b42fee1412..db4363358a8 100644 --- a/arch/sandbox/cpu/Makefile +++ b/arch/sandbox/cpu/Makefile @@ -8,6 +8,7 @@ # obj-y := cpu.o os.o start.o state.o +obj-$(CONFIG_SPL_BUILD) += spl.o obj-$(CONFIG_ETH_SANDBOX_RAW) += eth-raw-os.o obj-$(CONFIG_SANDBOX_SDL) += sdl.o diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 196f3e1191e..2def72212d1 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -4,10 +4,12 @@ */ #define DEBUG #include <common.h> -#include <dm/root.h> +#include <errno.h> +#include <libfdt.h> #include <os.h> #include <asm/io.h> #include <asm/state.h> +#include <dm/root.h> DECLARE_GLOBAL_DATA_PTR; @@ -55,7 +57,7 @@ int cleanup_before_linux_select(int flags) void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) { -#ifdef CONFIG_PCI +#if defined(CONFIG_PCI) && !defined(CONFIG_SPL_BUILD) unsigned long plen = len; void *ptr; diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 8a4d719835c..2d63dd88f12 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -541,6 +541,57 @@ int os_jump_to_image(const void *dest, int size) return unlink(fname); } +int os_find_u_boot(char *fname, int maxlen) +{ + struct sandbox_state *state = state_get_current(); + const char *progname = state->argv[0]; + int len = strlen(progname); + char *p; + int fd; + + if (len >= maxlen || len < 4) + return -ENOSPC; + + /* Look for 'u-boot' in the same directory as 'u-boot-spl' */ + strcpy(fname, progname); + if (!strcmp(fname + len - 4, "-spl")) { + fname[len - 4] = '\0'; + fd = os_open(fname, O_RDONLY); + if (fd >= 0) { + close(fd); + return 0; + } + } + + /* Look for 'u-boot' in the parent directory of spl/ */ + p = strstr(fname, "/spl/"); + if (p) { + strcpy(p, p + 4); + fd = os_open(fname, O_RDONLY); + if (fd >= 0) { + close(fd); + return 0; + } + } + + return -ENOENT; +} + +int os_spl_to_uboot(const char *fname) +{ + struct sandbox_state *state = state_get_current(); + char *argv[state->argc + 1]; + int ret; + + memcpy(argv, state->argv, sizeof(char *) * (state->argc + 1)); + argv[0] = (char *)fname; + ret = execv(fname, argv); + if (ret) + return ret; + + return unlink(fname); +} + void os_localtime(struct rtc_time *rt) { time_t t = time(NULL); diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c new file mode 100644 index 00000000000..e8349c0b932 --- /dev/null +++ b/arch/sandbox/cpu/spl.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 Google, Inc + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <os.h> +#include <spl.h> +#include <asm/spl.h> +#include <asm/state.h> + +DECLARE_GLOBAL_DATA_PTR; + +void board_init_f(ulong flag) +{ + struct sandbox_state *state = state_get_current(); + + gd->arch.ram_buf = state->ram_buf; + gd->ram_size = state->ram_size; +} + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_BOARD; +} + +void spl_board_announce_boot_device(void) +{ + char fname[256]; + int ret; + + ret = os_find_u_boot(fname, sizeof(fname)); + if (ret) { + printf("(%s not found, error %d)\n", fname, ret); + return; + } + printf("%s\n", fname); +} + +int spl_board_load_image(void) +{ + char fname[256]; + int ret; + + ret = os_find_u_boot(fname, sizeof(fname)); + if (ret) + return ret; + + /* Hopefully this will not return */ + return os_spl_to_uboot(fname); +} + +void spl_board_init(void) +{ + struct udevice *dev; + + preloader_console_init(); + + /* + * Scan all the devices so that we can output their platform data. See + * sandbox_spl_probe(). + */ + for (uclass_first_device(UCLASS_MISC, &dev); + dev; + uclass_next_device(&dev)) + ; +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 969618ef875..6e4ec017ccd 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -73,6 +73,7 @@ static int sandbox_cmdline_cb_help(struct sandbox_state *state, const char *arg) } SANDBOX_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help"); +#ifndef CONFIG_SPL_BUILD int sandbox_main_loop_init(void) { struct sandbox_state *state = state_get_current(); @@ -97,6 +98,7 @@ int sandbox_main_loop_init(void) return 0; } +#endif static int sandbox_cmdline_cb_boot(struct sandbox_state *state, const char *arg) diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds new file mode 100644 index 00000000000..7e92b4ac66c --- /dev/null +++ b/arch/sandbox/cpu/u-boot-spl.lds @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2011-2012 The Chromium OS Authors. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +SECTIONS +{ + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + __u_boot_sandbox_option_start = .; + _u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) } + __u_boot_sandbox_option_end = .; + + __bss_start = .; +} + +INSERT BEFORE .data; diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts index 2ae40148b09..e6d336f16ab 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -172,6 +172,37 @@ }; }; + spl-test { + u-boot,dm-pre-reloc; + compatible = "sandbox,spl-test"; + boolval; + intval = <1>; + intarray = <2 3 4>; + byteval = [05]; + bytearray = [06]; + longbytearray = [09 0a 0b 0c 0d 0e 0f 10 11]; + stringval = "message"; + stringarray = "multi-word", "message"; + }; + + spl-test2 { + u-boot,dm-pre-reloc; + compatible = "sandbox,spl-test"; + intval = <3>; + intarray = <5>; + byteval = [08]; + bytearray = [01 23 34]; + longbytearray = [09 0a 0b 0c]; + stringval = "message2"; + stringarray = "another", "multi-word", "message"; + }; + + spl-test3 { + u-boot,dm-pre-reloc; + compatible = "sandbox,spl-test"; + stringarray = "one"; + }; + square { compatible = "demo-shape"; colour = "blue"; diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h new file mode 100644 index 00000000000..59f24011703 --- /dev/null +++ b/arch/sandbox/include/asm/spl.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 Google, Inc + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __asm_spl_h +#define __asm_spl_h + +#define CONFIG_SPL_BOARD_LOAD_IMAGE + +/** + * Board-specific load method for boards that have a special way of loading + * U-Boot, which does not fit with the existing SPL code. + * + * @return 0 on success, negative errno value on failure. + */ +int spl_board_load_image(void); + +enum { + BOOT_DEVICE_BOARD, +}; + +#endif diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile index 96761e27f7a..7820c55c855 100644 --- a/arch/sandbox/lib/Makefile +++ b/arch/sandbox/lib/Makefile @@ -8,5 +8,7 @@ # obj-y += interrupts.o +ifndef CONFIG_SPL_BUILD obj-$(CONFIG_PCI) += pci_io.o +endif obj-$(CONFIG_CMD_BOOTM) += bootm.o diff --git a/arch/sandbox/lib/bootm.c b/arch/sandbox/lib/bootm.c index d49c927b346..0c9a7979d23 100644 --- a/arch/sandbox/lib/bootm.c +++ b/arch/sandbox/lib/bootm.c @@ -56,7 +56,7 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) bootstage_mark(BOOTSTAGE_ID_RUN_OS); printf("## Transferring control to Linux (at address %08lx)...\n", images->ep); - reset_cpu(0); + printf("sandbox: continuing, as we cannot run Linux\n"); } return 0; diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 0a00db36179..5dc27bebd50 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -128,39 +128,6 @@ extern void __raw_readsl(unsigned int addr, void *data, int longlen); #define in_8(port) inb(port) #define in_le16(port) inw(port) #define in_le32(port) inl(port) -/* - * ioremap and friends. - * - * ioremap takes a PCI memory address, as specified in - * linux/Documentation/IO-mapping.txt. If you want a - * physical address, use __ioremap instead. - */ -extern void *__ioremap(unsigned long offset, size_t size, unsigned long flags); -extern void __iounmap(void *addr); - -/* - * Generic ioremap support. - * - * Define: - * iomem_valid_addr(off,size) - * iomem_to_phys(off) - */ -#ifdef iomem_valid_addr -#define __arch_ioremap(off, sz, nocache) \ -({ \ - unsigned long _off = (off), _size = (sz); \ - void *_ret = (void *)0; \ - if (iomem_valid_addr(_off, _size)) \ - _ret = __ioremap(iomem_to_phys(_off), _size, 0); \ - _ret; \ -}) - -#define __arch_iounmap __iounmap -#endif - -#define ioremap(off, sz) __arch_ioremap((off), (sz), 0) -#define ioremap_nocache(off, sz) __arch_ioremap((off), (sz), 1) -#define iounmap(_addr) __arch_iounmap(_addr) /* * DMA-consistent mapping functions. These allocate/free a region of |