soc: intel_adsp: Generalize bootloader

Move bootloader to soc/xtensa/intel_adsp making it available for other
boards.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This commit is contained in:
Andrei Emeltchenko 2020-05-07 15:30:51 +03:00 committed by Carles Cufí
commit d6a33ef467
12 changed files with 36 additions and 8 deletions

View file

@ -7,3 +7,5 @@ zephyr_library_sources(soc.c)
zephyr_library_sources(main_entry.S)
zephyr_library_sources_ifdef(CONFIG_SMP soc_mp.c)
add_subdirectory(common)

View file

@ -0,0 +1,20 @@
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
add_subdirectory(${SOC_DIR}/${ARCH}/${SOC_FAMILY}/common/bootloader ${build_dir})
add_custom_target(
process_elf ALL
DEPENDS base_module
DEPENDS ${ZEPHYR_FINAL_EXECUTABLE}
COMMAND ${CMAKE_OBJCOPY} --dump-section .data=mod-apl.bin ${CMAKE_BINARY_DIR}/zephyr/soc/xtensa/${SOC_FAMILY}/common/bootloader/libbase_module.a
COMMAND ${CMAKE_OBJCOPY} --add-section .module=mod-apl.bin --set-section-flags .module=load,readonly ${CMAKE_BINARY_DIR}/zephyr/zephyr.elf ${CMAKE_BINARY_DIR}/zephyr/zephyr.elf.mod
)
add_custom_target(
process_bootloader ALL
DEPENDS bootloader boot_module
COMMAND ${CMAKE_OBJCOPY} --dump-section .data=mod-boot.bin ${CMAKE_BINARY_DIR}/zephyr/soc/xtensa/${SOC_FAMILY}/common/bootloader/libboot_module.a
COMMAND ${CMAKE_OBJCOPY} --add-section .module=mod-boot.bin --set-section-flags .module=load,readonly ${CMAKE_BINARY_DIR}/zephyr/soc/xtensa/${SOC_FAMILY}/common/bootloader/bootloader.elf ${CMAKE_BINARY_DIR}/zephyr/bootloader.elf.mod
)

View file

@ -0,0 +1,6 @@
# Intel CAVS SoC family CMake file
#
# Copyright (c) 2020 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
include(bootloader.cmake)

View file

@ -0,0 +1,30 @@
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
set(SOC_FAMILY intel_apl_adsp)
if(EXISTS ${SOC_DIR}/${ARCH}/${SOC_FAMILY}/common/bootloader/CMakeLists.txt)
if(USING_OUT_OF_TREE_BOARD)
set(build_dir boards/${ARCH}/${BOARD}/bootloader)
else()
unset(build_dir)
endif()
add_subdirectory(${SOC_DIR}/${ARCH}/${SOC_FAMILY}/common/bootloader ${build_dir})
endif()
add_custom_target(
process_elf ALL
DEPENDS base_module
DEPENDS ${ZEPHYR_FINAL_EXECUTABLE}
COMMAND ${CMAKE_OBJCOPY} --dump-section .data=mod-apl.bin ${CMAKE_BINARY_DIR}/zephyr/soc/xtensa/${SOC_FAMILY}/common/bootloader/libbase_module.a
COMMAND ${CMAKE_OBJCOPY} --add-section .module=mod-apl.bin --set-section-flags .module=load,readonly ${CMAKE_BINARY_DIR}/zephyr/zephyr.elf ${CMAKE_BINARY_DIR}/zephyr/zephyr.elf.mod
)
add_custom_target(
process_bootloader ALL
DEPENDS bootloader boot_module
COMMAND ${CMAKE_OBJCOPY} --dump-section .data=mod-boot.bin ${CMAKE_BINARY_DIR}/zephyr/soc/xtensa/${SOC_FAMILY}/common/bootloader/libboot_module.a
COMMAND ${CMAKE_OBJCOPY} --add-section .module=mod-boot.bin --set-section-flags .module=load,readonly ${CMAKE_BINARY_DIR}/zephyr/soc/xtensa/${SOC_FAMILY}/common/bootloader/bootloader.elf ${CMAKE_BINARY_DIR}/zephyr/bootloader.elf.mod
)

View file

