diff options
Diffstat (limited to 'arch')
100 files changed, 1812 insertions, 560 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/config.mk b/arch/arm/config.mk index 9a5a9747c48..8f8586295ef 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -120,8 +120,8 @@ endif ifdef CONFIG_ARM64 OBJCOPYFLAGS += -j .text -j .rodata -j .data -j .u_boot_list -j .rela.dyn else -OBJCOPYFLAGS += -j .text -j .secure_text -j .rodata -j .hash -j .data -j \ - .got -j .got.plt -j .u_boot_list -j .rel.dyn +OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \ + -j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn endif ifdef CONFIG_OF_EMBED 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/Kconfig b/arch/arm/cpu/armv7/Kconfig index afeaac84dec..bd6108eec06 100644 --- a/arch/arm/cpu/armv7/Kconfig +++ b/arch/arm/cpu/armv7/Kconfig @@ -21,7 +21,7 @@ config ARMV7_BOOT_SEC_DEFAULT Say Y here to boot in secure mode by default even if non-secure mode is supported. This option is useful to boot kernels which do not suppport booting in non-secure mode. Only set this if you need it. - This can be overriden at run-time by setting the bootm_boot_mode env. + This can be overridden at run-time by setting the bootm_boot_mode env. variable to "sec" or "nonsec". config ARMV7_VIRT diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile index ddd8d12d517..0d4bfbc55b3 100644 --- a/arch/arm/cpu/armv7/Makefile +++ b/arch/arm/cpu/armv7/Makefile @@ -19,7 +19,7 @@ endif endif obj-$(CONFIG_ARMV7_NONSEC) += nonsec_virt.o virt-v7.o virt-dt.o -obj-$(CONFIG_ARMV7_PSCI) += psci.o +obj-$(CONFIG_ARMV7_PSCI) += psci.o psci-common.o obj-$(CONFIG_IPROC) += iproc-common/ obj-$(CONFIG_KONA) += kona-common/ 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/ls102xa/psci.S b/arch/arm/cpu/armv7/ls102xa/psci.S index cf5cd48bcbe..f9b26b43218 100644 --- a/arch/arm/cpu/armv7/ls102xa/psci.S +++ b/arch/arm/cpu/armv7/ls102xa/psci.S @@ -29,16 +29,16 @@ @ r2 = target PC .globl psci_cpu_on psci_cpu_on: - push {lr} + push {r4, r5, r6, lr} @ Clear and Get the correct CPU number @ r1 = 0xf01 - and r1, r1, #0xff + and r4, r1, #0xff - mov r0, r1 - bl psci_get_cpu_stack_top - str r2, [r0] - dsb + mov r0, r4 + mov r1, r2 + bl psci_save_target_pc + mov r1, r4 @ Get DCFG base address movw r4, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff) @@ -101,7 +101,7 @@ holdoff_release: @ Return mov r0, #ARM_PSCI_RET_SUCCESS - pop {lr} + pop {r4, r5, r6, lr} bx lr .globl psci_cpu_off @@ -111,16 +111,4 @@ psci_cpu_off: 1: wfi b 1b -.globl psci_arch_init -psci_arch_init: - mov r6, lr - - bl psci_get_cpu_id - bl psci_get_cpu_stack_top - mov sp, r0 - - bx r6 - - .globl psci_text_end -psci_text_end: .popsection diff --git a/arch/arm/cpu/armv7/mx7/psci-mx7.c b/arch/arm/cpu/armv7/mx7/psci-mx7.c index 9a330476cf5..502552d1718 100644 --- a/arch/arm/cpu/armv7/mx7/psci-mx7.c +++ b/arch/arm/cpu/armv7/mx7/psci-mx7.c @@ -1,9 +1,9 @@ #include <asm/io.h> #include <asm/psci.h> +#include <asm/secure.h> #include <asm/arch/imx-regs.h> #include <common.h> -#define __secure __attribute__((section("._secure.text"))) #define GPC_CPU_PGC_SW_PDN_REQ 0xfc #define GPC_CPU_PGC_SW_PUP_REQ 0xf0 diff --git a/arch/arm/cpu/armv7/mx7/psci.S b/arch/arm/cpu/armv7/mx7/psci.S index 34c6ab33f05..96e88d6184e 100644 --- a/arch/arm/cpu/armv7/mx7/psci.S +++ b/arch/arm/cpu/armv7/mx7/psci.S @@ -9,35 +9,22 @@ .arch_extension sec - @ r1 = target CPU - @ r2 = target PC - -.globl psci_arch_init -psci_arch_init: - mov r6, lr - - bl psci_get_cpu_id - bl psci_get_cpu_stack_top - mov sp, r0 - - bx r6 - - @ r1 = target CPU - @ r2 = target PC - .globl psci_cpu_on psci_cpu_on: - push {lr} + push {r4, r5, lr} + mov r4, r0 + mov r5, r1 mov r0, r1 - bl psci_get_cpu_stack_top - str r2, [r0] - dsb + mov r1, r2 + bl psci_save_target_pc + mov r0, r4 + mov r1, r5 ldr r2, =psci_cpu_entry bl imx_cpu_on - pop {pc} + pop {r4, r5, pc} .globl psci_cpu_off psci_cpu_off: @@ -49,6 +36,4 @@ psci_cpu_off: 1: wfi b 1b - .globl psci_text_end -psci_text_end: .popsection diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S index b7563edbe6b..95ce9387b83 100644 --- a/arch/arm/cpu/armv7/nonsec_virt.S +++ b/arch/arm/cpu/armv7/nonsec_virt.S @@ -49,8 +49,13 @@ _secure_monitor: mcr p15, 0, r5, c12, c0, 1 isb - @ Obtain a secure stack, and configure the PSCI backend + @ Obtain a secure stack + bl psci_stack_setup + + @ Configure the PSCI backend + push {r0, r1, r2, ip} bl psci_arch_init + pop {r0, r1, r2, ip} #endif #ifdef CONFIG_ARM_ERRATA_773022 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/armv7/psci-common.c b/arch/arm/cpu/armv7/psci-common.c new file mode 100644 index 00000000000..d14b6937473 --- /dev/null +++ b/arch/arm/cpu/armv7/psci-common.c @@ -0,0 +1,39 @@ +/* + * Common PSCI functions + * + * Copyright (C) 2016 Chen-Yu Tsai + * Author: Chen-Yu Tsai <wens@csie.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <asm/armv7.h> +#include <asm/macro.h> +#include <asm/psci.h> +#include <asm/secure.h> +#include <linux/linkage.h> + +static u32 psci_target_pc[CONFIG_ARMV7_PSCI_NR_CPUS] __secure_data = { 0 }; + +void __secure psci_save_target_pc(int cpu, u32 pc) +{ + psci_target_pc[cpu] = pc; + DSB; +} + +u32 __secure psci_get_target_pc(int cpu) +{ + return psci_target_pc[cpu]; +} + diff --git a/arch/arm/cpu/armv7/psci.S b/arch/arm/cpu/armv7/psci.S index ab408378fca..350b75ce20e 100644 --- a/arch/arm/cpu/armv7/psci.S +++ b/arch/arm/cpu/armv7/psci.S @@ -196,29 +196,56 @@ ENTRY(psci_cpu_off_common) bx lr ENDPROC(psci_cpu_off_common) -@ expects CPU ID in r0 and returns stack top in r0 -ENTRY(psci_get_cpu_stack_top) - mov r3, #0x400 @ 1kB of stack per CPU - mul r0, r0, r3 - - ldr r3, =psci_text_end @ end of monitor text - add r3, r3, #0x2000 @ Skip two pages - lsr r3, r3, #12 @ Align to start of page - lsl r3, r3, #12 - sub r3, r3, #4 @ reserve 1 word for target PC - sub r0, r3, r0 @ here's our stack! - +@ The stacks are allocated in reverse order, i.e. +@ the stack for CPU0 has the highest memory address. +@ +@ -------------------- __secure_stack_end +@ | CPU0 target PC | +@ |------------------| +@ | | +@ | CPU0 stack | +@ | | +@ |------------------| __secure_stack_end - 1KB +@ | . | +@ | . | +@ | . | +@ | . | +@ -------------------- __secure_stack_start +@ +@ This expects CPU ID in r0 and returns stack top in r0 +LENTRY(psci_get_cpu_stack_top) + @ stack top = __secure_stack_end - (cpuid << ARM_PSCI_STACK_SHIFT) + ldr r3, =__secure_stack_end + sub r0, r3, r0, LSL #ARM_PSCI_STACK_SHIFT + sub r0, r0, #4 @ Save space for target PC bx lr ENDPROC(psci_get_cpu_stack_top) +@ {r0, r1, r2, ip} from _do_nonsec_entry(kernel_entry, 0, machid, r2) in +@ arch/arm/lib/bootm.c:boot_jump_linux() must remain unchanged across +@ this function. +ENTRY(psci_stack_setup) + mov r6, lr + mov r7, r0 + bl psci_get_cpu_id @ CPU ID => r0 + bl psci_get_cpu_stack_top @ stack top => r0 + mov sp, r0 + mov r0, r7 + bx r6 +ENDPROC(psci_stack_setup) + +ENTRY(psci_arch_init) + mov pc, lr +ENDPROC(psci_arch_init) +.weak psci_arch_init + ENTRY(psci_cpu_entry) bl psci_enable_smp bl _nonsec_init bl psci_get_cpu_id @ CPU ID => r0 - bl psci_get_cpu_stack_top @ stack top => r0 - ldr r0, [r0] @ target PC at stack top + bl psci_get_target_pc @ target PC => r0 b _do_nonsec_entry ENDPROC(psci_cpu_entry) diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index c2085101685..b35b9df4a9d 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_ARMV7_PSCI) += psci.o -obj-$(CONFIG_ARMV7_PSCI) += psci_head.o endif ifdef CONFIG_SPL_BUILD diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c index a118e9d0c4a..7ac84065f4a 100644 --- a/arch/arm/cpu/armv7/sunxi/psci.c +++ b/arch/arm/cpu/armv7/sunxi/psci.c @@ -17,11 +17,11 @@ #include <asm/gic.h> #include <asm/io.h> #include <asm/psci.h> +#include <asm/secure.h> #include <asm/system.h> #include <linux/bitops.h> -#define __secure __attribute__ ((section ("._secure.text"))) #define __irq __attribute__ ((interrupt ("IRQ"))) #define GICD_BASE (SUNXI_GIC400_BASE + GIC_DIST_OFFSET) @@ -209,9 +209,8 @@ int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc) (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE; u32 cpu = (mpidr & 0x3); - /* store target PC at target CPU stack top */ - writel(pc, psci_get_cpu_stack_top(cpu)); - DSB; + /* store target PC */ + psci_save_target_pc(cpu, pc); /* Set secondary core power on PC */ writel((u32)&psci_cpu_entry, &cpucfg->priv0); @@ -250,7 +249,7 @@ void __secure psci_cpu_off(void) wfi(); } -void __secure sunxi_gic_init(void) +void __secure psci_arch_init(void) { u32 reg; diff --git a/arch/arm/cpu/armv7/sunxi/psci_head.S b/arch/arm/cpu/armv7/sunxi/psci_head.S deleted file mode 100644 index 8fa823d1df3..00000000000 --- a/arch/arm/cpu/armv7/sunxi/psci_head.S +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2013 - ARM Ltd - * Author: Marc Zyngier <marc.zyngier@arm.com> - * - * Based on code by Carl van Schaik <carl@ok-labs.com>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <config.h> -#include <linux/linkage.h> - -#include <asm/arch-armv7/generictimer.h> -#include <asm/gic.h> -#include <asm/macro.h> -#include <asm/psci.h> -#include <asm/arch/cpu.h> - -/* - * Memory layout: - * - * SECURE_RAM to text_end : - * ._secure_text section - * text_end to ALIGN_PAGE(text_end): - * nothing - * ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000) - * 1kB of stack per CPU (4 CPUs max). - */ - - .pushsection ._secure.text, "ax" - - .arch_extension sec - -#define GICD_BASE (SUNXI_GIC400_BASE + 0x1000) -#define GICC_BASE (SUNXI_GIC400_BASE + 0x2000) - -@ {r0, r1, r2, ip} from _do_nonsec_entry(kernel_entry, 0, machid, r2) in -@ arch/arm/lib/bootm.c:boot_jump_linux() must remain unchanged across -@ this function. -ENTRY(psci_arch_init) - mov r6, lr - mov r7, r0 - bl psci_get_cpu_id @ CPU ID => r0 - bl psci_get_cpu_stack_top @ stack top => r0 - sub r0, r0, #4 @ Save space for target PC - mov sp, r0 - mov r0, r7 - mov lr, r6 - - push {r0, r1, r2, ip, lr} - bl sunxi_gic_init - pop {r0, r1, r2, ip, pc} -ENDPROC(psci_arch_init) - -ENTRY(psci_text_end) - .popsection 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 33e6db0cc52..dea14657d9a 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -16,6 +16,9 @@ obj-y += tlb.o obj-y += transition.o obj-y += fwcall.o obj-y += cpu-dt.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o +endif obj-$(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o sec_firmware_asm.o obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/ diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 index da5e052569c..7867c379d4b 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 @@ -128,7 +128,7 @@ mcinitcmd: This environment variable is defined to initiate MC and DPL deploymen during U-boot booting.However the MC, DPC and DPL can be applied from console independently. The variable needs to be set from the console once and then on - rebooting the parameters set in the varible will automatically be + rebooting the parameters set in the variable will automatically be executed. The commmand is demostrated taking an example of mc boot using NOR Flash i.e. MC, DPL, and DPC is stored in the NOR flash: 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/cpu/armv8/zynqmp/mp.c b/arch/arm/cpu/armv8/zynqmp/mp.c index 58312a79bc5..e10fc3136c8 100644 --- a/arch/arm/cpu/armv8/zynqmp/mp.c +++ b/arch/arm/cpu/armv8/zynqmp/mp.c @@ -128,7 +128,7 @@ static void enable_clock_r5(void) writel(tmp, &crlapb_base->cpu_r5_ctrl); /* Give some delay for clock - * to propogate */ + * to propagate */ udelay(0x500); } diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds index 1769b6ea881..36c9fd0bd01 100644 --- a/arch/arm/cpu/u-boot.lds +++ b/arch/arm/cpu/u-boot.lds @@ -8,6 +8,7 @@ */ #include <config.h> +#include <asm/psci.h> OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) @@ -48,34 +49,67 @@ SECTIONS #ifdef CONFIG_ARMV7_NONSEC + /* Align the secure section only if we're going to use it in situ */ + .__secure_start : +#ifndef CONFIG_ARMV7_SECURE_BASE + ALIGN(CONSTANT(COMMONPAGESIZE)) +#endif + { + KEEP(*(.__secure_start)) + } + #ifndef CONFIG_ARMV7_SECURE_BASE #define CONFIG_ARMV7_SECURE_BASE #define __ARMV7_PSCI_STACK_IN_RAM #endif - .__secure_start : { - . = ALIGN(0x1000); - *(.__secure_start) - } - .secure_text CONFIG_ARMV7_SECURE_BASE : AT(ADDR(.__secure_start) + SIZEOF(.__secure_start)) { *(._secure.text) } - . = LOADADDR(.__secure_start) + - SIZEOF(.__secure_start) + - SIZEOF(.secure_text); + .secure_data : AT(LOADADDR(.secure_text) + SIZEOF(.secure_text)) + { + *(._secure.data) + } + .secure_stack ALIGN(ADDR(.secure_data) + SIZEOF(.secure_data), + CONSTANT(COMMONPAGESIZE)) (NOLOAD) : #ifdef __ARMV7_PSCI_STACK_IN_RAM - /* Align to page boundary and skip 2 pages */ - . = (. & ~ 0xfff) + 0x2000; -#undef __ARMV7_PSCI_STACK_IN_RAM + AT(ADDR(.secure_stack)) +#else + AT(LOADADDR(.secure_data) + SIZEOF(.secure_data)) +#endif + { + KEEP(*(.__secure_stack_start)) + + /* Skip addreses for stack */ + . = . + CONFIG_ARMV7_PSCI_NR_CPUS * ARM_PSCI_STACK_SIZE; + + /* Align end of stack section to page boundary */ + . = ALIGN(CONSTANT(COMMONPAGESIZE)); + + KEEP(*(.__secure_stack_end)) + +#ifdef CONFIG_ARMV7_SECURE_MAX_SIZE + /* + * We are not checking (__secure_end - __secure_start) here, + * as these are the load addresses, and do not include the + * stack section. Instead, use the end of the stack section + * and the start of the text section. + */ + ASSERT((. - ADDR(.secure_text)) <= CONFIG_ARMV7_SECURE_MAX_SIZE, + "Error: secure section exceeds secure memory size"); +#endif + } + +#ifndef __ARMV7_PSCI_STACK_IN_RAM + /* Reset VMA but don't allocate space if we have secure SRAM */ + . = LOADADDR(.secure_stack); #endif - __secure_end_lma = .; - .__secure_end : AT(__secure_end_lma) { + .__secure_end : AT(ADDR(.__secure_end)) { *(.__secure_end) LONG(0x1d1071c); /* Must output something to reset LMA */ } diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index ef573ec6851..acecb7c3594 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -242,6 +242,7 @@ dtb-$(CONFIG_MACH_SUN8I_A83T) += \ sun8i-a83t-sinovoip-bpi-m3.dtb dtb-$(CONFIG_MACH_SUN8I_H3) += \ sun8i-h3-orangepi-2.dtb \ + sun8i-h3-orangepi-lite.dtb \ sun8i-h3-orangepi-one.dtb \ sun8i-h3-orangepi-pc.dtb \ sun8i-h3-orangepi-plus.dtb 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/dts/sun50i-a64-pine64-plus.dts b/arch/arm/dts/sun50i-a64-pine64-plus.dts index 549dc15bd5d..389c6096ca1 100644 --- a/arch/arm/dts/sun50i-a64-pine64-plus.dts +++ b/arch/arm/dts/sun50i-a64-pine64-plus.dts @@ -57,3 +57,16 @@ reg = <0x40000000 0x40000000>; }; }; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii"; + phy = <&phy1>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi index 1bd436f8470..7d0dc76a11f 100644 --- a/arch/arm/dts/sun50i-a64.dtsi +++ b/arch/arm/dts/sun50i-a64.dtsi @@ -506,6 +506,25 @@ allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; + + rmii_pins: rmii_pins { + allwinner,pins = "PD10", "PD11", "PD13", "PD14", + "PD17", "PD18", "PD19", "PD20", + "PD22", "PD23"; + allwinner,function = "emac"; + allwinner,drive = <SUN4I_PINCTRL_40_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; + + rgmii_pins: rgmii_pins { + allwinner,pins = "PD8", "PD9", "PD10", "PD11", + "PD12", "PD13", "PD15", + "PD16", "PD17", "PD18", "PD19", + "PD20", "PD21", "PD22", "PD23"; + allwinner,function = "emac"; + allwinner,drive = <SUN4I_PINCTRL_40_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; }; ahb_rst: reset@1c202c0 { @@ -620,5 +639,19 @@ #address-cells = <1>; #size-cells = <0>; }; + + emac: ethernet@01c30000 { + compatible = "allwinner,sun50i-a64-emac"; + reg = <0x01c30000 0x2000>, <0x01c00030 0x4>; + reg-names = "emac", "syscon"; + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; + resets = <&ahb_rst 17>; + reset-names = "ahb"; + clocks = <&bus_gates 17>; + clock-names = "ahb"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; }; }; diff --git a/arch/arm/dts/sun8i-h3-orangepi-2.dts b/arch/arm/dts/sun8i-h3-orangepi-2.dts index f93f5d1695c..d3f8f550a22 100644 --- a/arch/arm/dts/sun8i-h3-orangepi-2.dts +++ b/arch/arm/dts/sun8i-h3-orangepi-2.dts @@ -184,3 +184,16 @@ usb1_vbus-supply = <®_usb1_vbus>; status = "okay"; }; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii"; + phy = <&phy1>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + diff --git a/arch/arm/dts/sun8i-h3-orangepi-lite.dts b/arch/arm/dts/sun8i-h3-orangepi-lite.dts new file mode 100644 index 00000000000..ac7174914e6 --- /dev/null +++ b/arch/arm/dts/sun8i-h3-orangepi-lite.dts @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2016 Hans de Goede <hdegoede@redhat.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun8i-h3.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/pinctrl/sun4i-a10.h> + +/ { + model = "Xunlong Orange Pi Lite"; + compatible = "xunlong,orangepi-lite", "allwinner,sun8i-h3"; + + aliases { + /* The H3 emac is not used so the wifi is ethernet0 */ + ethernet1 = &rtl8189ftv; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_opc>, <&leds_r_opc>; + + pwr_led { + label = "orangepi:green:pwr"; + gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + status_led { + label = "orangepi:red:status"; + gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; + }; + }; + + r_gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&sw_r_opc>; + + sw4 { + label = "sw4"; + linux,code = <BTN_0>; + gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&ehci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; +}; + +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ + cd-inverted; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_a>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + non-removable; + status = "okay"; + + /* + * Explicitly define the sdio device, so that we can add an ethernet + * alias for it (which e.g. makes u-boot set a mac-address). + */ + rtl8189ftv: sdio_wifi@1 { + reg = <1>; + }; +}; + +&ohci1 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + +&pio { + leds_opc: led_pins@0 { + allwinner,pins = "PA15"; + allwinner,function = "gpio_out"; + allwinner,drive = <SUN4I_PINCTRL_10_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; +}; + +&r_pio { + leds_r_opc: led_pins@0 { + allwinner,pins = "PL10"; + allwinner,function = "gpio_out"; + allwinner,drive = <SUN4I_PINCTRL_10_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; + + sw_r_opc: key_pins@0 { + allwinner,pins = "PL3"; + allwinner,function = "gpio_in"; + allwinner,drive = <SUN4I_PINCTRL_10_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + /* USB VBUS is always on */ + status = "okay"; +}; diff --git a/arch/arm/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/dts/sun8i-h3-orangepi-pc.dts index 30ccca019dd..0a74a9193bb 100644 --- a/arch/arm/dts/sun8i-h3-orangepi-pc.dts +++ b/arch/arm/dts/sun8i-h3-orangepi-pc.dts @@ -173,3 +173,15 @@ /* USB VBUS is always on */ status = "okay"; }; + +&emac { + phy = <&phy1>; + phy-mode = "mii"; + allwinner,use-internal-phy; + allwinner,leds-active-low; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; diff --git a/arch/arm/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/dts/sun8i-h3-orangepi-plus.dts index 900ec4fc8c8..28f74f6ffd1 100644 --- a/arch/arm/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/dts/sun8i-h3-orangepi-plus.dts @@ -40,26 +40,13 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -/dts-v1/; -#include "sun8i-h3.dtsi" -#include "sunxi-common-regulators.dtsi" - -#include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/input/input.h> -#include <dt-bindings/pinctrl/sun4i-a10.h> +/* The Orange Pi Plus is an extended version of the Orange Pi 2 */ +#include "sun8i-h3-orangepi-2.dts" / { - model = "Xunlong Orange Pi Plus"; + model = "Xunlong Orange Pi Plus / Plus 2 / Plus 2E"; compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3"; - aliases { - serial0 = &uart0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - reg_usb3_vbus: usb3-vbus { compatible = "regulator-fixed"; pinctrl-names = "default"; @@ -71,75 +58,42 @@ enable-active-high; gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; }; +}; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&leds_opc>; - - status_led { - label = "status:red:user"; - gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; - }; - }; - - r_leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&leds_r_opc>; - - tx { - label = "pwr:green:user"; - gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - }; - - r_gpio_keys { - compatible = "gpio-keys"; - input-name = "sw4"; - - pinctrl-names = "default"; - pinctrl-0 = <&sw_r_opc>; +&ehci2 { + status = "okay"; +}; - sw4@0 { - label = "sw4"; - linux,code = <BTN_0>; - gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; - }; - }; +&ehci3 { + status = "okay"; }; -&pio { - leds_opc: led_pins@0 { - allwinner,pins = "PA15"; - allwinner,function = "gpio_out"; - allwinner,drive = <SUN4I_PINCTRL_10_MA>; - allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; - }; +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_8bit_pins>; + vmmc-supply = <®_vcc3v3>; + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; + status = "okay"; }; -&r_pio { - leds_r_opc: led_pins@0 { - allwinner,pins = "PL10"; - allwinner,function = "gpio_out"; - allwinner,drive = <SUN4I_PINCTRL_10_MA>; - allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; - }; +&mmc2_8bit_pins { + /* Increase drive strength for DDR modes */ + allwinner,drive = <SUN4I_PINCTRL_40_MA>; + /* eMMC is missing pull-ups */ + allwinner,pull = <SUN4I_PINCTRL_PULL_UP>; +}; - sw_r_opc: key_pins@0 { - allwinner,pins = "PL03"; - allwinner,function = "gpio_in"; - allwinner,drive = <SUN4I_PINCTRL_10_MA>; - allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; - }; +&ohci1 { + status = "okay"; }; -&ehci1 { +&ohci2 { status = "okay"; }; -&ehci3 { +&ohci3 { status = "okay"; }; @@ -152,33 +106,6 @@ }; }; -&mmc0 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; - vmmc-supply = <®_vcc3v3>; - bus-width = <4>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ - cd-inverted; - status = "okay"; -}; - -®_usb1_vbus { - gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>; - status = "okay"; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; -}; - -&usb1_vbus_pin_a { - allwinner,pins = "PG13"; -}; - &usbphy { - usb1_vbus-supply = <®_usb1_vbus>; usb3_vbus-supply = <®_usb3_vbus>; - status = "okay"; }; diff --git a/arch/arm/dts/sun8i-h3.dtsi b/arch/arm/dts/sun8i-h3.dtsi index c2f63c50501..72c0920466a 100644 --- a/arch/arm/dts/sun8i-h3.dtsi +++ b/arch/arm/dts/sun8i-h3.dtsi @@ -501,6 +501,17 @@ interrupt-controller; #interrupt-cells = <3>; + rgmii_pins: rgmii_pins { + allwinner,pins = "PD0", "PD1", "PD2", "PD3", + "PD4", "PD5", "PD7", + "PD8", "PD9", "PD10", + "PD12", "PD13", "PD15", + "PD16", "PD17"; + allwinner,function = "emac"; + allwinner,drive = <SUN4I_PINCTRL_40_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; + uart0_pins_a: uart0@0 { allwinner,pins = "PA4", "PA5"; allwinner,function = "uart0"; @@ -530,6 +541,16 @@ allwinner,drive = <SUN4I_PINCTRL_30_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; + + mmc2_8bit_pins: mmc2_8bit { + allwinner,pins = "PC5", "PC6", "PC8", + "PC9", "PC10", "PC11", + "PC12", "PC13", "PC14", + "PC15", "PC16"; + allwinner,function = "mmc2"; + allwinner,drive = <SUN4I_PINCTRL_30_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; }; ahb_rst: reset@01c202c0 { @@ -616,6 +637,20 @@ status = "disabled"; }; + emac: ethernet@01c30000 { + compatible = "allwinner,sun8i-h3-emac"; + reg = <0x01c30000 0x2000>, <0x01c00030 0x4>; + reg-names = "emac", "syscon"; + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; + resets = <&ahb_rst 17>, <&ahb_rst 66>; + reset-names = "ahb", "ephy"; + clocks = <&bus_gates 17>, <&bus_gates 128>; + clock-names = "ahb", "ephy"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + gic: interrupt-controller@01c81000 { compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; reg = <0x01c81000 0x1000>, diff --git a/arch/arm/imx-common/ddrmc-vf610.c b/arch/arm/imx-common/ddrmc-vf610.c index daf3c7ebfaf..9bc56f6ac13 100644 --- a/arch/arm/imx-common/ddrmc-vf610.c +++ b/arch/arm/imx-common/ddrmc-vf610.c @@ -212,7 +212,7 @@ void ddrmc_ctrl_init_ddr3(struct ddr3_jedec_timings const *timings, cr_setting++; } - /* perform default PHY settings (may be overriden by custom settings */ + /* perform default PHY settings (may be overridden by custom settings */ phy_setting = default_phy_settings; while (phy_setting->phy_rnum >= 0) { writel(phy_setting->setting, 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/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index c2e72f5a86b..d4dff1e3463 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -40,7 +40,8 @@ struct sunxi_ccm_reg { u32 ahb_gate1; /* 0x64 ahb module clock gating 1 */ u32 apb1_gate; /* 0x68 apb1 module clock gating */ u32 apb2_gate; /* 0x6c apb2 module clock gating */ - u32 reserved9[4]; + u32 bus_gate4; /* 0x70 gate 4 module clock gating */ + u8 res3[0xc]; u32 nand0_clk_cfg; /* 0x80 nand0 clock control */ u32 nand1_clk_cfg; /* 0x84 nand1 clock control */ u32 sd0_clk_cfg; /* 0x88 sd0 clock control */ @@ -387,6 +388,7 @@ struct sunxi_ccm_reg { #define AHB_RESET_OFFSET_LCD0 4 /* ahb_reset2 offsets */ +#define AHB_RESET_OFFSET_EPHY 2 #define AHB_RESET_OFFSET_LVDS 0 /* apb2 reset */ diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h index c5e9d88bab5..cd009d7ccc2 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h @@ -87,7 +87,8 @@ #define SUNXI_KEYPAD_BASE 0x01c23000 #define SUNXI_TZPC_BASE 0x01c23400 -#if defined(CONFIG_MACH_SUN8I_A83T) || defined(CONFIG_MACH_SUN8I_H3) +#if defined(CONFIG_MACH_SUN8I_A83T) || defined(CONFIG_MACH_SUN8I_H3) || \ +defined(CONFIG_MACH_SUN50I) /* SID address space starts at 0x01c1400, but e-fuse is at offset 0x200 */ #define SUNXI_SID_BASE 0x01c14200 #else diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 1ace5480227..bff7d1453f1 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -141,6 +141,7 @@ enum sunxi_gpio_number { /* GPIO pin function config */ #define SUNXI_GPIO_INPUT 0 #define SUNXI_GPIO_OUTPUT 1 +#define SUNXI_GPIO_DISABLE 7 #define SUNXI_GPA_EMAC 2 #define SUN6I_GPA_GMAC 2 @@ -162,8 +163,10 @@ enum sunxi_gpio_number { #define SUN50I_GPB_UART0 4 #define SUNXI_GPC_NAND 2 +#define SUNXI_GPC_SPI0 3 #define SUNXI_GPC_SDC2 3 #define SUN6I_GPC_SDC3 4 +#define SUN50I_GPC_SPI0 4 #define SUN8I_GPD_SDC1 3 #define SUNXI_GPD_LCD0 2 diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h index 3da360b177d..cb52e648731 100644 --- a/arch/arm/include/asm/arch-sunxi/mmc.h +++ b/arch/arm/include/asm/arch-sunxi/mmc.h @@ -127,5 +127,4 @@ struct sunxi_mmc { #define SUNXI_MMC_COMMON_RESET (1 << 18) struct mmc *sunxi_mmc_init(int sdc_no); -int sunxi_mmc_has_egon_boot_signature(struct mmc *mmc); #endif /* _SUNXI_MMC_H */ diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h index ec73379735c..5d7ab559ef9 100644 --- a/arch/arm/include/asm/arch-sunxi/spl.h +++ b/arch/arm/include/asm/arch-sunxi/spl.h @@ -51,7 +51,14 @@ struct boot_file_head { uint8_t spl_signature[4]; }; uint32_t fel_script_address; - uint32_t reserved1[3]; + /* + * If the fel_uEnv_length member below is set to a non-zero value, + * it specifies the size (byte count) of data at fel_script_address. + * At the same time this indicates that the data is in uEnv.txt + * compatible format, ready to be imported via "env import -t". + */ + uint32_t fel_uEnv_length; + uint32_t reserved1[2]; uint32_t boot_media; /* written here by the boot ROM */ uint32_t reserved2[5]; /* padding, align to 64 bytes */ }; diff --git a/arch/arm/include/asm/arch-tegra/board.h b/arch/arm/include/asm/arch-tegra/board.h index 783bb3c0fa1..a3db7ed6044 100644 --- a/arch/arm/include/asm/arch-tegra/board.h +++ b/arch/arm/include/asm/arch-tegra/board.h @@ -20,7 +20,7 @@ void gpio_early_init(void); /* overrideable GPIO config */ /* * Hooks to allow boards to set up the pinmux for a specific function. * Has to be implemented in the board files as we don't yet support pinmux - * setup from FTD. If a board file does not implement one of those functions + * setup from FDT. If a board file does not implement one of those functions * an empty stub function will be called. */ diff --git a/arch/arm/include/asm/arch-tegra/clock.h b/arch/arm/include/asm/arch-tegra/clock.h index e56031d1afa..7daf8bc1632 100644 --- a/arch/arm/include/asm/arch-tegra/clock.h +++ b/arch/arm/include/asm/arch-tegra/clock.h @@ -324,7 +324,7 @@ enum periph_id clk_id_to_periph_id(int clk_id); * @param p post divider(DIVP) * @param cpcon base PLL charge pump(CPCON) * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot - * be overriden), 1 if PLL is already correct + * be overridden), 1 if PLL is already correct */ int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon); diff --git a/arch/arm/include/asm/arch-tegra124/display.h b/arch/arm/include/asm/arch-tegra124/display.h index ca6644af345..c522faa9367 100644 --- a/arch/arm/include/asm/arch-tegra124/display.h +++ b/arch/arm/include/asm/arch-tegra124/display.h @@ -11,7 +11,7 @@ /** * Register a new display based on device tree configuration. * - * The frame buffer can be positioned by U-Boot or overriden by the fdt. + * The frame buffer can be positioned by U-Boot or overridden by the fdt. * You should pass in the U-Boot address here, and check the contents of * struct fdt_disp_config to see what was actually chosen. * diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h index 423fc701116..a20702e612b 100644 --- a/arch/arm/include/asm/armv7.h +++ b/arch/arm/include/asm/armv7.h @@ -126,6 +126,8 @@ void _smp_pen(void); extern char __secure_start[]; extern char __secure_end[]; +extern char __secure_stack_start[]; +extern char __secure_stack_end[]; #endif /* CONFIG_ARMV7_NONSEC */ 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/psci.h b/arch/arm/include/asm/psci.h index f92633b13f8..e76ecb27a7f 100644 --- a/arch/arm/include/asm/psci.h +++ b/arch/arm/include/asm/psci.h @@ -47,12 +47,19 @@ #define ARM_PSCI_0_2_FN_SYSTEM_OFF ARM_PSCI_0_2_FN(8) #define ARM_PSCI_0_2_FN_SYSTEM_RESET ARM_PSCI_0_2_FN(9) +/* 1KB stack per core */ +#define ARM_PSCI_STACK_SHIFT 10 +#define ARM_PSCI_STACK_SIZE (1 << ARM_PSCI_STACK_SHIFT) + #ifndef __ASSEMBLY__ #include <asm/types.h> +/* These 2 helper functions assume cpu < CONFIG_ARMV7_PSCI_NR_CPUS */ +u32 psci_get_target_pc(int cpu); +void psci_save_target_pc(int cpu, u32 pc); + void psci_cpu_entry(void); u32 psci_get_cpu_id(void); -u32 psci_get_cpu_stack_top(int cpu); void psci_cpu_off_common(void); int psci_update_dt(void *fdt); diff --git a/arch/arm/include/asm/secure.h b/arch/arm/include/asm/secure.h index effdb1858d8..5a403bc0f15 100644 --- a/arch/arm/include/asm/secure.h +++ b/arch/arm/include/asm/secure.h @@ -3,6 +3,9 @@ #include <config.h> +#define __secure __attribute__ ((section ("._secure.text"))) +#define __secure_data __attribute__ ((section ("._secure.data"))) + #ifdef CONFIG_ARMV7_SECURE_BASE /* * Warning, horror ahead. 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 fe5b4883391..4481f9e2fa9 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 + #if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV8_PSCI) 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/lib/sections.c b/arch/arm/lib/sections.c index 6a945224183..952e8ae49bf 100644 --- a/arch/arm/lib/sections.c +++ b/arch/arm/lib/sections.c @@ -27,6 +27,8 @@ char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start"))); char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end"))); char __secure_start[0] __attribute__((section(".__secure_start"))); char __secure_end[0] __attribute__((section(".__secure_end"))); +char __secure_stack_start[0] __attribute__((section(".__secure_stack_start"))); +char __secure_stack_end[0] __attribute__((section(".__secure_stack_end"))); char __efi_runtime_start[0] __attribute__((section(".__efi_runtime_start"))); char __efi_runtime_stop[0] __attribute__((section(".__efi_runtime_stop"))); char __efi_runtime_rel_start[0] __attribute__((section(".__efi_runtime_rel_start"))); 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/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 01bfc93cbb8..6d9518d4c60 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -205,7 +205,8 @@ DECLARE_GLOBAL_DATA_PTR; */ u32 spl_boot_device(void) { - __maybe_unused struct mmc *mmc0, *mmc1; + int boot_source; + /* * When booting from the SD card or NAND memory, the "eGON.BT0" * signature is expected to be found in memory at the address 0x0004 @@ -225,27 +226,19 @@ u32 spl_boot_device(void) if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */ return BOOT_DEVICE_BOARD; - /* The BROM will try to boot from mmc0 first, so try that first. */ -#ifdef CONFIG_MMC - mmc_initialize(gd->bd); - mmc0 = find_mmc_device(0); - if (sunxi_mmc_has_egon_boot_signature(mmc0)) + boot_source = readb(SPL_ADDR + 0x28); + switch (boot_source) { + case SUNXI_BOOTED_FROM_MMC0: return BOOT_DEVICE_MMC1; -#endif - - /* Fallback to booting NAND if enabled. */ - if (IS_ENABLED(CONFIG_SPL_NAND_SUPPORT)) + case SUNXI_BOOTED_FROM_NAND: return BOOT_DEVICE_NAND; - -#ifdef CONFIG_MMC - if (CONFIG_MMC_SUNXI_SLOT_EXTRA == 2) { - mmc1 = find_mmc_device(1); - if (sunxi_mmc_has_egon_boot_signature(mmc1)) - return BOOT_DEVICE_MMC2; + case SUNXI_BOOTED_FROM_MMC2: + return BOOT_DEVICE_MMC2; + case SUNXI_BOOTED_FROM_SPI: + return BOOT_DEVICE_SPI; } -#endif - panic("Could not determine boot source\n"); + panic("Unknown boot source %d\n", boot_source); return -1; /* Never reached */ } diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index c50d56dc888..36eabc8f572 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -510,7 +510,7 @@ unsigned clock_get_rate(enum clock_id clkid) * @param p post divider(DIVP) * @param cpcon base PLL charge pump(CPCON) * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot - * be overriden), 1 if PLL is already correct + * be overridden), 1 if PLL is already correct */ int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon) { diff --git a/arch/arm/mach-tegra/psci.S b/arch/arm/mach-tegra/psci.S index b836da1c0ed..645d08fa0bd 100644 --- a/arch/arm/mach-tegra/psci.S +++ b/arch/arm/mach-tegra/psci.S @@ -61,9 +61,6 @@ ENTRY(psci_arch_init) ldrne r7, [r5] mcrne p15, 0, r7, c14, c0, 0 @ write CNTFRQ to CPU1..3 - bl psci_get_cpu_stack_top @ stack top => r0 - mov sp, r0 - bx r6 ENDPROC(psci_arch_init) @@ -88,12 +85,13 @@ _loop: wfi ENDPROC(psci_cpu_off) ENTRY(psci_cpu_on) - push {lr} + push {r4, r5, r6, lr} + mov r4, r1 mov r0, r1 - bl psci_get_cpu_stack_top @ get stack top of target CPU - str r2, [r0] @ store target PC at stack top - dsb + mov r1, r2 + bl psci_save_target_pc @ store target PC + mov r1, r4 ldr r6, =TEGRA_RESET_EXCEPTION_VECTOR ldr r5, =psci_cpu_entry @@ -106,9 +104,7 @@ ENTRY(psci_cpu_on) str r5, [r6, r2] mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS - pop {pc} + pop {r4, r5, r6, pc} ENDPROC(psci_cpu_on) - .globl psci_text_end -psci_text_end: .popsection 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/powerpc/cpu/mpc85xx/mp.c b/arch/powerpc/cpu/mpc85xx/mp.c index 88c8e65930e..0addf8493c2 100644 --- a/arch/powerpc/cpu/mpc85xx/mp.c +++ b/arch/powerpc/cpu/mpc85xx/mp.c @@ -30,7 +30,7 @@ u32 get_my_id() */ int hold_cores_in_reset(int verbose) { - /* Default to no, overriden by 'y', 'yes', 'Y', 'Yes', or '1' */ + /* Default to no, overridden by 'y', 'yes', 'Y', 'Yes', or '1' */ if (getenv_yesno("mp_holdoff") == 1) { if (verbose) { puts("Secondary cores are being held in reset.\n"); diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S index b432b18c74d..5647d712d6d 100644 --- a/arch/powerpc/cpu/ppc4xx/start.S +++ b/arch/powerpc/cpu/ppc4xx/start.S @@ -144,7 +144,7 @@ #endif /* - * Unless otherwise overriden, enable two 128MB cachable instruction regions + * Unless otherwise overridden, enable two 128MB cachable instruction regions * at CONFIG_SYS_SDRAM_BASE and another 128MB cacheable instruction region covering * NOR flash at CONFIG_SYS_FLASH_BASE. Disable all cacheable data regions. */ diff --git a/arch/powerpc/include/asm/status_led.h b/arch/powerpc/include/asm/status_led.h index 441619042d2..260a8319ce3 100644 --- a/arch/powerpc/include/asm/status_led.h +++ b/arch/powerpc/include/asm/status_led.h @@ -7,7 +7,7 @@ #ifndef __ASM_STATUS_LED_H__ #define __ASM_STATUS_LED_H__ -/* if not overriden */ +/* if not overridden */ #ifndef CONFIG_BOARD_SPECIFIC_LED # if defined(CONFIG_8xx) # include <mpc8xx.h> 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 |