![](https://secure.gravatar.com/avatar/24e6a8158be3c9b52253d878d1487123.jpg?s=120&d=mm&r=g)
Add platform support drivers an initialisation for Haswell and Broadwell.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/platform/haswell/Makefile.am | 16 ++ src/platform/haswell/broadwell.x.in | 508 ++++++++++++++++++++++++++++++++++++ src/platform/haswell/clk.c | 210 +++++++++++++++ src/platform/haswell/dai.c | 89 +++++++ src/platform/haswell/dma.c | 137 ++++++++++ src/platform/haswell/haswell.x.in | 508 ++++++++++++++++++++++++++++++++++++ src/platform/haswell/platform.c | 249 ++++++++++++++++++ src/platform/haswell/timer.c | 105 ++++++++ 8 files changed, 1822 insertions(+) create mode 100644 src/platform/haswell/Makefile.am create mode 100755 src/platform/haswell/broadwell.x.in create mode 100644 src/platform/haswell/clk.c create mode 100644 src/platform/haswell/dai.c create mode 100644 src/platform/haswell/dma.c create mode 100755 src/platform/haswell/haswell.x.in create mode 100644 src/platform/haswell/platform.c create mode 100644 src/platform/haswell/timer.c
diff --git a/src/platform/haswell/Makefile.am b/src/platform/haswell/Makefile.am new file mode 100644 index 0000000..bf9d40a --- /dev/null +++ b/src/platform/haswell/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = include + +noinst_LIBRARIES = libplatform.a + +libplatform_a_SOURCES = \ + platform.c \ + dai.c \ + dma.c \ + clk.c \ + timer.c + +libplatform_a_CFLAGS = \ + $(ARCH_CFLAGS) \ + $(ARCH_INCDIR) \ + $(REEF_INCDIR) \ + $(PLATFORM_INCDIR) diff --git a/src/platform/haswell/broadwell.x.in b/src/platform/haswell/broadwell.x.in new file mode 100755 index 0000000..51a573c --- /dev/null +++ b/src/platform/haswell/broadwell.x.in @@ -0,0 +1,508 @@ +/* + * Linker Script for Broadwell. + * + * 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_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 = XCHAL_NMI_VECTOR_VADDR + REEF_MEM_VECT_SIZE, + len = (IRAM_BASE + IRAM_SIZE) - (XCHAL_NMI_VECTOR_VADDR + REEF_MEM_VECT_SIZE) + reef_data_ro : + org = DRAM0_BASE, + len = REEF_MEM_RO_SIZE + reef_data : + org = DRAM0_BASE + REEF_MEM_RO_SIZE, + len = HEAP_SYSTEM_BASE - (DRAM0_BASE + REEF_MEM_RO_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_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_int6_text_phdr PT_LOAD; + vector_int6_lit_phdr PT_LOAD; + vector_int7_text_phdr PT_LOAD; + vector_int7_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + reef_text_start_phdr PT_LOAD; + reef_data_ro_phdr PT_LOAD; + reef_data_phdr PT_LOAD; + reef_data_bss_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(_ResetVector) +_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 + + .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 + + .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_start :reef_text_start_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >reef_data_ro :reef_data_ro_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_data :reef_data_bss_phdr + + /* stack */ + _end = REEF_STACK_END; + PROVIDE(end = REEF_STACK_END); + _stack_sentry = REEF_STACK_END; + __stack = REEF_STACK_BASE; + + .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/haswell/clk.c b/src/platform/haswell/clk.c new file mode 100644 index 0000000..0d4449d --- /dev/null +++ b/src/platform/haswell/clk.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2016, 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@linux.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 fabric; + uint32_t enc; +}; + +static struct clk_pdata *clk_pdata; + +/* increasing frequency order */ +static const struct freq_table cpu_freq[] = { + {32000000, 80, 32000000, 0x6}, + {80000000, 80, 80000000, 0x2}, + {160000000, 160, 80000000, 0x1}, + {320000000, 320, 160000000, 0x4},/* default */ + {320000000, 320, 80000000, 0x0}, + {160000000, 160, 160000000, 0x5}, +}; + +static const struct freq_table ssp_freq[] = { + {24000000, 24, 0, 0}, /* default */ +}; + +#define CPU_DEFAULT_IDX 3 +#define SSP_DEFAULT_IDX 0 + +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 chaining 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_CSR, + SHIM_CSR_DCS_MASK, + SHIM_CSR_DCS(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_SYS, 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/haswell/dai.c b/src/platform/haswell/dai.c new file mode 100644 index 0000000..4a05e6a --- /dev/null +++ b/src/platform/haswell/dai.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016, 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@linux.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[2] = { +{ + .type = SOF_DAI_INTEL_SSP, + .index = 0, + .plat_data = { + .base = SSP0_BASE, + .irq = IRQ_NUM_EXT_SSP0, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SSP0_BASE + SSDR, + .handshake = DMA_HANDSHAKE_SSP0_TX, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SSP0_BASE + SSDR, + .handshake = DMA_HANDSHAKE_SSP0_RX, + } + }, + .ops = &ssp_ops, +}, +{ + .type = SOF_DAI_INTEL_SSP, + .index = 1, + .plat_data = { + .base = SSP1_BASE, + .irq = IRQ_NUM_EXT_SSP1, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SSP1_BASE + SSDR, + .handshake = DMA_HANDSHAKE_SSP1_TX, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SSP1_BASE + SSDR, + .handshake = DMA_HANDSHAKE_SSP1_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/haswell/dma.c b/src/platform/haswell/dma.c new file mode 100644 index 0000000..92cd5db --- /dev/null +++ b/src/platform/haswell/dma.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016, 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@linux.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[] = { +{ + .plat_data = { + .base = DMA0_BASE, + .irq = IRQ_NUM_EXT_DMAC0, + .drv_plat_data = &dmac0, + }, + .ops = &dw_dma_ops, +}, +{ + .plat_data = { + .base = DMA1_BASE, + .irq = IRQ_NUM_EXT_DMAC1, + .drv_plat_data = &dmac1, + }, + .ops = &dw_dma_ops, +},}; + +struct dma *dma_get(int dmac_id) +{ + switch (dmac_id) { + case DMA_ID_DMAC0: + return &dma[0]; + case DMA_ID_DMAC1: + return &dma[1]; + default: + return NULL; + } +} diff --git a/src/platform/haswell/haswell.x.in b/src/platform/haswell/haswell.x.in new file mode 100755 index 0000000..add3eed --- /dev/null +++ b/src/platform/haswell/haswell.x.in @@ -0,0 +1,508 @@ +/* + * Linker Script for Baytrail. + * + * 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_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 = XCHAL_NMI_VECTOR_VADDR + REEF_MEM_VECT_SIZE, + len = (IRAM_BASE + IRAM_SIZE) - (XCHAL_NMI_VECTOR_VADDR + REEF_MEM_VECT_SIZE) + reef_data_ro : + org = DRAM0_BASE, + len = REEF_MEM_RO_SIZE + reef_data : + org = DRAM0_BASE + REEF_MEM_RO_SIZE, + len = HEAP_SYSTEM_BASE - (DRAM0_BASE + REEF_MEM_RO_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_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_int6_text_phdr PT_LOAD; + vector_int6_lit_phdr PT_LOAD; + vector_int7_text_phdr PT_LOAD; + vector_int7_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + reef_text_start_phdr PT_LOAD; + reef_data_ro_phdr PT_LOAD; + reef_data_phdr PT_LOAD; + reef_data_bss_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(_ResetVector) +_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 + + .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 + + .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_start :reef_text_start_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >reef_data_ro :reef_data_ro_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_data :reef_data_bss_phdr + + /* stack */ + _end = REEF_STACK_END; + PROVIDE(end = REEF_STACK_END); + _stack_sentry = REEF_STACK_END; + __stack = REEF_STACK_BASE; + + .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/haswell/platform.c b/src/platform/haswell/platform.c new file mode 100644 index 0000000..89afb8e --- /dev/null +++ b/src/platform/haswell/platform.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2016, 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@linux.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/pmc.h> +#include <uapi/ipc.h> +#include <reef/mailbox.h> +#include <reef/dai.h> +#include <reef/dma.h> +#include <reef/interrupt.h> +#include <reef/reef.h> +#include <reef/work.h> +#include <reef/clock.h> +#include <reef/ipc.h> +#include <reef/trace.h> +#include <reef/agent.h> +#include <reef/io.h> +#include <reef/dma-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), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .dspbox_offset = MAILBOX_HOST_OFFSET + MAILBOX_DSPBOX_OFFSET, + .hostbox_offset = MAILBOX_HOST_OFFSET + MAILBOX_HOSTBOX_OFFSET, + .dspbox_size = MAILBOX_DSPBOX_SIZE, + .hostbox_size = MAILBOX_HOSTBOX_SIZE, + .version = { + .build = REEF_BUILD, + .minor = REEF_MINOR, + .major = REEF_MAJOR, + .date = __DATE__, + .time = __TIME__, + .tag = REEF_TAG, + }, + /* TODO: add capabilities */ +}; + +static struct work_queue_timesource platform_generic_queue = { + .timer = { + .id = TIMER0, /* external timer using SSP */ + .irq = IRQ_NUM_TIMER1, + }, + .clk = CLK_CPU, + .notifier = NOTIFIER_ID_CPU_FREQ, + .timer_set = arch_timer_set, + .timer_clear = arch_timer_clear, + .timer_get = arch_timer_get_system, +}; + +struct timer *platform_timer = &platform_generic_queue.timer; + +int platform_boot_complete(uint32_t boot_message) +{ + uint64_t outbox = MAILBOX_HOST_OFFSET >> 3; + + mailbox_dspbox_write(0, &ready, sizeof(ready)); + + /* now interrupt host to tell it we are done booting */ + shim_write(SHIM_IPCD, outbox | SHIM_IPCD_BUSY); + + /* boot now complete so we can relax the CPU */ + clock_set_freq(CLK_CPU, CLK_DEFAULT_CPU_HZ); + + return 0; +} + +void platform_interrupt_set(int irq) +{ + arch_interrupt_set(irq); +} + +/* clear mask in PISR, bits are W1C in docs but some bits need preserved ?? */ +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + switch (irq) { + case IRQ_NUM_EXT_DMAC0: + case IRQ_NUM_EXT_DMAC1: + case IRQ_NUM_EXT_SSP0: + case IRQ_NUM_EXT_SSP1: + interrupt_clear(irq); + break; + default: + break; + } +} + +/* TODO: expand this to 64 bit - should we just return mask of IRQ numbers */ +uint32_t platform_interrupt_get_enabled(void) +{ + return shim_read(SHIM_IMRD); +} + +void platform_interrupt_mask(uint32_t irq, uint32_t mask) +{ + switch (irq) { + case IRQ_NUM_EXT_SSP0: + shim_write(SHIM_IMRD, SHIM_IMRD_SSP0); + break; + case IRQ_NUM_EXT_SSP1: + shim_write(SHIM_IMRD, SHIM_IMRD_SSP1); + break; + case IRQ_NUM_EXT_DMAC0: + shim_write(SHIM_IMRD, SHIM_IMRD_DMAC0); + break; + case IRQ_NUM_EXT_DMAC1: + shim_write(SHIM_IMRD, SHIM_IMRD_DMAC1); + break; + default: + break; + } +} + +void platform_interrupt_unmask(uint32_t irq, uint32_t mask) +{ + switch (irq) { + case IRQ_NUM_EXT_SSP0: + shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_SSP0); + break; + case IRQ_NUM_EXT_SSP1: + shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_SSP1); + break; + case IRQ_NUM_EXT_DMAC0: + shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DMAC0); + break; + case IRQ_NUM_EXT_DMAC1: + shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DMAC1); + break; + default: + break; + } +} + +int platform_init(struct reef *reef) +{ + struct dma *dmac0; + struct dma *dmac1; + struct dai *ssp0; + struct dai *ssp1; + + trace_point(TRACE_BOOT_PLATFORM_MBOX); + + /* clear mailbox for early trace and debug */ + bzero((void*)MAILBOX_BASE, IPC_MAX_MAILBOX_BYTES); + + trace_point(TRACE_BOOT_PLATFORM_SHIM); + + /* init work queues and clocks */ + trace_point(TRACE_BOOT_SYS_WORK); + init_system_workq(&platform_generic_queue); + + trace_point(TRACE_BOOT_PLATFORM_TIMER); + platform_timer_start(platform_timer); + + trace_point(TRACE_BOOT_PLATFORM_CLOCK); + init_platform_clocks(); + + /* 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); + + dma_trace_init_early(&reef->ipc->dmat); + + /* init DMACs */ + trace_point(TRACE_BOOT_PLATFORM_DMA); + dmac0 = dma_get(DMA_ID_DMAC0); + if (dmac0 == NULL) + return -ENODEV; + dma_probe(dmac0); + + /* clear the masks for dsp of the dmac*/ + io_reg_update_bits(SHIM_BASE + SHIM_IMRD, + SHIM_IMRD_DMAC0, 0); + + dmac1 = dma_get(DMA_ID_DMAC1); + if (dmac1 == NULL) + return -ENODEV; + dma_probe(dmac1); + + /* clear the masks for dsp of the dmac*/ + io_reg_update_bits(SHIM_BASE + SHIM_IMRD, + SHIM_IMRD_DMAC1, 0); + + /* init SSP ports */ + trace_point(TRACE_BOOT_PLATFORM_SSP); + ssp0 = dai_get(SOF_DAI_INTEL_SSP, 0); + if (ssp0 == NULL) + return -ENODEV; + dai_probe(ssp0); + + ssp1 = dai_get(SOF_DAI_INTEL_SSP, 1); + if (ssp1 == NULL) + return -ENODEV; + dai_probe(ssp1); + + /* Initialize DMA for Trace*/ + dma_trace_init_complete(&reef->ipc->dmat); + + return 0; +} diff --git a/src/platform/haswell/timer.c b/src/platform/haswell/timer.c new file mode 100644 index 0000000..bb74330 --- /dev/null +++ b/src/platform/haswell/timer.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, 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@linux.intel.com + */ + +#include <platform/timer.h> +#include <platform/shim.h> +#include <platform/interrupt.h> +#include <reef/debug.h> +#include <reef/audio/component.h> +#include <stdint.h> + +void platform_timer_start(struct timer *timer) +{ +} + +void platform_timer_stop(struct timer *timer) +{ +} + +int platform_timer_set(struct timer *timer, uint64_t ticks) +{ + return 0; +} + +void platform_timer_clear(struct timer *timer) +{ +} + +uint64_t platform_timer_get(struct timer *timer) +{ + return 0; +} + +/* 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 | SOF_TIME_HOST_64; +} + +/* 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 = timer_get_system(platform_timer) - posn->wallclock; + posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64; +} + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + /* only 1 wallclock on HSW */ + *wallclock = timer_get_system(platform_timer); +} + +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); + default: + return -EINVAL; + } +}