@ -0,0 +1,47 @@
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
add_library(base_module base_module.c)
target_include_directories(base_module PUBLIC
${SOC_DIR}/${ARCH}/${SOC_PATH}/include
)
add_library(boot_module boot_module.c)
target_include_directories(boot_module PUBLIC
${SOC_DIR}/${ARCH}/${SOC_PATH}/include
)
add_executable(bootloader
boot_entry.S
${ARCH_DIR}/${ARCH}/core/startup/memctl_default.S
${ARCH_DIR}/${ARCH}/core/startup/memerror-vector.S
${ARCH_DIR}/${ARCH}/core/startup/reset-vector.S
boot_loader.c
start_address.S
)
add_dependencies(bootloader ${SYSCALL_LIST_H_TARGET})
set(zephyr_sdk $ENV{ZEPHYR_SDK_INSTALL_DIR})
target_include_directories(bootloader PUBLIC
./
${ZEPHYR_BASE}/include
${TOOLCHAIN_INCLUDES}
${SOC_DIR}/${ARCH}/${SOC_PATH}/
${SOC_DIR}/${ARCH}/${SOC_PATH}/include
)
set_source_files_properties(boot_entry.S PROPERTIES COMPILE_FLAGS -DASSEMBLY)
set_source_files_properties(${ARCH_DIR}/${ARCH}/core/startup/reset-vector.S PROPERTIES COMPILE_FLAGS -DBOOTLOADER)
target_compile_options(bootloader PUBLIC -fno-inline-functions -mlongcalls -mtext-section-literals -imacros${CMAKE_BINARY_DIR}/zephyr/include/generated/autoconf.h)
target_link_libraries(bootloader PUBLIC -Wl,--no-check-sections -ucall_user_start -Wl,-static -nostdlib)
target_link_libraries(bootloader PRIVATE -lhal -L${zephyr_sdk}/xtensa/intel_apl_adsp/xtensa-zephyr-elf/lib)
target_link_libraries(bootloader PRIVATE -T${SOC_DIR}/${ARCH}/${SOC_FAMILY}/common/bootloader/boot_ldr.x)
if(CONFIG_XTENSA_HAL)
target_link_libraries(bootloader PRIVATE XTENSA_HAL)
endif()

View file

@ -0,0 +1,32 @@
/*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
#include "manifest.h"
#include <platform/memory.h>
/*
* Each module has an entry in the FW manifest header. This is NOT part of
* the SOF executable image but is inserted by object copy as a ELF section
* for parsing by rimage (to genrate the manifest).
*/
struct sof_man_module_manifest apl_manifest = {
.module = {
.name = "BASEFW",
.uuid = {0x2e, 0x9e, 0x86, 0xfc, 0xf8, 0x45, 0x45, 0x40,
0xa4, 0x16, 0x89, 0x88, 0x0a, 0xe3, 0x20, 0xa9},
.entry_point = SOF_TEXT_START,
.type = {
.load_type = SOF_MAN_MOD_TYPE_MODULE,
.domain_ll = 1,
},
.affinity_mask = 3,
},
};
/* not used, but stops linker complaining */
int _start;

View file

