[Sound-open-firmware] [PATCH] platform: Add platform drivers for cannonlake
Liam Girdwood
liam.r.girdwood at linux.intel.com
Tue Jan 23 17:40:14 CET 2018
From: Rander Wang <rander.wang at linux.intel.com>
Add platform initialisation and drivers for Intel Cannonlake platform.
Signed-off-by: Rander Wang <rander.wang at linux.intel.com>
---
src/platform/cannonlake/Makefile.am | 35 ++
src/platform/cannonlake/base_module.c | 52 +++
src/platform/cannonlake/boot_ldr.x.in | 431 ++++++++++++++++++++++
src/platform/cannonlake/boot_module.c | 52 +++
src/platform/cannonlake/cannonlake.x.in | 542 ++++++++++++++++++++++++++++
src/platform/cannonlake/clk.c | 206 +++++++++++
src/platform/cannonlake/dai.c | 108 ++++++
src/platform/cannonlake/dma.c | 175 +++++++++
src/platform/cannonlake/include/Makefile.am | 1 +
src/platform/cannonlake/interrupt.c | 304 ++++++++++++++++
src/platform/cannonlake/platform.c | 272 ++++++++++++++
src/platform/cannonlake/timer.c | 134 +++++++
12 files changed, 2312 insertions(+)
create mode 100644 src/platform/cannonlake/Makefile.am
create mode 100644 src/platform/cannonlake/base_module.c
create mode 100644 src/platform/cannonlake/boot_ldr.x.in
create mode 100644 src/platform/cannonlake/boot_module.c
create mode 100644 src/platform/cannonlake/cannonlake.x.in
create mode 100644 src/platform/cannonlake/clk.c
create mode 100644 src/platform/cannonlake/dai.c
create mode 100644 src/platform/cannonlake/dma.c
create mode 100644 src/platform/cannonlake/include/Makefile.am
create mode 100644 src/platform/cannonlake/interrupt.c
create mode 100644 src/platform/cannonlake/platform.c
create mode 100644 src/platform/cannonlake/timer.c
diff --git a/src/platform/cannonlake/Makefile.am b/src/platform/cannonlake/Makefile.am
new file mode 100644
index 0000000..9f3d591
--- /dev/null
+++ b/src/platform/cannonlake/Makefile.am
@@ -0,0 +1,35 @@
+SUBDIRS = include
+
+noinst_LIBRARIES = libplatform.a
+
+libplatform_a_SOURCES = \
+ platform.c \
+ dai.c \
+ dma.c \
+ clk.c \
+ timer.c \
+ interrupt.c
+
+libplatform_a_CFLAGS = \
+ $(ARCH_CFLAGS) \
+ $(ARCH_INCDIR) \
+ $(REEF_INCDIR) \
+ $(PLATFORM_INCDIR)
+
+noinst_PROGRAMS = module boot_module
+
+module_SOURCES = \
+ base_module.c
+
+module_CFLAGS = \
+ $(ARCH_INCDIR) \
+ $(REEF_INCDIR) \
+ $(PLATFORM_INCDIR)
+
+boot_module_SOURCES = \
+ boot_module.c
+
+boot_module_CFLAGS = \
+ $(ARCH_INCDIR) \
+ $(REEF_INCDIR) \
+ $(PLATFORM_INCDIR)
\ No newline at end of file
diff --git a/src/platform/cannonlake/base_module.c b/src/platform/cannonlake/base_module.c
new file mode 100644
index 0000000..dd5d719
--- /dev/null
+++ b/src/platform/cannonlake/base_module.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ */
+
+#include <uapi/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 cnl_manifest = {
+ .name = "BASEFW",
+ .uuid = {0x32, 0x8c, 0x39, 0x0e, 0xde, 0x5a, 0x4b, 0xba,
+ 0x93, 0xb1, 0xc5, 0x04, 0x32, 0x28, 0x0e, 0xe4},
+ .entry_point = REEF_TEXT_START,
+ .type = {
+ .load_type = SOF_MAN_MOD_TYPE_MODULE,
+ .domain_ll = 1,
+ },
+ .affinity_mask = 3,
+};
+
+/* not used, but stops linker complaining */
+int _start;
diff --git a/src/platform/cannonlake/boot_ldr.x.in b/src/platform/cannonlake/boot_ldr.x.in
new file mode 100644
index 0000000..cc7a2dc
--- /dev/null
+++ b/src/platform/cannonlake/boot_ldr.x.in
@@ -0,0 +1,431 @@
+/*
+ * Linker Script for Cannonlake Bootloader.
+ *
+ * This script is run through the GNU C preprocessor to align the memory
+ * offsets with headers.
+ *
+ * Use spaces for formatting as cpp ignore tab sizes.
+ */
+
+#include <platform/memory.h>
+#include <xtensa/config/core-isa-boot.h>
+
+OUTPUT_ARCH(xtensa)
+
+MEMORY
+{
+ boot_entry_text :
+ org = IMR_BOOT_LDR_TEXT_ENTRY_BASE,
+ len = IMR_BOOT_LDR_TEXT_ENTRY_SIZE
+ boot_entry_lit :
+ org = IMR_BOOT_LDR_LIT_BASE,
+ len = IMR_BOOT_LDR_LIT_SIZE
+ reef_text :
+ org = IMR_BOOT_LDR_TEXT_BASE,
+ len = IMR_BOOT_LDR_TEXT_SIZE,
+ vector_base_text :
+ org = XCHAL_VECBASE_RESET_PADDR,
+ len = REEF_MEM_VECBASE_LIT_SIZE
+ vector_int2_lit :
+ org = XCHAL_INTLEVEL2_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int2_text :
+ org = XCHAL_INTLEVEL2_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int3_lit :
+ org = XCHAL_INTLEVEL3_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int3_text :
+ org = XCHAL_INTLEVEL3_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int4_lit :
+ org = XCHAL_INTLEVEL4_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int4_text :
+ org = XCHAL_INTLEVEL4_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int5_lit :
+ org = XCHAL_INTLEVEL5_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int5_text :
+ org = XCHAL_INTLEVEL5_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int6_lit :
+ org = XCHAL_INTLEVEL6_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int6_text :
+ org = XCHAL_INTLEVEL6_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int7_lit :
+ org = XCHAL_INTLEVEL7_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int7_text :
+ org = XCHAL_INTLEVEL7_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_kernel_lit :
+ org = XCHAL_KERNEL_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_kernel_text :
+ org = XCHAL_KERNEL_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_user_lit :
+ org = XCHAL_USER_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_user_text :
+ org = XCHAL_USER_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_double_lit :
+ org = XCHAL_DOUBLEEXC_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_double_text :
+ org = XCHAL_DOUBLEEXC_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ reef_data :
+ org = IMR_BOOT_LDR_DATA_BASE,
+ len = IMR_BOOT_LDR_DATA_SIZE
+ reef_bss_data :
+ org = IMR_BOOT_LDR_BSS_BASE,
+ len = IMR_BOOT_LDR_BSS_SIZE
+}
+
+PHDRS
+{
+ boot_entry_text_phdr PT_LOAD;
+ boot_entry_lit_phdr PT_LOAD;
+ reef_text_phdr PT_LOAD;
+ vector_base_text_phdr PT_LOAD;
+ vector_int2_lit_phdr PT_LOAD;
+ vector_int2_text_phdr PT_LOAD;
+ vector_int3_lit_phdr PT_LOAD;
+ vector_int3_text_phdr PT_LOAD;
+ vector_int4_lit_phdr PT_LOAD;
+ vector_int4_text_phdr PT_LOAD;
+ vector_int5_lit_phdr PT_LOAD;
+ vector_int5_text_phdr PT_LOAD;
+ vector_int6_lit_phdr PT_LOAD;
+ vector_int6_text_phdr PT_LOAD;
+ vector_int7_lit_phdr PT_LOAD;
+ vector_int7_text_phdr PT_LOAD;
+ vector_kernel_lit_phdr PT_LOAD;
+ vector_kernel_text_phdr PT_LOAD;
+ vector_user_lit_phdr PT_LOAD;
+ vector_user_text_phdr PT_LOAD;
+ vector_double_lit_phdr PT_LOAD;
+ vector_double_text_phdr PT_LOAD;
+ reef_data_phdr PT_LOAD;
+ reef_bss_data_phdr PT_LOAD;
+}
+
+/* Default entry point: */
+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)
+ _text_end = ABSOLUTE(.);
+ _etext = .;
+ } >reef_text :reef_text_phdr
+
+ .WindowVectors.text : ALIGN(4)
+ {
+ _WindowVectors_text_start = ABSOLUTE(.);
+ KEEP (*(.WindowVectors.text))
+ _WindowVectors_text_end = ABSOLUTE(.);
+ } >vector_base_text :vector_base_text_phdr
+
+ .Level2InterruptVector.literal : ALIGN(4)
+ {
+ _Level2InterruptVector_literal_start = ABSOLUTE(.);
+ *(.Level2InterruptVector.literal)
+ _Level2InterruptVector_literal_end = ABSOLUTE(.);
+ } >vector_int2_lit :vector_int2_lit_phdr
+
+ .Level2InterruptVector.text : ALIGN(4)
+ {
+ _Level2InterruptVector_text_start = ABSOLUTE(.);
+ KEEP (*(.Level2InterruptVector.text))
+ _Level2InterruptVector_text_end = ABSOLUTE(.);
+ } >vector_int2_text :vector_int2_text_phdr
+
+ .Level3InterruptVector.literal : ALIGN(4)
+ {
+ _Level3InterruptVector_literal_start = ABSOLUTE(.);
+ *(.Level3InterruptVector.literal)
+ _Level3InterruptVector_literal_end = ABSOLUTE(.);
+ } >vector_int3_lit :vector_int3_lit_phdr
+
+ .Level3InterruptVector.text : ALIGN(4)
+ {
+ _Level3InterruptVector_text_start = ABSOLUTE(.);
+ KEEP (*(.Level3InterruptVector.text))
+ _Level3InterruptVector_text_end = ABSOLUTE(.);
+ } >vector_int3_text :vector_int3_text_phdr
+
+ .Level4InterruptVector.literal : ALIGN(4)
+ {
+ _Level4InterruptVector_literal_start = ABSOLUTE(.);
+ *(.Level4InterruptVector.literal)
+ _Level4InterruptVector_literal_end = ABSOLUTE(.);
+ } >vector_int4_lit :vector_int4_lit_phdr
+
+ .Level4InterruptVector.text : ALIGN(4)
+ {
+ _Level4InterruptVector_text_start = ABSOLUTE(.);
+ KEEP (*(.Level4InterruptVector.text))
+ _Level4InterruptVector_text_end = ABSOLUTE(.);
+ } >vector_int4_text :vector_int4_text_phdr
+
+ .Level5InterruptVector.literal : ALIGN(4)
+ {
+ _Level5InterruptVector_literal_start = ABSOLUTE(.);
+ *(.Level5InterruptVector.literal)
+ _Level5InterruptVector_literal_end = ABSOLUTE(.);
+ } >vector_int5_lit :vector_int5_lit_phdr
+
+ .Level5InterruptVector.text : ALIGN(4)
+ {
+ _Level5InterruptVector_text_start = ABSOLUTE(.);
+ KEEP (*(.Level5InterruptVector.text))
+ _Level5InterruptVector_text_end = ABSOLUTE(.);
+ } >vector_int5_text :vector_int5_text_phdr
+
+ .DebugExceptionVector.literal : ALIGN(4)
+ {
+ _DebugExceptionVector_literal_start = ABSOLUTE(.);
+ *(.DebugExceptionVector.literal)
+ _DebugExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_int6_lit :vector_int6_lit_phdr
+
+ .DebugExceptionVector.text : ALIGN(4)
+ {
+ _DebugExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.DebugExceptionVector.text))
+ _DebugExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_int6_text :vector_int6_text_phdr
+
+ .NMIExceptionVector.literal : ALIGN(4)
+ {
+ _NMIExceptionVector_literal_start = ABSOLUTE(.);
+ *(.NMIExceptionVector.literal)
+ _NMIExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_int7_lit :vector_int7_lit_phdr
+
+ .NMIExceptionVector.text : ALIGN(4)
+ {
+ _NMIExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.NMIExceptionVector.text))
+ _NMIExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_int7_text :vector_int7_text_phdr
+
+ .KernelExceptionVector.literal : ALIGN(4)
+ {
+ _KernelExceptionVector_literal_start = ABSOLUTE(.);
+ *(.KernelExceptionVector.literal)
+ _KernelExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_kernel_lit :vector_kernel_lit_phdr
+
+ .KernelExceptionVector.text : ALIGN(4)
+ {
+ _KernelExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.KernelExceptionVector.text))
+ _KernelExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_kernel_text :vector_kernel_text_phdr
+
+ .UserExceptionVector.literal : ALIGN(4)
+ {
+ _UserExceptionVector_literal_start = ABSOLUTE(.);
+ *(.UserExceptionVector.literal)
+ _UserExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_user_lit :vector_user_lit_phdr
+
+ .UserExceptionVector.text : ALIGN(4)
+ {
+ _UserExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.UserExceptionVector.text))
+ _UserExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_user_text :vector_user_text_phdr
+
+ .DoubleExceptionVector.literal : ALIGN(4)
+ {
+ _DoubleExceptionVector_literal_start = ABSOLUTE(.);
+ *(.DoubleExceptionVector.literal)
+ _DoubleExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_double_lit :vector_double_lit_phdr
+
+ .DoubleExceptionVector.text : ALIGN(4)
+ {
+ _DoubleExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.DoubleExceptionVector.text))
+ _DoubleExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_double_text :vector_double_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))
+ /* C++ constructor and destructor tables, properly ordered: */
+ 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))
+ /* C++ exception handlers table: */
+ __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); /* this table MUST be 4-byte aligned */
+ _bss_table_start = ABSOLUTE(.);
+ LONG(_bss_start)
+ LONG(_bss_end)
+ _bss_table_end = ABSOLUTE(.);
+ _rodata_end = ABSOLUTE(.);
+ } >reef_data :reef_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(.);
+ } >reef_data :reef_data_phdr
+
+ .lit4 : ALIGN(4)
+ {
+ _lit4_start = ABSOLUTE(.);
+ *(*.lit4)
+ *(.lit4.*)
+ *(.gnu.linkonce.lit4.*)
+ _lit4_end = ABSOLUTE(.);
+ } >reef_data :reef_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(.);
+ } >reef_bss_data :reef_bss_data_phdr
+
+ _man = 0x1234567;
+
+ PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET);
+
+ _memmap_cacheattr_wbna_trapnull = 0x25222222;
+ PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull);
+
+ .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) }
+
+ .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.*))
+ }
+}
diff --git a/src/platform/cannonlake/boot_module.c b/src/platform/cannonlake/boot_module.c
new file mode 100644
index 0000000..7d965f5
--- /dev/null
+++ b/src/platform/cannonlake/boot_module.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ */
+
+#include <uapi/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 cnl_bootldr_manifest = {
+ .name = "BRNGUP",
+ .uuid = {0xf3, 0xe4, 0x79, 0x2b, 0x75, 0x46, 0x49, 0xf6,
+ 0x89, 0xdf, 0x3b, 0xc1, 0x94, 0xa9, 0x1a, 0xeb},
+ .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;
diff --git a/src/platform/cannonlake/cannonlake.x.in b/src/platform/cannonlake/cannonlake.x.in
new file mode 100644
index 0000000..9ca28f0
--- /dev/null
+++ b/src/platform/cannonlake/cannonlake.x.in
@@ -0,0 +1,542 @@
+/*
+ * Linker Script for Apololake.
+ *
+ * This script is run through the GNU C preprocessor to align the memory
+ * offsets with headers.
+ *
+ * Use spaces for formatting as cpp ignore tab sizes.
+ */
+
+#include <platform/memory.h>
+#include <xtensa/config/core-isa.h>
+
+OUTPUT_ARCH(xtensa)
+
+MEMORY
+{
+ vector_reset_text :
+ org = XCHAL_RESET_VECTOR0_PADDR,
+ len = REEF_MEM_RESET_TEXT_SIZE
+ vector_reset_lit :
+ org = XCHAL_RESET_VECTOR0_PADDR + REEF_MEM_RESET_TEXT_SIZE,
+ len = REEF_MEM_RESET_LIT_SIZE
+ vector_memory_lit :
+ org = XCHAL_MEMERROR_VECTOR_PADDR + REEF_MEM_ERROR_LIT_SIZE,
+ len = REEF_MEM_ERROR_LIT_SIZE
+ vector_memory_text :
+ org = XCHAL_MEMERROR_VECTOR_PADDR,
+ len = REEF_MEM_ERROR_TEXT_SIZE
+ vector_base_text :
+ org = XCHAL_VECBASE_RESET_PADDR,
+ len = REEF_MEM_VECBASE_LIT_SIZE
+ vector_int2_lit :
+ org = XCHAL_INTLEVEL2_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int2_text :
+ org = XCHAL_INTLEVEL2_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int3_lit :
+ org = XCHAL_INTLEVEL3_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int3_text :
+ org = XCHAL_INTLEVEL3_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int4_lit :
+ org = XCHAL_INTLEVEL4_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int4_text :
+ org = XCHAL_INTLEVEL4_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int5_lit :
+ org = XCHAL_INTLEVEL5_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int5_text :
+ org = XCHAL_INTLEVEL5_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int6_lit :
+ org = XCHAL_INTLEVEL6_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int6_text :
+ org = XCHAL_INTLEVEL6_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_int7_lit :
+ org = XCHAL_INTLEVEL7_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_int7_text :
+ org = XCHAL_INTLEVEL7_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_kernel_lit :
+ org = XCHAL_KERNEL_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_kernel_text :
+ org = XCHAL_KERNEL_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_user_lit :
+ org = XCHAL_USER_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_user_text :
+ org = XCHAL_USER_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ vector_double_lit :
+ org = XCHAL_DOUBLEEXC_VECTOR_PADDR - REEF_MEM_VECT_LIT_SIZE,
+ len = REEF_MEM_VECT_LIT_SIZE
+ vector_double_text :
+ org = XCHAL_DOUBLEEXC_VECTOR_PADDR,
+ len = REEF_MEM_VECT_TEXT_SIZE
+ reef_text_start :
+ org = REEF_TEXT_START,
+ len = REEF_TEXT_START_SIZE,
+ reef_text :
+ org = REEF_TEXT_BASE,
+ len = REEF_TEXT_SIZE,
+ reef_data :
+ org = REEF_TEXT_BASE + REEF_TEXT_SIZE,
+ len = REEF_DATA_SIZE
+ reef_bss_data :
+ org = REEF_TEXT_BASE + REEF_TEXT_SIZE + REEF_DATA_SIZE,
+ len = REEF_BSS_DATA_SIZE
+ system_heap :
+ org = HEAP_SYSTEM_BASE,
+ len = HEAP_SYSTEM_SIZE
+ runtime_heap :
+ org = HEAP_RUNTIME_BASE,
+ len = HEAP_RUNTIME_SIZE
+ buffer_heap :
+ org = HEAP_BUFFER_BASE,
+ len = HEAP_BUFFER_SIZE
+ reef_stack :
+ org = REEF_STACK_END,
+ len = REEF_STACK_BASE - REEF_STACK_END
+}
+
+PHDRS
+{
+ vector_reset_text_phdr PT_LOAD;
+ vector_reset_lit_phdr PT_LOAD;
+ vector_memory_lit_phdr PT_LOAD;
+ vector_memory_text_phdr PT_LOAD;
+ vector_base_text_phdr PT_LOAD;
+ vector_int2_lit_phdr PT_LOAD;
+ vector_int2_text_phdr PT_LOAD;
+ vector_int3_lit_phdr PT_LOAD;
+ vector_int3_text_phdr PT_LOAD;
+ vector_int4_lit_phdr PT_LOAD;
+ vector_int4_text_phdr PT_LOAD;
+ vector_int5_lit_phdr PT_LOAD;
+ vector_int5_text_phdr PT_LOAD;
+ vector_int6_lit_phdr PT_LOAD;
+ vector_int6_text_phdr PT_LOAD;
+ vector_int7_lit_phdr PT_LOAD;
+ vector_int7_text_phdr PT_LOAD;
+ vector_kernel_lit_phdr PT_LOAD;
+ vector_kernel_text_phdr PT_LOAD;
+ vector_user_lit_phdr PT_LOAD;
+ vector_user_text_phdr PT_LOAD;
+ vector_double_lit_phdr PT_LOAD;
+ vector_double_text_phdr PT_LOAD;
+ reef_text_start_phdr PT_LOAD;
+ reef_text_phdr PT_LOAD;
+ reef_data_phdr PT_LOAD;
+ reef_bss_data_phdr PT_LOAD;
+ system_heap_phdr PT_LOAD;
+ runtime_heap_phdr PT_LOAD;
+ buffer_heap_phdr PT_LOAD;
+ reef_stack_phdr PT_LOAD;
+}
+
+/* Default entry point: */
+ENTRY(_MainEntry)
+_rom_store_table = 0;
+
+/* ABI0 does not use Window base */
+PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR);
+
+/* Various memory-map dependent cache attribute settings: */
+_memmap_cacheattr_wb_base = 0x44024000;
+_memmap_cacheattr_wt_base = 0x11021000;
+_memmap_cacheattr_bp_base = 0x22022000;
+_memmap_cacheattr_unused_mask = 0x00F00FFF;
+_memmap_cacheattr_wb_trapnull = 0x4422422F;
+_memmap_cacheattr_wba_trapnull = 0x4422422F;
+_memmap_cacheattr_wbna_trapnull = 0x25222222;
+_memmap_cacheattr_wt_trapnull = 0x1122122F;
+_memmap_cacheattr_bp_trapnull = 0x2222222F;
+_memmap_cacheattr_wb_strict = 0x44F24FFF;
+_memmap_cacheattr_wt_strict = 0x11F21FFF;
+_memmap_cacheattr_bp_strict = 0x22F22FFF;
+_memmap_cacheattr_wb_allvalid = 0x44224222;
+_memmap_cacheattr_wt_allvalid = 0x11221222;
+_memmap_cacheattr_bp_allvalid = 0x22222222;
+PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull);
+
+SECTIONS
+{
+ .ResetVector.text : ALIGN(4)
+ {
+ _ResetVector_text_start = ABSOLUTE(.);
+ KEEP (*(.ResetVector.text))
+ _ResetVector_text_end = ABSOLUTE(.);
+ } >vector_reset_text :vector_reset_text_phdr
+
+ .ResetVector.literal : ALIGN(4)
+ {
+ _ResetVector_literal_start = ABSOLUTE(.);
+ *(.ResetVector.literal)
+ _ResetVector_literal_end = ABSOLUTE(.);
+ } >vector_reset_lit :vector_reset_lit_phdr
+
+ .MemoryExceptionVector.literal : ALIGN(4)
+ {
+ _MemoryExceptionVector_literal_start = ABSOLUTE(.);
+ KEEP (*(.MemoryExceptionVector.literal))
+ _MemoryExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_memory_lit :vector_memory_lit_phdr
+
+ .MemoryExceptionVector.text : ALIGN(4)
+ {
+ _MemoryExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.MemoryExceptionVector.text))
+ _MemoryExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_memory_text :vector_memory_text_phdr
+
+ .WindowVectors.text : ALIGN(4)
+ {
+ _WindowVectors_text_start = ABSOLUTE(.);
+ KEEP (*(.WindowVectors.text))
+ _WindowVectors_text_end = ABSOLUTE(.);
+ } >vector_base_text :vector_base_text_phdr
+
+ .Level2InterruptVector.literal : ALIGN(4)
+ {
+ _Level2InterruptVector_literal_start = ABSOLUTE(.);
+ *(.Level2InterruptVector.literal)
+ _Level2InterruptVector_literal_end = ABSOLUTE(.);
+ } >vector_int2_lit :vector_int2_lit_phdr
+
+ .Level2InterruptVector.text : ALIGN(4)
+ {
+ _Level2InterruptVector_text_start = ABSOLUTE(.);
+ KEEP (*(.Level2InterruptVector.text))
+ _Level2InterruptVector_text_end = ABSOLUTE(.);
+ } >vector_int2_text :vector_int2_text_phdr
+
+ .Level3InterruptVector.literal : ALIGN(4)
+ {
+ _Level3InterruptVector_literal_start = ABSOLUTE(.);
+ *(.Level3InterruptVector.literal)
+ _Level3InterruptVector_literal_end = ABSOLUTE(.);
+ } >vector_int3_lit :vector_int3_lit_phdr
+
+ .Level3InterruptVector.text : ALIGN(4)
+ {
+ _Level3InterruptVector_text_start = ABSOLUTE(.);
+ KEEP (*(.Level3InterruptVector.text))
+ _Level3InterruptVector_text_end = ABSOLUTE(.);
+ } >vector_int3_text :vector_int3_text_phdr
+
+ .Level4InterruptVector.literal : ALIGN(4)
+ {
+ _Level4InterruptVector_literal_start = ABSOLUTE(.);
+ *(.Level4InterruptVector.literal)
+ _Level4InterruptVector_literal_end = ABSOLUTE(.);
+ } >vector_int4_lit :vector_int4_lit_phdr
+
+ .Level4InterruptVector.text : ALIGN(4)
+ {
+ _Level4InterruptVector_text_start = ABSOLUTE(.);
+ KEEP (*(.Level4InterruptVector.text))
+ _Level4InterruptVector_text_end = ABSOLUTE(.);
+ } >vector_int4_text :vector_int4_text_phdr
+
+ .Level5InterruptVector.literal : ALIGN(4)
+ {
+ _Level5InterruptVector_literal_start = ABSOLUTE(.);
+ *(.Level5InterruptVector.literal)
+ _Level5InterruptVector_literal_end = ABSOLUTE(.);
+ } >vector_int5_lit :vector_int5_lit_phdr
+
+ .Level5InterruptVector.text : ALIGN(4)
+ {
+ _Level5InterruptVector_text_start = ABSOLUTE(.);
+ KEEP (*(.Level5InterruptVector.text))
+ _Level5InterruptVector_text_end = ABSOLUTE(.);
+ } >vector_int5_text :vector_int5_text_phdr
+
+ .DebugExceptionVector.literal : ALIGN(4)
+ {
+ _DebugExceptionVector_literal_start = ABSOLUTE(.);
+ *(.DebugExceptionVector.literal)
+ _DebugExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_int6_lit :vector_int6_lit_phdr
+
+ .DebugExceptionVector.text : ALIGN(4)
+ {
+ _DebugExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.DebugExceptionVector.text))
+ _DebugExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_int6_text :vector_int6_text_phdr
+
+ .NMIExceptionVector.literal : ALIGN(4)
+ {
+ _NMIExceptionVector_literal_start = ABSOLUTE(.);
+ *(.NMIExceptionVector.literal)
+ _NMIExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_int7_lit :vector_int7_lit_phdr
+
+ .NMIExceptionVector.text : ALIGN(4)
+ {
+ _NMIExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.NMIExceptionVector.text))
+ _NMIExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_int7_text :vector_int7_text_phdr
+
+ .KernelExceptionVector.literal : ALIGN(4)
+ {
+ _KernelExceptionVector_literal_start = ABSOLUTE(.);
+ *(.KernelExceptionVector.literal)
+ _KernelExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_kernel_lit :vector_kernel_lit_phdr
+
+ .KernelExceptionVector.text : ALIGN(4)
+ {
+ _KernelExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.KernelExceptionVector.text))
+ _KernelExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_kernel_text :vector_kernel_text_phdr
+
+ .UserExceptionVector.literal : ALIGN(4)
+ {
+ _UserExceptionVector_literal_start = ABSOLUTE(.);
+ *(.UserExceptionVector.literal)
+ _UserExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_user_lit :vector_user_lit_phdr
+
+ .UserExceptionVector.text : ALIGN(4)
+ {
+ _UserExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.UserExceptionVector.text))
+ _UserExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_user_text :vector_user_text_phdr
+
+ .DoubleExceptionVector.literal : ALIGN(4)
+ {
+ _DoubleExceptionVector_literal_start = ABSOLUTE(.);
+ *(.DoubleExceptionVector.literal)
+ _DoubleExceptionVector_literal_end = ABSOLUTE(.);
+ } >vector_double_lit :vector_double_lit_phdr
+
+ .DoubleExceptionVector.text : ALIGN(4)
+ {
+ _DoubleExceptionVector_text_start = ABSOLUTE(.);
+ KEEP (*(.DoubleExceptionVector.text))
+ _DoubleExceptionVector_text_end = ABSOLUTE(.);
+ } >vector_double_text :vector_double_text_phdr
+
+ .MainEntry.text : ALIGN(4)
+ {
+ _MainEntry_text_start = ABSOLUTE(.);
+ KEEP (*(.MainEntry.text))
+ _MainEntry_text_end = ABSOLUTE(.);
+ } >reef_text_start :reef_text_start_phdr
+
+ .text : ALIGN(4)
+ {
+ _stext = .;
+ _text_start = ABSOLUTE(.);
+ *(.entry.text)
+ *(.init.literal)
+ KEEP(*(.init))
+ *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+ *(.fini.literal)
+ KEEP(*(.fini))
+ *(.gnu.version)
+ _text_end = ABSOLUTE(.);
+ _etext = .;
+ } >reef_text :reef_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))
+ /* C++ constructor and destructor tables, properly ordered: */
+ 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))
+ /* C++ exception handlers table: */
+ __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); /* this table MUST be 4-byte aligned */
+ _bss_table_start = ABSOLUTE(.);
+ LONG(_bss_start)
+ LONG(_bss_end)
+ _bss_table_end = ABSOLUTE(.);
+ _rodata_end = ABSOLUTE(.);
+ } >reef_data :reef_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(.);
+ } >reef_data :reef_data_phdr
+
+ .lit4 : ALIGN(4)
+ {
+ _lit4_start = ABSOLUTE(.);
+ *(*.lit4)
+ *(.lit4.*)
+ *(.gnu.linkonce.lit4.*)
+ _lit4_end = ABSOLUTE(.);
+ } >reef_data :reef_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(.);
+ } >reef_bss_data :reef_bss_data_phdr
+
+ /* stack */
+ _end = REEF_STACK_END;
+ PROVIDE(end = REEF_STACK_END);
+ _stack_sentry = REEF_STACK_END;
+ __stack = REEF_STACK_BASE;
+
+ /* System Heap */
+ _system_heap = HEAP_SYSTEM_BASE;
+
+
+ /* module heap */
+ _module_heap = HEAP_RUNTIME_BASE;
+
+ /* buffer heap */
+ _buffer_heap = HEAP_BUFFER_BASE;
+ _buffer_heap_end = _stack_sentry;
+
+ .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) }
+
+ .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.*))
+ }
+
+ .system_heap (NOLOAD) : ALIGN(8)
+ {
+ . = ALIGN (32);
+ _system_heap_start = ABSOLUTE(.);
+ . = . + HEAP_SYSTEM_SIZE;
+ _system_heap_end = ABSOLUTE(.);
+ } >system_heap :system_heap_phdr
+
+ .runtime_heap (NOLOAD) : ALIGN(8)
+ {
+ . = ALIGN (32);
+ _runtime_heap_start = ABSOLUTE(.);
+ . = . + HEAP_RUNTIME_SIZE;
+ _runtime_heap_end = ABSOLUTE(.);
+ } >runtime_heap :runtime_heap_phdr
+
+ .buffer_heap (NOLOAD) : ALIGN(8)
+ {
+ . = ALIGN (32);
+ _system_heap_start = ABSOLUTE(.);
+ . = . + HEAP_BUFFER_SIZE;
+ _system_heap_end = ABSOLUTE(.);
+ } >buffer_heap :buffer_heap_phdr
+
+ .reef_stack (NOLOAD) : ALIGN(8)
+ {
+ . = ALIGN (4096);
+ _reef_stack_start = ABSOLUTE(.);
+ . = . + REEF_STACK_SIZE;
+ _reef_stack_end = ABSOLUTE(.);
+ } >reef_stack :reef_stack_phdr
+}
diff --git a/src/platform/cannonlake/clk.c b/src/platform/cannonlake/clk.c
new file mode 100644
index 0000000..bcce20d
--- /dev/null
+++ b/src/platform/cannonlake/clk.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ * Keyon Jie <yang.jie at linux.intel.com>
+ * Rander Wang <rander.wang at intel.com>
+ */
+
+#include <reef/clock.h>
+#include <reef/io.h>
+#include <reef/reef.h>
+#include <reef/list.h>
+#include <reef/alloc.h>
+#include <reef/notifier.h>
+#include <reef/lock.h>
+#include <platform/clk.h>
+#include <platform/shim.h>
+#include <platform/timer.h>
+#include <config.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define NUM_CLOCKS 2
+
+struct clk_data {
+ uint32_t freq;
+ uint32_t ticks_per_usec;
+ spinlock_t lock;
+};
+
+struct clk_pdata {
+ struct clk_data clk[NUM_CLOCKS];
+};
+
+struct freq_table {
+ uint32_t freq;
+ uint32_t ticks_per_usec;
+ uint32_t enc;
+};
+
+static struct clk_pdata *clk_pdata;
+
+/* increasing frequency order */
+static const struct freq_table cpu_freq[] = {
+ {120000000, 120, 0x0},
+ {400000000, 400, 0x4},
+};
+
+static const struct freq_table ssp_freq[] = {
+ {19200000, 19,},
+ {25000000, 25,}, /* default */
+};
+
+#define CPU_DEFAULT_IDX 2
+#define SSP_DEFAULT_IDX 1
+
+static inline uint32_t get_freq(const struct freq_table *table, int size,
+ unsigned int hz)
+{
+ uint32_t i;
+
+ /* find lowest available frequency that is >= requested hz */
+ for (i = 0; i < size; i++) {
+ if (hz <= table[i].freq)
+ return i;
+ }
+
+ /* not found, so return max frequency */
+ return size - 1;
+}
+
+void clock_enable(int clock)
+{
+ switch (clock) {
+ case CLK_CPU:
+ break;
+ case CLK_SSP:
+ default:
+ break;
+ }
+}
+
+void clock_disable(int clock)
+{
+ switch (clock) {
+ case CLK_CPU:
+ break;
+ case CLK_SSP:
+ default:
+ break;
+ }
+}
+
+uint32_t clock_set_freq(int clock, uint32_t hz)
+{
+ struct clock_notify_data notify_data;
+ uint32_t idx;
+ uint32_t flags;
+
+ notify_data.old_freq = clk_pdata->clk[clock].freq;
+ notify_data.old_ticks_per_usec = clk_pdata->clk[clock].ticks_per_usec;
+
+ /* atomic context for chaning clocks */
+ spin_lock_irq(&clk_pdata->clk[clock].lock, flags);
+
+ switch (clock) {
+ case CLK_CPU:
+ /* get nearest frequency that is >= requested Hz */
+ idx = get_freq(cpu_freq, ARRAY_SIZE(cpu_freq), hz);
+ notify_data.freq = cpu_freq[idx].freq;
+
+ /* tell anyone interested we are about to change CPU freq */
+ notifier_event(NOTIFIER_ID_CPU_FREQ, CLOCK_NOTIFY_PRE,
+ ¬ify_data);
+
+ /* set CPU frequency request for CCU */
+ io_reg_update_bits(SHIM_BASE + SHIM_CLKCTL,
+ SHIM_CLKCTL_DPCS_MASK(0), cpu_freq[idx].enc);
+
+ /* tell anyone interested we have now changed CPU freq */
+ notifier_event(NOTIFIER_ID_CPU_FREQ, CLOCK_NOTIFY_POST,
+ ¬ify_data);
+ break;
+ case CLK_SSP:
+ default:
+ break;
+ }
+
+ spin_unlock_irq(&clk_pdata->clk[clock].lock, flags);
+ return clk_pdata->clk[clock].freq;
+}
+
+uint32_t clock_get_freq(int clock)
+{
+ return clk_pdata->clk[clock].freq;
+}
+
+uint64_t clock_us_to_ticks(int clock, uint64_t us)
+{
+ return clk_pdata->clk[clock].ticks_per_usec * us;
+}
+
+uint64_t clock_time_elapsed(int clock, uint64_t previous, uint64_t *current)
+{
+ uint64_t _current;
+
+ // TODO: change timer APIs to clk APIs ??
+ switch (clock) {
+ case CLK_CPU:
+ _current = arch_timer_get_system(NULL);
+ break;
+ case CLK_SSP:
+ _current = platform_timer_get(platform_timer);
+ break;
+ default:
+ return 0;
+ }
+
+ *current = _current;
+ if (_current >= previous)
+ return (_current - previous) /
+ clk_pdata->clk[clock].ticks_per_usec;
+ else
+ return (_current + (ULONG_LONG_MAX - previous)) /
+ clk_pdata->clk[clock].ticks_per_usec;
+}
+
+void init_platform_clocks(void)
+{
+ clk_pdata = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*clk_pdata));
+
+ spinlock_init(&clk_pdata->clk[0].lock);
+ spinlock_init(&clk_pdata->clk[1].lock);
+
+ /* set defaults */
+ clk_pdata->clk[CLK_CPU].freq = cpu_freq[CPU_DEFAULT_IDX].freq;
+ clk_pdata->clk[CLK_CPU].ticks_per_usec =
+ cpu_freq[CPU_DEFAULT_IDX].ticks_per_usec;
+ clk_pdata->clk[CLK_SSP].freq = ssp_freq[SSP_DEFAULT_IDX].freq;
+ clk_pdata->clk[CLK_SSP].ticks_per_usec =
+ ssp_freq[SSP_DEFAULT_IDX].ticks_per_usec;
+}
diff --git a/src/platform/cannonlake/dai.c b/src/platform/cannonlake/dai.c
new file mode 100644
index 0000000..1ca5c29
--- /dev/null
+++ b/src/platform/cannonlake/dai.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ * Keyon Jie <yang.jie at linux.intel.com>
+ * Rander Wang <rander.wang at intel.com>
+ */
+
+#include <reef/reef.h>
+#include <reef/dai.h>
+#include <reef/ssp.h>
+#include <reef/stream.h>
+#include <reef/audio/component.h>
+#include <platform/memory.h>
+#include <platform/interrupt.h>
+#include <platform/dma.h>
+#include <stdint.h>
+#include <string.h>
+#include <config.h>
+
+static struct dai ssp[] = {
+{
+ .type = SOF_DAI_INTEL_SSP,
+ .index = 0,
+ .plat_data = {
+ .base = SSP_BASE(0),
+ .irq = IRQ_EXT_SSP0_LVL5(0),
+ .fifo[SOF_IPC_STREAM_PLAYBACK] = {
+ .offset = SSP_BASE(0) + SSDR,
+ .handshake = DMA_HANDSHAKE_SSP0_TX,
+ },
+ .fifo[SOF_IPC_STREAM_CAPTURE] = {
+ .offset = SSP_BASE(0) + SSDR,
+ .handshake = DMA_HANDSHAKE_SSP0_RX,
+ }
+ },
+ .ops = &ssp_ops,
+},
+{
+ .type = SOF_DAI_INTEL_SSP,
+ .index = 1,
+ .plat_data = {
+ .base = SSP_BASE(1),
+ .irq = IRQ_EXT_SSP1_LVL5(0),
+ .fifo[SOF_IPC_STREAM_PLAYBACK] = {
+ .offset = SSP_BASE(1) + SSDR,
+ .handshake = DMA_HANDSHAKE_SSP1_TX,
+ },
+ .fifo[SOF_IPC_STREAM_CAPTURE] = {
+ .offset = SSP_BASE(1) + SSDR,
+ .handshake = DMA_HANDSHAKE_SSP1_RX,
+ }
+ },
+ .ops = &ssp_ops,
+},
+{
+ .type = SOF_DAI_INTEL_SSP,
+ .index = 2,
+ .plat_data = {
+ .base = SSP_BASE(2),
+ .irq = IRQ_EXT_SSP2_LVL5(0),
+ .fifo[SOF_IPC_STREAM_PLAYBACK] = {
+ .offset = SSP_BASE(2) + SSDR,
+ .handshake = DMA_HANDSHAKE_SSP2_TX,
+ },
+ .fifo[SOF_IPC_STREAM_CAPTURE] = {
+ .offset = SSP_BASE(2) + SSDR,
+ .handshake = DMA_HANDSHAKE_SSP2_RX,
+ }
+ },
+ .ops = &ssp_ops,
+},};
+
+struct dai *dai_get(uint32_t type, uint32_t index)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ssp); i++) {
+ if (ssp[i].type == type && ssp[i].index == index)
+ return &ssp[i];
+ }
+
+ return NULL;
+}
diff --git a/src/platform/cannonlake/dma.c b/src/platform/cannonlake/dma.c
new file mode 100644
index 0000000..45bdee3
--- /dev/null
+++ b/src/platform/cannonlake/dma.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ * Keyon Jie <yang.jie at linux.intel.com>
+ * Rander Wang <rander.wang at intel.com>
+ */
+
+#include <reef/dma.h>
+#include <reef/dw-dma.h>
+#include <platform/memory.h>
+#include <platform/interrupt.h>
+#include <platform/dma.h>
+#include <stdint.h>
+#include <string.h>
+
+static struct dw_drv_plat_data dmac0 = {
+ .chan[0] = {
+ .class = 6,
+ .weight = 0,
+ },
+ .chan[1] = {
+ .class = 6,
+ .weight = 0,
+ },
+ .chan[2] = {
+ .class = 6,
+ .weight = 0,
+ },
+ .chan[3] = {
+ .class = 6,
+ .weight = 0,
+ },
+ .chan[4] = {
+ .class = 6,
+ .weight = 0,
+ },
+ .chan[5] = {
+ .class = 6,
+ .weight = 0,
+ },
+ .chan[6] = {
+ .class = 6,
+ .weight = 0,
+ },
+ .chan[7] = {
+ .class = 6,
+ .weight = 0,
+ },
+};
+
+static struct dw_drv_plat_data dmac1 = {
+ .chan[0] = {
+ .class = 7,
+ .weight = 0,
+ },
+ .chan[1] = {
+ .class = 7,
+ .weight = 0,
+ },
+ .chan[2] = {
+ .class = 7,
+ .weight = 0,
+ },
+ .chan[3] = {
+ .class = 7,
+ .weight = 0,
+ },
+ .chan[4] = {
+ .class = 7,
+ .weight = 0,
+ },
+ .chan[5] = {
+ .class = 7,
+ .weight = 0,
+ },
+ .chan[6] = {
+ .class = 7,
+ .weight = 0,
+ },
+ .chan[7] = {
+ .class = 7,
+ .weight = 0,
+ },
+};
+
+static struct dma dma[] = {
+{ /* Low Power GP DMAC 0 */
+ .plat_data = {
+ .id = DMA_GP_LP_DMAC0,
+ .base = LP_GP_DMA_BASE(0),
+ .channels = 8,
+ .irq = IRQ_EXT_LP_GPDMA0_LVL5(0, 0),
+ .drv_plat_data = &dmac0,
+ },
+ .ops = &dw_dma_ops,
+},
+{ /* Low Power GP DMAC 1 */
+ .plat_data = {
+ .id = DMA_GP_LP_DMAC1,
+ .base = LP_GP_DMA_BASE(1),
+ .channels = 8,
+ .irq = IRQ_EXT_LP_GPDMA1_LVL4(0, 0),
+ .drv_plat_data = &dmac1,
+ },
+ .ops = &dw_dma_ops,
+},
+{ /* Host In DMAC */
+ .plat_data = {
+ .id = DMA_HOST_IN_DMAC,
+ .base = GTW_HOST_IN_STREAM_BASE(0),
+ .channels = 7,
+ .irq = IRQ_EXT_HOST_DMA_IN_LVL3(0, 0),
+ },
+},
+{ /* Host out DMAC */
+ .plat_data = {
+ .id = DMA_HOST_OUT_DMAC,
+ .base = GTW_HOST_OUT_STREAM_BASE(0),
+ .channels = 6,
+ .irq = IRQ_EXT_HOST_DMA_OUT_LVL3(0, 0),
+ },
+},
+{ /* Link In DMAC */
+ .plat_data = {
+ .id = DMA_LINK_IN_DMAC,
+ .base = GTW_LINK_IN_STREAM_BASE(0),
+ .channels = 8,
+ .irq = IRQ_EXT_LINK_DMA_IN_LVL4(0, 0),
+ },
+},
+{ /* Link out DMAC */
+ .plat_data = {
+ .id = DMA_LINK_OUT_DMAC,
+ .base = GTW_LINK_OUT_STREAM_BASE(0),
+ .channels = 8,
+ .irq = IRQ_EXT_LINK_DMA_OUT_LVL4(0, 0),
+ },
+},};
+
+struct dma *dma_get(int dmac_id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dma); i++) {
+ if (dma[i].plat_data.id == dmac_id)
+ return &dma[i];
+ }
+
+ return NULL;
+}
diff --git a/src/platform/cannonlake/include/Makefile.am b/src/platform/cannonlake/include/Makefile.am
new file mode 100644
index 0000000..19f40eb
--- /dev/null
+++ b/src/platform/cannonlake/include/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = platform xtensa
diff --git a/src/platform/cannonlake/interrupt.c b/src/platform/cannonlake/interrupt.c
new file mode 100644
index 0000000..3268362
--- /dev/null
+++ b/src/platform/cannonlake/interrupt.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Keyon Jie <yang.jie at linux.intel.com>
+ * Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ * Rander Wang <rander.wang at intel.com>
+ */
+
+#include <reef/reef.h>
+#include <reef/interrupt.h>
+#include <reef/interrupt-map.h>
+#include <arch/interrupt.h>
+#include <platform/interrupt.h>
+#include <platform/shim.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+static void parent_level2_handler(void *data)
+{
+ struct irq_parent *parent = (struct irq_parent *)data;
+ struct irq_child * child = NULL;
+ uint32_t status;
+ uint32_t i = 0;
+
+ /* mask the parent IRQ */
+ arch_interrupt_disable_mask(1 << IRQ_NUM_EXT_LEVEL2);
+
+ /* mask all child interrupts */
+ status = irq_read(REG_IRQ_IL2SD(0));
+ irq_write(REG_IRQ_IL2MSD(0), status);
+
+ /* handle each child */
+ while (status) {
+
+ /* any IRQ for this child bit ? */
+ if ((status & 0x1) == 0)
+ goto next;
+
+ /* get child if any and run handler */
+ child = parent->child[i];
+ if (child && child->handler) {
+ child->handler(child->handler_arg);
+
+ /* unmask this bit i interrupt */
+ irq_write(REG_IRQ_IL2MCD(0), 0x1 << i);
+ } else {
+ /* nobody cared ? */
+ trace_irq_error("nbc");
+ }
+
+next:
+ status >>= 1;
+ i++;
+ }
+
+ /* clear parent and unmask */
+ arch_interrupt_clear(IRQ_NUM_EXT_LEVEL2);
+ arch_interrupt_enable_mask(1 << IRQ_NUM_EXT_LEVEL2);
+}
+
+static void parent_level3_handler(void *data)
+{
+ struct irq_parent *parent = (struct irq_parent *)data;
+ struct irq_child * child = NULL;
+ uint32_t status;
+ uint32_t i = 0;
+
+ /* mask the parent IRQ */
+ arch_interrupt_disable_mask(1 << IRQ_NUM_EXT_LEVEL3);
+
+ /* mask all child interrupts */
+ status = irq_read(REG_IRQ_IL3SD(0));
+ irq_write(REG_IRQ_IL3MSD(0), status);
+
+ /* handle each child */
+ while (status) {
+
+ /* any IRQ for this child bit ? */
+ if ((status & 0x1) == 0)
+ goto next;
+
+ /* get child if any and run handler */
+ child = parent->child[i];
+ if (child && child->handler) {
+ child->handler(child->handler_arg);
+
+ /* unmask this bit i interrupt */
+ irq_write(REG_IRQ_IL3MCD(0), 0x1 << i);
+ } else {
+ /* nobody cared ? */
+ trace_irq_error("nbc");
+ }
+
+next:
+ status >>= 1;
+ i++;
+ }
+
+ /* clear parent and unmask */
+ arch_interrupt_clear(IRQ_NUM_EXT_LEVEL3);
+ arch_interrupt_enable_mask(1 << IRQ_NUM_EXT_LEVEL3);
+}
+
+static void parent_level4_handler(void *data)
+{
+ struct irq_parent *parent = (struct irq_parent *)data;
+ struct irq_child * child = NULL;
+ uint32_t status;
+ uint32_t i = 0;
+
+ /* mask the parent IRQ */
+ arch_interrupt_disable_mask(1 << IRQ_NUM_EXT_LEVEL4);
+
+ /* mask all child interrupts */
+ status = irq_read(REG_IRQ_IL4SD(0));
+ irq_write(REG_IRQ_IL4MSD(0), status);
+
+ /* handle each child */
+ while (status) {
+
+ /* any IRQ for this child bit ? */
+ if ((status & 0x1) == 0)
+ goto next;
+
+ /* get child if any and run handler */
+ child = parent->child[i];
+ if (child && child->handler) {
+ child->handler(child->handler_arg);
+
+ /* unmask this bit i interrupt */
+ irq_write(REG_IRQ_IL4MCD(0), 0x1 << i);
+ } else {
+ /* nobody cared ? */
+ trace_irq_error("nbc");
+ }
+
+next:
+ status >>= 1;
+ i++;
+ }
+
+ /* clear parent and unmask */
+ arch_interrupt_clear(IRQ_NUM_EXT_LEVEL4);
+ arch_interrupt_enable_mask(1 << IRQ_NUM_EXT_LEVEL4);
+}
+
+static void parent_level5_handler(void *data)
+{
+ struct irq_parent *parent = (struct irq_parent *)data;
+ struct irq_child * child = NULL;
+ uint32_t status;
+ uint32_t i = 0;
+
+ /* mask the parent IRQ */
+ arch_interrupt_disable_mask(1 << IRQ_NUM_EXT_LEVEL5);
+
+ /* mask all child interrupts */
+ status = irq_read(REG_IRQ_IL5SD(0));
+ irq_write(REG_IRQ_IL5MSD(0), status);
+
+ /* handle each child */
+ while (status) {
+
+ /* any IRQ for this child bit ? */
+ if ((status & 0x1) == 0)
+ goto next;
+
+ /* get child if any and run handler */
+ child = parent->child[i];
+ if (child && child->handler) {
+ child->handler(child->handler_arg);
+
+ /* unmask this bit i interrupt */
+ irq_write(REG_IRQ_IL5MCD(0), 0x1 << i);
+ } else {
+ /* nobody cared ? */
+ trace_irq_error("nbc");
+ }
+
+next:
+ status >>= 1;
+ i++;
+ }
+
+ /* clear parent and unmask */
+ arch_interrupt_clear(IRQ_NUM_EXT_LEVEL5);
+ arch_interrupt_enable_mask(1 << IRQ_NUM_EXT_LEVEL5);
+}
+
+/* DSP internal interrupts */
+static struct irq_parent dsp_irq[4] = {
+ {IRQ_NUM_EXT_LEVEL2, parent_level2_handler, },
+ {IRQ_NUM_EXT_LEVEL3, parent_level3_handler, },
+ {IRQ_NUM_EXT_LEVEL4, parent_level4_handler, },
+ {IRQ_NUM_EXT_LEVEL5, parent_level5_handler, },
+};
+
+struct irq_parent *platform_irq_get_parent(uint32_t irq)
+{
+ switch (REEF_IRQ_NUMBER(irq)) {
+ case IRQ_NUM_EXT_LEVEL2:
+ return &dsp_irq[0];
+ case IRQ_NUM_EXT_LEVEL3:
+ return &dsp_irq[1];
+ case IRQ_NUM_EXT_LEVEL4:
+ return &dsp_irq[2];
+ case IRQ_NUM_EXT_LEVEL5:
+ return &dsp_irq[3];
+ default:
+ return NULL;
+ }
+}
+
+uint32_t platform_interrupt_get_enabled(void)
+{
+ return 0;
+}
+
+void platform_interrupt_mask(uint32_t irq, uint32_t mask)
+{
+ /* mask external interrupt bit */
+ switch (REEF_IRQ_NUMBER(irq)) {
+ case IRQ_NUM_EXT_LEVEL5:
+ irq_write(REG_IRQ_IL5MSD(0), 1 << REEF_IRQ_BIT(irq));
+ break;
+ case IRQ_NUM_EXT_LEVEL4:
+ irq_write(REG_IRQ_IL4MSD(0), 1 << REEF_IRQ_BIT(irq));
+ break;
+ case IRQ_NUM_EXT_LEVEL3:
+ irq_write(REG_IRQ_IL3MSD(0), 1 << REEF_IRQ_BIT(irq));
+ break;
+ case IRQ_NUM_EXT_LEVEL2:
+ irq_write(REG_IRQ_IL2MSD(0), 1 << REEF_IRQ_BIT(irq));
+ break;
+ default:
+ break;
+ }
+
+}
+
+void platform_interrupt_unmask(uint32_t irq, uint32_t mask)
+{
+ /* unmask external interrupt bit */
+ switch (REEF_IRQ_NUMBER(irq)) {
+ case IRQ_NUM_EXT_LEVEL5:
+ irq_write(REG_IRQ_IL5MCD(0), 1 << REEF_IRQ_BIT(irq));
+ break;
+ case IRQ_NUM_EXT_LEVEL4:
+ irq_write(REG_IRQ_IL4MCD(0), 1 << REEF_IRQ_BIT(irq));
+ break;
+ case IRQ_NUM_EXT_LEVEL3:
+ irq_write(REG_IRQ_IL3MCD(0), 1 << REEF_IRQ_BIT(irq));
+ break;
+ case IRQ_NUM_EXT_LEVEL2:
+ irq_write(REG_IRQ_IL2MCD(0), 1 << REEF_IRQ_BIT(irq));
+ break;
+ default:
+ break;
+ }
+
+}
+
+void platform_interrupt_clear(uint32_t irq, uint32_t mask)
+{
+}
+
+void platform_interrupt_init(void)
+{
+ int i;
+
+ /* mask all external IRQs by default */
+ irq_write(REG_IRQ_IL2MSD(0), REG_IRQ_IL2MD_ALL);
+ irq_write(REG_IRQ_IL3MSD(0), REG_IRQ_IL3MD_ALL);
+ irq_write(REG_IRQ_IL4MSD(0), REG_IRQ_IL4MD_ALL);
+ irq_write(REG_IRQ_IL5MSD(0), REG_IRQ_IL5MD_ALL);
+
+ for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) {
+ spinlock_init(&dsp_irq[i].lock);
+ }
+}
diff --git a/src/platform/cannonlake/platform.c b/src/platform/cannonlake/platform.c
new file mode 100644
index 0000000..729364f
--- /dev/null
+++ b/src/platform/cannonlake/platform.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ * Keyon Jie <yang.jie at linux.intel.com>
+ * Rander Wang <rander.wang at intel.com>
+ */
+
+#include <platform/memory.h>
+#include <platform/mailbox.h>
+#include <platform/shim.h>
+#include <platform/dma.h>
+#include <platform/clk.h>
+#include <platform/timer.h>
+#include <platform/interrupt.h>
+#include <uapi/ipc.h>
+#include <reef/mailbox.h>
+#include <reef/dai.h>
+#include <reef/dma.h>
+#include <reef/reef.h>
+#include <reef/work.h>
+#include <reef/clock.h>
+#include <reef/ipc.h>
+#include <reef/agent.h>
+#include <reef/io.h>
+#include <reef/trace.h>
+#include <reef/audio/component.h>
+#include <config.h>
+#include <string.h>
+#include <version.h>
+
+static const struct sof_ipc_fw_ready ready = {
+ .hdr = {
+ .cmd = SOF_IPC_FW_READY,
+ .size = sizeof(struct sof_ipc_fw_ready),
+ },
+ .version = {
+ .build = REEF_BUILD,
+ .minor = REEF_MINOR,
+ .major = REEF_MAJOR,
+ .date = __DATE__,
+ .time = __TIME__,
+ .tag = REEF_TAG,
+ },
+};
+
+#define SRAM_WINDOW_HOST_OFFSET(x) (0x80000 + x * 0x20000)
+
+#define NUM_CNL_WINDOWS 5
+
+static const struct sof_ipc_window sram_window = {
+ .ext_hdr = {
+ .hdr.cmd = SOF_IPC_FW_READY,
+ .hdr.size = sizeof(struct sof_ipc_window) +
+ sizeof(struct sof_ipc_window_elem) * NUM_CNL_WINDOWS,
+ .type = SOF_IPC_EXT_WINDOW,
+ },
+ .num_windows = NUM_CNL_WINDOWS,
+ .window[0] = {
+ .type = SOF_IPC_REGION_REGS,
+ .id = 0, /* map to host window 0 */
+ .flags = 0, // TODO: set later
+ .size = MAILBOX_SW_REG_SIZE,
+ .offset = 0,
+ },
+ .window[1] = {
+ .type = SOF_IPC_REGION_UPBOX,
+ .id = 0, /* map to host window 0 */
+ .flags = 0, // TODO: set later
+ .size = MAILBOX_DSPBOX_SIZE,
+ .offset = MAILBOX_SW_REG_SIZE,
+ },
+ .window[2] = {
+ .type = SOF_IPC_REGION_DOWNBOX,
+ .id = 1, /* map to host window 1 */
+ .flags = 0, // TODO: set later
+ .size = MAILBOX_HOSTBOX_SIZE,
+ .offset = 0,
+ },
+ .window[3] = {
+ .type = SOF_IPC_REGION_DEBUG,
+ .id = 2, /* map to host window 2 */
+ .flags = 0, // TODO: set later
+ .size = SRAM_DEBUG_SIZE,
+ .offset = 0,
+ },
+ .window[4] = {
+ .type = SOF_IPC_REGION_TRACE,
+ .id = 3, /* map to host window 3 */
+ .flags = 0, // TODO: set later
+ .size = MAILBOX_TRACE_SIZE,
+ .offset = 0,
+ },
+
+};
+
+static struct work_queue_timesource platform_generic_queue = {
+ .timer = {
+ .id = TIMER3, /* external timer */
+ .irq = IRQ_EXT_TSTAMP0_LVL2(0),
+ },
+ .clk = CLK_CPU,
+ .notifier = NOTIFIER_ID_CPU_FREQ,
+ .timer_set = platform_timer_set,
+ .timer_clear = platform_timer_clear,
+ .timer_get = platform_timer_get,
+};
+
+struct timer *platform_timer = &platform_generic_queue.timer;
+
+int platform_boot_complete(uint32_t boot_message)
+{
+ mailbox_dspbox_write(0, &ready, sizeof(ready));
+ mailbox_dspbox_write(sizeof(ready), &sram_window,
+ sram_window.ext_hdr.hdr.size);
+
+ /* boot now complete so we can relax the CPU */
+ clock_set_freq(CLK_CPU, CLK_DEFAULT_CPU_HZ);
+
+ /* tell host we are ready */
+ ipc_write(IPC_DIPCIDD, SRAM_WINDOW_HOST_OFFSET(0) >> 12);
+ ipc_write(IPC_DIPCIDR, 0x80000000 | SOF_IPC_FW_READY);
+
+ return 0;
+}
+
+static void platform_memory_windows_init(void)
+{
+ /* window0, for fw status & outbox/uplink mbox */
+ io_reg_write(DMWLO(0), HP_SRAM_WIN0_SIZE | 0x7);
+ io_reg_write(DMWBA(0), HP_SRAM_WIN0_BASE
+ | DMWBA_READONLY | DMWBA_ENABLE);
+
+ /* window1, for inbox/downlink mbox */
+ io_reg_write(DMWLO(1), HP_SRAM_WIN1_SIZE | 0x7);
+ io_reg_write(DMWBA(1), HP_SRAM_WIN1_BASE
+ | DMWBA_ENABLE);
+
+ /* window2, for debug */
+ io_reg_write(DMWLO(2), HP_SRAM_WIN2_SIZE | 0x7);
+ io_reg_write(DMWBA(2), HP_SRAM_WIN2_BASE
+ | DMWBA_READONLY | DMWBA_ENABLE);
+
+ /* window3, for trace */
+ io_reg_write(DMWLO(3), HP_SRAM_WIN3_SIZE | 0x7);
+ io_reg_write(DMWBA(3), HP_SRAM_WIN3_BASE
+ | DMWBA_READONLY | DMWBA_ENABLE);
+}
+
+/* init HW */
+static void platform_init_hw(void)
+{
+ io_reg_write(DSP_INIT_GENO,
+ GENO_MDIVOSEL | GENO_DIOPTOSEL);
+
+ io_reg_write(DSP_INIT_IOPO,
+ IOPO_DMIC_FLAG |IOPO_I2S_FLAG);
+
+ io_reg_write(DSP_INIT_ALHO,
+ ALHO_ASO_FLAG | ALHO_CSO_FLAG | ALHO_CFO_FLAG);
+
+ io_reg_write(DSP_INIT_LPGPDMA(0),
+ LPGPDMA_CHOSEL_FLAG | LPGPDMA_CTLOSEL_FLAG);
+ io_reg_write(DSP_INIT_LPGPDMA(1),
+ LPGPDMA_CHOSEL_FLAG | LPGPDMA_CTLOSEL_FLAG);
+}
+
+static struct timer platform_ext_timer = {
+ .id = TIMER3,
+ .irq = IRQ_EXT_TSTAMP0_LVL2(0),
+};
+
+int platform_init(struct reef *reef)
+{
+ struct dma *dmac0;
+ struct dma *dmac1;
+ struct dai *ssp;
+ int i;
+
+ trace_point(TRACE_BOOT_PLATFORM_ENTRY);
+ platform_init_hw();
+
+ platform_interrupt_init();
+
+ trace_point(TRACE_BOOT_PLATFORM_MBOX);
+ platform_memory_windows_init();
+
+ trace_point(TRACE_BOOT_PLATFORM_SHIM);
+
+ /* init work queues and clocks */
+ trace_point(TRACE_BOOT_PLATFORM_TIMER);
+ platform_timer_start(&platform_ext_timer);
+
+ trace_point(TRACE_BOOT_PLATFORM_CLOCK);
+ init_platform_clocks();
+
+ trace_point(TRACE_BOOT_SYS_WORK);
+ init_system_workq(&platform_generic_queue);
+
+ /* init the system agent */
+ sa_init(reef);
+
+ /* Set CPU to default frequency for booting */
+ trace_point(TRACE_BOOT_SYS_CPU_FREQ);
+ clock_set_freq(CLK_CPU, CLK_MAX_CPU_HZ);
+
+ /* set SSP clock to 25M */
+ trace_point(TRACE_BOOT_PLATFORM_SSP_FREQ);
+ clock_set_freq(CLK_SSP, 25000000);
+
+ /* initialise the host IPC mechanisms */
+ trace_point(TRACE_BOOT_PLATFORM_IPC);
+ ipc_init(reef);
+
+ /* prevent Core0 clock gating. */
+ shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) |
+ SHIM_CLKCTL_TCPLCG(0));
+
+ /* prevent LP GPDMA 0&1 clock gating */
+ io_reg_write(GPDMA_CLKCTL(0), GPDMA_FDCGB);
+ io_reg_write(GPDMA_CLKCTL(1), GPDMA_FDCGB);
+
+ /* prevent DSP Common power gating */
+ shim_write16(SHIM_PWRCTL, SHIM_PWRCTL_TCPDSP0PG);
+
+ /* init DMACs */
+ trace_point(TRACE_BOOT_PLATFORM_DMA);
+ dmac0 = dma_get(DMA_GP_LP_DMAC0);
+ if (dmac0 == NULL)
+ return -ENODEV;
+ dma_probe(dmac0);
+
+ dmac1 = dma_get(DMA_GP_LP_DMAC1);
+ if (dmac1 == NULL)
+ return -ENODEV;
+ dma_probe(dmac1);
+
+ /* init SSP ports */
+ trace_point(TRACE_BOOT_PLATFORM_SSP);
+ for(i = 0; i < PLATFORM_SSP_COUNT; i++) {
+ ssp = dai_get(SOF_DAI_INTEL_SSP, i);
+ if (ssp == NULL)
+ return -ENODEV;
+ dai_probe(ssp);
+ }
+
+ return 0;
+}
diff --git a/src/platform/cannonlake/timer.c b/src/platform/cannonlake/timer.c
new file mode 100644
index 0000000..d2ee870
--- /dev/null
+++ b/src/platform/cannonlake/timer.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ * Keyon Jie <yang.jie at linux.intel.com>
+ * Rander Wang <rander.wang at intel.com>
+ */
+
+#include <platform/timer.h>
+#include <platform/shim.h>
+#include <reef/debug.h>
+#include <reef/audio/component.h>
+#include <stdint.h>
+
+void platform_timer_start(struct timer *timer)
+{
+ /* run timer */
+ shim_write64(SHIM_DSPWCT0C, 0);
+ shim_write(SHIM_DSPWCTCS,
+ shim_read(SHIM_DSPWCTCS) | SHIM_DSPWCTCS_T0A);
+}
+
+void platform_timer_stop(struct timer *timer)
+{
+ /* stop timer */
+ shim_write64(SHIM_DSPWCT0C, 0);
+ shim_write(SHIM_DSPWCTCS,
+ shim_read(SHIM_DSPWCTCS) & ~SHIM_DSPWCTCS_T0A);
+}
+
+int platform_timer_set(struct timer *timer, uint64_t ticks)
+{
+ /* a tick value of 0 will not generate an IRQ */
+ if (ticks == 0)
+ ticks = 1;
+
+ /* set new value and run */
+ shim_write64(SHIM_DSPWCT0C, ticks);
+ shim_write(SHIM_DSPWCTCS,
+ shim_read(SHIM_DSPWCTCS) | SHIM_DSPWCTCS_T0A);
+
+ return 0;
+}
+
+void platform_timer_clear(struct timer *timer)
+{
+ /* write 1 to clear the timer interrupt */
+ shim_write(SHIM_DSPWCTCS,
+ shim_read(SHIM_DSPWCTCS) | SHIM_DSPWCTCS_T0T);
+}
+
+uint64_t platform_timer_get(struct timer *timer)
+{
+// return arch_timer_get_system(timer);
+ return (uint64_t)shim_read64(SHIM_DSPWC);
+}
+
+/* get timestamp for host stream DMA position */
+void platform_host_timestamp(struct comp_dev *host,
+ struct sof_ipc_stream_posn *posn)
+{
+ int err;
+
+ /* get host postion */
+ err = comp_position(host, posn);
+ if (err == 0)
+ posn->flags |= SOF_TIME_HOST_VALID;
+}
+
+/* get timestamp for DAI stream DMA position */
+void platform_dai_timestamp(struct comp_dev *dai,
+ struct sof_ipc_stream_posn *posn)
+{
+ int err;
+
+ /* get DAI postion */
+ err = comp_position(dai, posn);
+ if (err == 0)
+ posn->flags |= SOF_TIME_DAI_VALID;
+
+ /* get SSP wallclock - DAI sets this to stream start value */
+ posn->wallclock = shim_read64(SHIM_DSPWC) - posn->wallclock;
+ posn->flags |= SOF_TIME_WALL_VALID;
+}
+
+/* get current wallclock for componnent */
+void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock)
+{
+ *wallclock = shim_read64(SHIM_DSPWC);
+}
+
+int platform_timer_register(struct timer *timer,
+ void (*handler)(void *arg), void *arg)
+{
+ return interrupt_register(timer->irq, handler, arg);
+}
+
+int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg)
+{
+ switch (timer->id) {
+ case TIMER0:
+ case TIMER1:
+ case TIMER2:
+ return arch_timer_register(timer, handler, arg);
+ case TIMER3:
+ return platform_timer_register(timer, handler, arg);
+ default:
+ return -EINVAL;
+ }
+}
--
2.14.1
More information about the Sound-open-firmware
mailing list