1/*******************************************************************************
2 * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * MPFS HAL Embedded Software
7 *
8 */
9/*******************************************************************************
10 *
11 * file name : mpfs-ddr-e51.ld
12 * Use this linker script when the program is fully located in DDR. The
13 * assumption is DDR has already been initialized by another program.
14 * This linker script can be used with a debugger or when compiled and loaded
15 * by a boot-loader.
16 * Please see the project mpfs-hal-run-from-ddr-1 located in the Bare Metal
17 * library under examples/mpfs-hal for an example of it use.
18 * https://github.com/polarfire-soc/polarfire-soc-bare-metal-library
19 *
20 * You can find details on the PolarFireSoC Memory map in the mpfs-memory-hierarchy.md
21 * which can be found under the link below:
22 * https://github.com/polarfire-soc/polarfire-soc-documentation
23 *
24 */
25
26OUTPUT_ARCH( "riscv" )
27ENTRY(_start)
28
29/*-----------------------------------------------------------------------------
30
31-- MSS hart Reset vector
32
33The MSS reset vector for each hart is stored securely in the MPFS.
34The most common usage will be where the reset vector for each hart will be set
35to the start of the envm at address 0x2022_0100, giving 128K-256B of contiguous
36non-volatile storage. Normally this is where the initial boot-loader will
37reside. (Note: The first 256B page of envm is used for metadata associated with
38secure boot. When not using secure boot (mode 0,1), this area is still reserved
39by convention. It allows easier transition from non-secure to secure boot flow
40during the development process.
41When debugging a bare metal program that is run out of reset from envm, a linker
42script will be used whereby the program will run from LIM instead of envm.
43In this case, the reset vector in the linker script is normally set to the
44start of LIM, 0x0800_0000.
45This means you are not continually programming the envm each time you load a
46program and there is no limitation with break points when debugging.
47See the mpfs-lim.ld example linker script when runing from LIM.
48
49------------------------------------------------------------------------------*/
50
51MEMORY
52{
53    /* In this example, our reset vector is set to point to the */
54    /* start at page 1 of the envm */
55    envm (rx) : ORIGIN  = 0x20220100, LENGTH = 128k - 0x100
56    dtim (rwx) : ORIGIN  = 0x01000000, LENGTH = 7k
57    e51_itim (rwx)     : ORIGIN = 0x01800000, LENGTH = 28k
58    u54_1_itim (rwx)   : ORIGIN = 0x01808000, LENGTH = 28k
59    u54_2_itim (rwx)   : ORIGIN = 0x01810000, LENGTH = 28k
60    u54_3_itim (rwx)   : ORIGIN = 0x01818000, LENGTH = 28k
61    u54_4_itim (rwx)   : ORIGIN = 0x01820000, LENGTH = 28k
62    l2lim (rwx)        : ORIGIN = 0x08000000, LENGTH = 256k
63    scratchpad(rwx)    : ORIGIN = 0x0A000000, LENGTH = 256k
64    /* This 1K of DTIM is used to run code when switching the envm clock */
65    switch_code_dtim (rx) : ORIGIN = 0x01001c00, LENGTH = 1k
66    /* DDR sections example */
67    ddr_cached_32bit (rwx) : ORIGIN  = 0x80000000, LENGTH = 768M
68    ddr_non_cached_32bit (rwx) : ORIGIN  = 0xC0000000, LENGTH = 256M
69    ddr_wcb_32bit (rwx) : ORIGIN  = 0xD0000000, LENGTH = 256M
70    ddr_cached_38bit (rwx) : ORIGIN  = 0x1000000000, LENGTH = 1024M
71    ddr_non_cached_38bit (rwx) : ORIGIN  = 0x1400000000, LENGTH = 0k
72    ddr_wcb_38bit (rwx) : ORIGIN  = 0x1800000000, LENGTH  = 0k
73}
74HEAP_SIZE           = 0k;               /* needs to be calculated for your application if using */
75
76/*
77 * Stack size for our single hart U54 application.
78 */
79STACK_SIZE_U54_APPLICATION = 8k;
80
81/*
82 * A small amount of unitialised memory used to store information
83 * obtained from the boot-loader on start-up
84 */
85UNITITALISED_MEM = 16B;
86
87/* reset address 0xC0000000 */
88SECTION_START_ADDRESS           = 0x80000000;
89
90
91SECTIONS
92{
93
94    /* text: test code section */
95    . = SECTION_START_ADDRESS;
96    .text : ALIGN(0x10)
97    {
98         __text_load = LOADADDR(.text);
99         __text_start = .;
100         *(.text.init)
101        . = ALIGN(0x10);
102        *(.text .text.* .gnu.linkonce.t.*)
103        *(.plt)
104        . = ALIGN(0x10);
105
106        KEEP (*crtbegin.o(.ctors))
107        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
108        KEEP (*(SORT(.ctors.*)))
109        KEEP (*crtend.o(.ctors))
110        KEEP (*crtbegin.o(.dtors))
111        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
112        KEEP (*(SORT(.dtors.*)))
113        KEEP (*crtend.o(.dtors))
114
115        *(.rodata .rodata.* .gnu.linkonce.r.*)
116        *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
117        *(.gcc_except_table)
118        *(.eh_frame_hdr)
119        *(.eh_frame)
120
121        KEEP (*(.init))
122        KEEP (*(.fini))
123
124        PROVIDE_HIDDEN (__preinit_array_start = .);
125        KEEP (*(.preinit_array))
126        PROVIDE_HIDDEN (__preinit_array_end = .);
127        PROVIDE_HIDDEN (__init_array_start = .);
128        KEEP (*(SORT(.init_array.*)))
129        KEEP (*(.init_array))
130        PROVIDE_HIDDEN (__init_array_end = .);
131        PROVIDE_HIDDEN (__fini_array_start = .);
132        KEEP (*(.fini_array))
133        KEEP (*(SORT(.fini_array.*)))
134        PROVIDE_HIDDEN (__fini_array_end = .);
135
136        *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
137        *(.srodata*)
138
139        . = ALIGN(0x10);
140        __text_end = .;
141    } > ddr_cached_32bit
142
143    .l2_scratchpad : ALIGN(0x10)
144    {
145        __l2_scratchpad_load = LOADADDR(.l2_scratchpad);
146        __l2_scratchpad_start = .;
147        __l2_scratchpad_vma_start = .;
148        *(.l2_scratchpad)
149        . = ALIGN(0x10);
150        __l2_scratchpad_end = .;
151        __l2_scratchpad_vma_end = .;
152    } >scratchpad AT> ddr_cached_32bit
153
154    /* short/global data section */
155    .sdata : ALIGN(0x10)
156    {
157        __sdata_load = LOADADDR(.sdata);
158        __sdata_start = .;
159        /* offset used with gp(gloabl pointer) are +/- 12 bits, so set point to middle of expected sdata range */
160        /* If sdata more than 4K, linker used direct addressing. Perhaps we should add check/warning to linker script if sdata is > 4k */
161        __global_pointer$ = . + 0x800;
162        *(.sdata .sdata.* .gnu.linkonce.s.*)
163        . = ALIGN(0x10);
164        __sdata_end = .;
165    } > ddr_cached_32bit
166
167    /* data section */
168    .data : ALIGN(0x10)
169    {
170        __data_load = LOADADDR(.data);
171        __data_start = .;
172        *(.got.plt) *(.got)
173        *(.shdata)
174        *(.data .data.* .gnu.linkonce.d.*)
175        . = ALIGN(0x10);
176        __data_end = .;
177    } > ddr_cached_32bit
178
179    /* sbss section */
180    .sbss : ALIGN(0x10)
181    {
182        __sbss_start = .;
183        *(.sbss .sbss.* .gnu.linkonce.sb.*)
184        *(.scommon)
185        . = ALIGN(0x10);
186        __sbss_end = .;
187    } > ddr_cached_32bit
188
189    /* sbss section */
190    .bss : ALIGN(0x10)
191    {
192        __bss_start = .;
193        *(.shbss)
194        *(.bss .bss.* .gnu.linkonce.b.*)
195        *(COMMON)
196        . = ALIGN(0x10);
197        __bss_end = .;
198    } > ddr_cached_32bit
199
200    /* End of uninitialized data segment */
201        _end = .;
202
203        .heap : ALIGN(0x10)
204        {
205        __heap_start = .;
206        . += HEAP_SIZE;
207        __heap_end = .;
208        . = ALIGN(0x10);
209        _heap_end = __heap_end;
210    } > ddr_cached_32bit
211
212    /* must be on 4k boundary- corresponds to page size */
213    .stack : ALIGN(0x1000)
214    {
215        PROVIDE(__app_stack_bottom = .);
216        . += STACK_SIZE_U54_APPLICATION;
217        PROVIDE(__app_stack_top = .);
218    } > ddr_cached_32bit
219
220    /*
221     * used by a program loaded by a bootloader to store information passed
222     * from boot-loader
223     * a0 holds the hart ID
224     * a1 hold pointer to device data, which includes pointer to shared memory
225     * when enabled by setting MPFS_HAL_SHARED_MEM_ENABLED define in the
226     * mss_sw_config.h
227     */
228    .no_init : ALIGN(0x10)
229    {
230        PROVIDE(__uninit_bottom$ = .);
231        . += UNITITALISED_MEM;
232        PROVIDE(__uninit_top_h$ = .);
233    } > ddr_cached_32bit
234}
235
236