@ -0,0 +1,223 @@
/*
* Copyright(c) 2016 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
/*
* Entry point from ROM - assumes :-
*
* 1) C runtime environment is initialized by ROM.
* 2) Stack is in first HPSRAM bank.
*/
#include <platform/shim.h>
#include <platform/platform.h>
#include <xtensa/corebits.h>
#include <xtensa/config/core-isa.h>
.type boot_master_core, @function
.begin literal_prefix .boot_entry
.section .boot_entry.text, "ax"
.align 4
.global boot_entry
boot_entry:
entry a1, 48
j boot_init
.align 4
.literal_position
#if defined(PLATFORM_RESET_MHE_AT_BOOT)
l2_mecs:
.word SHIM_L2_MECS
#endif
#if defined(PLATFORM_DISABLE_L2CACHE_AT_BOOT)
l2_cache_pref:
.word SHIM_L2_PREF_CFG
#endif
sof_stack_base:
.word SOF_STACK_BASE
wnd0_base:
.word DMWBA(0)
wnd0_size:
.word DMWLO(0)
wnd0_base_val:
.word HP_SRAM_WIN0_BASE | DMWBA_READONLY | DMWBA_ENABLE
wnd0_size_val:
.word HP_SRAM_WIN0_SIZE | 0x7
wnd0_status_address:
.word HP_SRAM_WIN0_BASE
wnd0_error_address:
.word HP_SRAM_WIN0_BASE | 0x4
#if defined(PLATFORM_MEM_INIT_AT_BOOT)
shim_ldoctl_address:
.word SHIM_BASE + SHIM_LDOCTL
ldoctl_hpsram_ldo_on:
.word SHIM_LDOCTL_HPSRAM_LDO_ON
ldoctl_hpsram_ldo_bypass:
.word SHIM_LDOCTL_HPSRAM_LDO_BYPASS
hspgctl0_address:
.word HSPGCTL0
hsrmctl0_address:
.word HSRMCTL0
hspgctl1_address:
.word HSPGCTL1
hsrmctl1_address:
.word HSRMCTL1
hspgists0_address:
.word HSPGISTS0
hspgists1_address:
.word HSPGISTS1
#endif
fw_loaded_status_value:
.word 0x00000005
fw_no_errors_value:
.word 0x00000000
boot_init:
.align 4
#if defined(PLATFORM_DISABLE_L2CACHE_AT_BOOT)
l32r a3, l2_cache_pref
movi a5, 0
s32i a5, a3, 0
memw
#endif
#if defined(PLATFORM_RESET_MHE_AT_BOOT)
/* reset memory hole */
l32r a3, l2_mecs
movi a5, 0
s32i a5, a3, 0
#endif
#if defined(PLATFORM_MEM_INIT_AT_BOOT)
/* turn on memory _before_ stack reprogramming */
l32r a3, ldoctl_hpsram_ldo_on
l32r a5, shim_ldoctl_address
s32i a3, a5, 0
memw
/* delay for 256 iterations before touching pwr regs */
movi a2, 256
1: addi.n a2, a2, -1
bnez a2, 1b
movi a3, 0
l32r a5, hspgctl0_address
s32i a3, a5, 0
memw
l32r a5, hsrmctl0_address
s32i a3, a5, 0
memw
l32r a5, hspgctl1_address
s32i a3, a5, 0
memw
l32r a5, hsrmctl1_address
s32i a3, a5, 0
memw
/* wait for status of first bank group */
l32r a5, hspgists0_address
2:
l32i a3, a5, 0
bnez a3, 2b
/* wait for status of second bank group */
l32r a5, hspgists1_address
3:
l32i a3, a5, 0
bnez a3, 3b
/* delay for 256 iterations before touching pwr regs */
movi a2, 256
4: addi.n a2, a2, -1
bnez a2, 4b
l32r a3, ldoctl_hpsram_ldo_bypass
l32r a5, shim_ldoctl_address
s32i a3, a5, 0
memw
#endif
/* reprogram stack to the area defined by main FW */
l32r a3, sof_stack_base
mov sp, a3
/* set status register to 0x00000005 in wnd0 */
l32r a3, fw_loaded_status_value
l32r a5, wnd0_status_address
s32i a3, a5, 0
/* set error register to 0x00 in wnd0 */
l32r a3, fw_no_errors_value
l32r a5, wnd0_error_address
s32i a3, a5, 0
/* realloc memory window0 to
continue reporting boot progress */
l32r a3, wnd0_size
l32r a5, wnd0_size_val
s32i a5, a3, 0
memw
l32r a3, wnd0_base
l32r a5, wnd0_base_val
s32i a5, a3, 0
memw
#if (XCHAL_DCACHE_IS_COHERENT || XCHAL_LOOP_BUFFER_SIZE) && \
XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0
/* Enable zero-overhead loop instr buffer,
and snoop responses, if configured. */
movi a3, (MEMCTL_SNOOP_EN | MEMCTL_L0IBUF_EN)
rsr a2, MEMCTL
or a2, a2, a3
wsr a2, MEMCTL
#endif
/* determine core we are running on */
rsr.prid a2
movi a3, PLATFORM_MASTER_CORE_ID
beq a2, a3, 1f
/* no core should get here */
j dead
1:
/* we are primary core so boot it */
call8 boot_master_core
dead:
/* should never get here - we are dead */
j dead
.size boot_entry, . - boot_entry
.end literal_prefix

View file

