[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,
+			&notify_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,
+			&notify_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