@ -0,0 +1,210 @@
OUTPUT_ARCH(xtensa)
PROVIDE(__memctl_default = 0x00000000);
PROVIDE(_MemErrorHandler = 0x00000000);
MEMORY
{
boot_entry_text :
org = 0xB000A000,
len = 0x86
boot_entry_lit :
org = (0xB000A000 + 0x86),
len = 0x70
sof_text :
org = ((0xB000A000 + 0x86) + 0x70),
len = 0x1C00,
sof_data :
org = 0xB0002000,
len = 0x1000
sof_bss_data :
org = 0xB0100000,
len = 0x10000
sof_stack :
org = 0xBE000000,
len = (1 * 0x1000)
wnd0 :
org = ((((((0xBE000000 + 0x8000) + 0x2000) + 0x800) + 0x800) + 0x1000) + 0x2000),
len = (0x1000 + 0x1000)
}
PHDRS
{
boot_entry_text_phdr PT_LOAD;
boot_entry_lit_phdr PT_LOAD;
sof_text_phdr PT_LOAD;
sof_data_phdr PT_LOAD;
sof_bss_data_phdr PT_LOAD;
sof_stack_phdr PT_LOAD;
wnd0_phdr PT_LOAD;
}
ENTRY(boot_entry)
EXTERN(reset_vector)
SECTIONS
{
.boot_entry.text : ALIGN(4)
{
_boot_entry_text_start = ABSOLUTE(.);
KEEP (*(.boot_entry.text))
_boot_entry_text_end = ABSOLUTE(.);
} >boot_entry_text :boot_entry_text_phdr
.boot_entry.literal : ALIGN(4)
{
_boot_entry_literal_start = ABSOLUTE(.);
*(.boot_entry.literal)
*(.literal .literal.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
_boot_entry_literal_end = ABSOLUTE(.);
} >boot_entry_lit :boot_entry_lit_phdr
.text : ALIGN(4)
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.entry.text)
*(.init.literal)
KEEP(*(.init))
*( .text .text.*)
*(.fini.literal)
KEEP(*(.fini))
*(.gnu.version)
KEEP (*(.ResetVector.text))
KEEP (*(.ResetHandler.text))
_text_end = ABSOLUTE(.);
_etext = .;
} >sof_text :sof_text_phdr
.rodata : ALIGN(4)
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
KEEP (*(.xt_except_table))
KEEP (*(.gcc_except_table))
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
KEEP (*(.eh_frame))
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
. = ALIGN(4);
_bss_table_start = ABSOLUTE(.);
LONG(_bss_start)
LONG(_bss_end)
_bss_table_end = ABSOLUTE(.);
_rodata_end = ABSOLUTE(.);
} >sof_data :sof_data_phdr
.data : ALIGN(4)
{
_data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
KEEP(*(.gnu.linkonce.d.*personality*))
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
KEEP(*(.jcr))
_data_end = ABSOLUTE(.);
} >sof_data :sof_data_phdr
.lit4 : ALIGN(4)
{
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
} >sof_data :sof_data_phdr
.bss (NOLOAD) : ALIGN(8)
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} >sof_bss_data :sof_bss_data_phdr
_man = 0x1234567;
PROVIDE(_memmap_vecbase_reset = (((((((0xBE000000 + 0x8000) + 0x2000) + 0x800) + 0x800) + 0x1000) + 0x2000) + (0x1000 + 0x1000)));
_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2;
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull);
__stack = 0xBE000000 + (1 * 0x1000);
__wnd0 = ((((((0xBE000000 + 0x8000) + 0x2000) + 0x800) + 0x800) + 0x1000) + 0x2000);
__wnd0_size = (0x1000 + 0x1000);
.comment 0 : { *(.comment) }
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.debug_ranges 0 : { *(.debug_ranges) }
.xtensa.info 0 : { *(.xtensa.info) }
.xt.insn 0 :
{
KEEP (*(.xt.insn))
KEEP (*(.gnu.linkonce.x.*))
}
.xt.prop 0 :
{
KEEP (*(.xt.prop))
KEEP (*(.xt.prop.*))
KEEP (*(.gnu.linkonce.prop.*))
}
.xt.lit 0 :
{
KEEP (*(.xt.lit))
KEEP (*(.xt.lit.*))
KEEP (*(.gnu.linkonce.p.*))
}
.xt.profile_range 0 :
{
KEEP (*(.xt.profile_range))
KEEP (*(.gnu.linkonce.profile_range.*))
}
.xt.profile_ranges 0 :
{
KEEP (*(.xt.profile_ranges))
KEEP (*(.gnu.linkonce.xt.profile_ranges.*))
}
.xt.profile_files 0 :
{
KEEP (*(.xt.profile_files))
KEEP (*(.gnu.linkonce.xt.profile_files.*))
}
}

View file

@ -0,0 +1,166 @@
/*
* Copyright(c) 2016 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
#include <platform/platform.h>
#include <platform/memory.h>
#include <soc.h>
#include "manifest.h"
#define MANIFEST_BASE IMR_BOOT_LDR_MANIFEST_BASE
extern void __start(void);
static inline void idelay(int n)
{
while (n--) {
__asm__ volatile("nop");
}
}
/* memcopy used by boot loader */
static inline void bmemcpy(void *dest, void *src, size_t bytes)
{
uint32_t *d = dest;
uint32_t *s = src;
int i;
for (i = 0; i < (bytes >> 2); i++)
d[i] = s[i];
SOC_DCACHE_FLUSH(dest, bytes);
}
/* bzero used by bootloader */
static inline void bbzero(void *dest, size_t bytes)
{
uint32_t *d = dest;
int i;
for (i = 0; i < (bytes >> 2); i++)
d[i] = 0;
SOC_DCACHE_FLUSH(dest, bytes);
}
static void parse_module(struct sof_man_fw_header *hdr,
struct sof_man_module *mod)
{
int i;
uint32_t bias;
/* each module has 3 segments */
for (i = 0; i < 3; i++) {
/* platform_trace_point(TRACE_BOOT_LDR_PARSE_SEGMENT + i); */
switch (mod->segment[i].flags.r.type) {
case SOF_MAN_SEGMENT_TEXT:
case SOF_MAN_SEGMENT_DATA:
bias = (mod->segment[i].file_offset -
SOF_MAN_ELF_TEXT_OFFSET);
/* copy from IMR to SRAM */
bmemcpy((void *)mod->segment[i].v_base_addr,
(void *)((int)hdr + bias),
mod->segment[i].flags.r.length *
HOST_PAGE_SIZE);
break;
case SOF_MAN_SEGMENT_BSS:
/* copy from IMR to SRAM */
bbzero((void *)mod->segment[i].v_base_addr,
mod->segment[i].flags.r.length *
HOST_PAGE_SIZE);
break;
default:
/* ignore */
break;
}
}
}
#define MAN_SKIP_ENTRIES 1
/* parse FW manifest and copy modules */
static void parse_manifest(void)
{
struct sof_man_fw_desc *desc =
(struct sof_man_fw_desc *)MANIFEST_BASE;
struct sof_man_fw_header *hdr = &desc->header;
struct sof_man_module *mod;
int i;
/* copy module to SRAM - skip bootloader module */
for (i = MAN_SKIP_ENTRIES; i < hdr->num_module_entries; i++) {
/* platform_trace_point(TRACE_BOOT_LDR_PARSE_MODULE + i); */
mod = (void *)((uintptr_t)desc + SOF_MAN_MODULE_OFFSET(i));
parse_module(hdr, mod);
}
}
static int32_t lp_sram_init(void)
{
uint32_t status;
uint32_t lspgctl_value;
uint32_t timeout_counter, delay_count = 256;
timeout_counter = delay_count;
shim_write(SHIM_LDOCTL, SHIM_LDOCTL_LPSRAM_LDO_ON);
/* add some delay before writing power registers */
idelay(delay_count);
lspgctl_value = shim_read(LSPGCTL);
shim_write(LSPGCTL, lspgctl_value & ~LPSRAM_MASK(0));
/* add some delay before checking the status */
idelay(delay_count);
/* query the power status of first part of LP memory */
/* to check whether it has been powered up. A few */
/* cycles are needed for it to be powered up */
status = io_reg_read(LSPGISTS);
while (status) {
if (!timeout_counter--) {
/* platform_panic(SOF_IPC_PANIC_MEM); */
break;
}
idelay(delay_count);
status = io_reg_read(LSPGISTS);
}
shim_write(SHIM_LDOCTL, SHIM_LDOCTL_LPSRAM_LDO_BYPASS);
return status;
}
/* boot master core */
void boot_master_core(void)
{
int32_t result;
/* TODO: platform trace should write to HW IPC regs on CNL */
/* platform_trace_point(TRACE_BOOT_LDR_ENTRY); */
/* init the LPSRAM */
/* platform_trace_point(TRACE_BOOT_LDR_LPSRAM); */
result = lp_sram_init();
if (result < 0) {
/* platform_panic(SOF_IPC_PANIC_MEM); */
return;
}
/* parse manifest and copy modules */
/* platform_trace_point(TRACE_BOOT_LDR_MANIFEST); */
parse_manifest();
/* now call SOF entry */
/* platform_trace_point(TRACE_BOOT_LDR_JUMP); */
__start();
}

View file

@ -0,0 +1,34 @@
/*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: Marcin Maka <marcin.maka@linux.intel.com>
*/
#include "manifest.h"
#include <platform/memory.h>
/*
* Each module has an entry in the FW manifest header. This is NOT part of
* the SOF executable image but is inserted by object copy as a ELF section
* for parsing by rimage (to generate the manifest).
*/
struct sof_man_module_manifest apl_bootldr_manifest = {
.module = {
.name = "BRNGUP",
.uuid = {
0xcc, 0x48, 0x7b, 0x0d, 0xa9, 0x1e, 0x0a, 0x47,
0xa8, 0xc1, 0x53, 0x34, 0x24, 0x52, 0x8a, 0x17
},
.entry_point = IMR_BOOT_LDR_TEXT_ENTRY_BASE,
.type = {
.load_type = SOF_MAN_MOD_TYPE_MODULE,
.domain_ll = 1,
},
.affinity_mask = 3,
},
};
/* not used, but stops linker complaining */
int _start;

View file

@ -0,0 +1,199 @@
/*
* Copyright(c) 2017 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
*/
#ifndef __INCLUDE_UAPI_USER_MANIFEST_H__
#define __INCLUDE_UAPI_USER_MANIFEST_H__
#include <stdint.h>
/* start offset for base FW module */
#define SOF_MAN_ELF_TEXT_OFFSET 0x2000
/* FW Extended Manifest Header id = $AE1 */
#define SOF_MAN_EXT_HEADER_MAGIC 0x31454124
/* module type load type */
#define SOF_MAN_MOD_TYPE_BUILTIN 0
#define SOF_MAN_MOD_TYPE_MODULE 1
struct sof_man_module_type {
uint32_t load_type:4; /* SOF_MAN_MOD_TYPE_ */
uint32_t auto_start:1;
uint32_t domain_ll:1;
uint32_t domain_dp:1;
uint32_t rsvd_:25;
};
/* segment flags.type */
#define SOF_MAN_SEGMENT_TEXT 0
#define SOF_MAN_SEGMENT_RODATA 1
#define SOF_MAN_SEGMENT_DATA 1
#define SOF_MAN_SEGMENT_BSS 2
#define SOF_MAN_SEGMENT_EMPTY 15
union sof_man_segment_flags {
uint32_t ul;
struct {
uint32_t contents:1;
uint32_t alloc:1;
uint32_t load:1;
uint32_t readonly:1;
uint32_t code:1;
uint32_t data:1;
uint32_t _rsvd0:2;
uint32_t type:4; /* MAN_SEGMENT_ */
uint32_t _rsvd1:4;
uint32_t length:16; /* of segment in pages */
} r;
} __attribute__((packed));
/*
* Module segment descriptor. Used by ROM - Immutable.
*/
struct sof_man_segment_desc {
union sof_man_segment_flags flags;
uint32_t v_base_addr;
uint32_t file_offset;
} __attribute__((packed));
/*
* The firmware binary can be split into several modules.
*/
#define SOF_MAN_MOD_ID_LEN 4
#define SOF_MAN_MOD_NAME_LEN 8
#define SOF_MAN_MOD_SHA256_LEN 32
#define SOF_MAN_MOD_ID {'$', 'A', 'M', 'E'}
/*
* Each module has an entry in the FW header. Used by ROM - Immutable.
*/
struct sof_man_module {
uint8_t struct_id[SOF_MAN_MOD_ID_LEN]; /* SOF_MAN_MOD_ID */
uint8_t name[SOF_MAN_MOD_NAME_LEN];
uint8_t uuid[16];
struct sof_man_module_type type;
uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
uint32_t entry_point;
uint16_t cfg_offset;
uint16_t cfg_count;
uint32_t affinity_mask;
uint16_t instance_max_count; /* max number of instances */
uint16_t instance_bss_size; /* instance (pages) */
struct sof_man_segment_desc segment[3];
} __attribute__((packed));
/*
* Each module has a configuration in the FW header. Used by ROM - Immutable.
*/
struct sof_man_mod_config {
uint32_t par[4]; /* module parameters */
uint32_t is_pages; /* actual size of instance .bss (pages) */
uint32_t cps; /* cycles per second */
uint32_t ibs; /* input buffer size (bytes) */
uint32_t obs; /* output buffer size (bytes) */
uint32_t module_flags; /* flags, reserved for future use */
uint32_t cpc; /* cycles per single run */
uint32_t obls; /* output block size, reserved for future use */
} __attribute__((packed));
/*
* FW Manifest Header
*/
#define SOF_MAN_FW_HDR_FW_NAME_LEN 8
#define SOF_MAN_FW_HDR_ID {'$', 'A', 'M', '1'}
#define SOF_MAN_FW_HDR_NAME "ADSPFW"
#define SOF_MAN_FW_HDR_FLAGS 0x0
#define SOF_MAN_FW_HDR_FEATURES 0x1ff
/*
* The firmware has a standard header that is checked by the ROM on firmware
* loading. preload_page_count is used by DMA code loader and is entire
* image size on CNL. i.e. CNL: total size of the binarys .text and .rodata
* Used by ROM - Immutable.
*/
struct sof_man_fw_header {
uint8_t header_id[4];
uint32_t header_len;
uint8_t name[SOF_MAN_FW_HDR_FW_NAME_LEN];
/* number of pages of preloaded image loaded by driver */
uint32_t preload_page_count;
uint32_t fw_image_flags;
uint32_t feature_mask;
uint16_t major_version;
uint16_t minor_version;
uint16_t hotfix_version;
uint16_t build_version;
uint32_t num_module_entries;
uint32_t hw_buf_base_addr;
uint32_t hw_buf_length;
/* target address for binary loading as offset in IMR
* must be == base offset
*/
uint32_t load_offset;
} __attribute__((packed));
/*
* Firmware manifest descriptor. This can contain N modules and N module
* configs. Used by ROM - Immutable.
*/
struct sof_man_fw_desc {
struct sof_man_fw_header header;
/* Warning - hack for module arrays. For some unknown reason the we
* have a variable size array of struct man_module followed by a
* variable size array of struct mod_config. These should have been
* merged into a variable array of a parent structure. We have to hack
* around this in many places....
*
* struct sof_man_module man_module[];
* struct sof_man_mod_config mod_config[];
*/
} __attribute__((packed));
/*
* Component Descriptor. Used by ROM - Immutable.
*/
struct sof_man_component_desc {
uint32_t reserved[2]; /* all 0 */
uint32_t version;
uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
uint32_t base_offset;
uint32_t limit_offset;
uint32_t attributes[4];
} __attribute__((packed));
/*
* Audio DSP extended metadata. Used by ROM - Immutable.
*/
struct sof_man_adsp_meta_file_ext {
uint32_t ext_type; /* always 17 for ADSP extension */
uint32_t ext_len;
uint32_t imr_type;
uint8_t reserved[16]; /* all 0 */
struct sof_man_component_desc comp_desc[1];
} __attribute__((packed));
/*
* Module Manifest for rimage module metadata. Not used by ROM.
*/
struct sof_man_module_manifest {
struct sof_man_module module;
uint32_t text_size;
};
/*
* Module offset in manifest.
*/
#define SOF_MAN_MODULE_OFFSET(index) \
(sizeof(struct sof_man_fw_header) + \
(index) * sizeof(struct sof_man_module))
#endif

View file

@ -0,0 +1,11 @@
/*
* Copyright (c) 2020 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <platform/memory.h>
.global _start
.equ _start, SOF_TEXT_BASE