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-envm-lma-scratchpad-vma.ld
12 * Code starts from eNVM and relocates itself to an L2 cache scratchpad mapped in
13 * the Zero Device address range.
14 *
15 * You can find details on the PolarFireSoC Memory map in the mpfs-memory-hierarchy.md
16 * which can be found under the link below:
17 * https://github.com/polarfire-soc/polarfire-soc-documentation
18 *
19 */
20
21OUTPUT_ARCH( "riscv" )
22ENTRY(_start)
23
24/*-----------------------------------------------------------------------------
25
26-- MSS hart Reset vector
27
28The MSS reset vector for each hart is stored securely in the MPFS.
29The most common usage will be where the reset vector for each hart will be set
30to the start of the envm at address 0x2022_0100, giving 128K-256B of contiguous
31non-volatile storage. Normally this is where the initial boot-loader will
32reside. (Note: The first 256B page of envm is used for metadata associated with
33secure boot. When not using secure boot (mode 0,1), this area is still reserved
34by convention. It allows easier transition from non-secure to secure boot flow
35during the development process.
36When debugging a bare metal program that is run out of reset from envm, a linker
37script will be used whereby the program will run from LIM instead of envm.
38In this case, the reset vector in the linker script is normally set to the
39start of LIM, 0x0800_0000.
40This means you are not continually programming the envm each time you load a
41program and there is no limitation with break points when debugging.
42See the mpfs-lim.ld example linker script when runing from LIM.
43
44------------------------------------------------------------------------------*/
45
46MEMORY
47{
48    /* In this example, our reset vector is set to point to the */
49    /* start at page 1 of the envm */
50    envm (rx) : ORIGIN  = 0x20220100, LENGTH = 128k - 0x100
51    dtim (rwx) : ORIGIN  = 0x01000000, LENGTH = 7k
52    e51_itim (rwx)     : ORIGIN = 0x01800000, LENGTH = 28k
53    u54_1_itim (rwx)   : ORIGIN = 0x01808000, LENGTH = 28k
54    u54_2_itim (rwx)   : ORIGIN = 0x01810000, LENGTH = 28k
55    u54_3_itim (rwx)   : ORIGIN = 0x01818000, LENGTH = 28k
56    u54_4_itim (rwx)   : ORIGIN = 0x01820000, LENGTH = 28k
57    l2lim (rwx)        : ORIGIN = 0x08000000, LENGTH = 256k
58    scratchpad(rwx)    : ORIGIN = 0x0A000000, LENGTH = 256k
59    /* This 1k of DTIM is used to run code when switching the envm clock */
60    switch_code (rx) :      ORIGIN = 0x01001c00, LENGTH = 1k
61    /* DDR sections example */
62    ddr_cached_32bit (rwx) : ORIGIN  = 0x80000000, LENGTH = 768M
63    ddr_non_cached_32bit (rwx) : ORIGIN  = 0xC0000000, LENGTH = 256M
64    ddr_wcb_32bit (rwx) : ORIGIN  = 0xD0000000, LENGTH = 256M
65    ddr_cached_38bit (rwx) : ORIGIN  = 0x1000000000, LENGTH = 1024M
66    ddr_non_cached_38bit (rwx) : ORIGIN  = 0x1400000000, LENGTH = 0k
67    ddr_wcb_38bit (rwx) : ORIGIN  = 0x1800000000, LENGTH  = 0k
68}
69
70HEAP_SIZE           = 8k;               /* needs to be calculated for your application if using */
71
72/*
73 * There is common area for shared variables, accessed from a pointer in a harts HLS
74 */
75SIZE_OF_COMMON_HART_MEM = 4k;
76
77/*
78 * The stack size needs to be calculated for your
79 * application. It must be Must be aligned
80 * Also Thread local storage (AKA hart local storage) is allocated for each hart
81 * as part of the stack
82 * So the memory map will look like once apportion in startup code:
83 * stack hart0  Actual Stack size = (STACK_SIZE_PER_HART - HLS_DEBUG_AREA_SIZE)
84 * TLS hart 0
85 * stack hart1
86 * TLS hart 1
87 * etc
88 * note: HLS_DEBUG_AREA_SIZE is defined in mss_sw_config.h
89 */
90
91/*
92 * STACK_SIZE_xxx_STARTUP
93 * Stack size for each hart's startup code.
94 * Before copying itself to the scratchpad memory area and executing the code from there, the
95 * startup code is executing from LIM. The scratchpad area is not configured yet. This per-hart
96 * startup stack area is located in LIM and used during this phase of the startup code.
97 * STACK_SIZE_xxx_APPLICATION
98 * After the startup code executing from LIM configures the scratchpad memory, it configures
99 * the each hart's SP with this stack area for the respective hart's application function,
100 * (namely e51(), u54_1(), u54_2(), u54_3(), u54_4() ) to use it.
101 * This per-hart application stack area is located in scratchpad and used by application when
102 * it is executing from scratchpad.
103 *
104 */
105STACK_SIZE_E51_STARTUP = 4k;
106STACK_SIZE_U54_1_STARTUP = 4k;
107STACK_SIZE_U54_2_STARTUP = 4k;
108STACK_SIZE_U54_3_STARTUP = 4k;
109STACK_SIZE_U54_4_STARTUP = 4k;
110
111STACK_SIZE_E51_APPLICATION = 8k;
112STACK_SIZE_U54_1_APPLICATION = 8k;
113STACK_SIZE_U54_2_APPLICATION = 8k;
114STACK_SIZE_U54_3_APPLICATION = 8k;
115STACK_SIZE_U54_4_APPLICATION = 8k;
116
117
118SECTIONS
119{
120    PROVIDE(__envm_start = ORIGIN(envm));
121    PROVIDE(__envm_end = ORIGIN(envm) + LENGTH(envm));
122    PROVIDE(__l2lim_start = ORIGIN(l2lim));
123    PROVIDE(__l2lim_end = ORIGIN(l2lim) + LENGTH(l2lim));
124    PROVIDE(__ddr_cached_32bit_start = ORIGIN(ddr_cached_32bit));
125    PROVIDE(__ddr_cached_32bit_end = ORIGIN(ddr_cached_32bit) + LENGTH(ddr_cached_32bit));
126    PROVIDE(__ddr_non_cached_32bit_start = ORIGIN(ddr_non_cached_32bit));
127    PROVIDE(__ddr_non_cached_32bit_end = ORIGIN(ddr_non_cached_32bit) + LENGTH(ddr_non_cached_32bit));
128    PROVIDE(__ddr_wcb_32bit_start = ORIGIN(ddr_wcb_32bit));
129    PROVIDE(__ddr_wcb_32bit_end = ORIGIN(ddr_wcb_32bit) + LENGTH(ddr_wcb_32bit));
130    PROVIDE(__ddr_cached_38bit_start = ORIGIN(ddr_cached_38bit));
131    PROVIDE(__ddr_cached_38bit_end = ORIGIN(ddr_cached_38bit) + LENGTH(ddr_cached_38bit));
132    PROVIDE(__ddr_non_cached_38bit_start = ORIGIN(ddr_non_cached_38bit));
133    PROVIDE(__ddr_non_cached_38bit_end = ORIGIN(ddr_non_cached_38bit) + LENGTH(ddr_non_cached_38bit));
134    PROVIDE(__ddr_wcb_38bit_start = ORIGIN(ddr_wcb_38bit));
135    PROVIDE(__ddr_wcb_38bit_end = ORIGIN(ddr_wcb_38bit) + LENGTH(ddr_wcb_38bit));
136    PROVIDE(__dtim_start = ORIGIN(dtim));
137    PROVIDE(__dtim_end = ORIGIN(dtim) + LENGTH(dtim));
138    PROVIDE(__e51itim_start = ORIGIN(e51_itim));
139    PROVIDE(__e51itim_end = ORIGIN(e51_itim) + LENGTH(e51_itim));
140    PROVIDE(__u54_1_itim_start = ORIGIN(u54_1_itim));
141    PROVIDE(__u54_1_itim_end = ORIGIN(u54_1_itim) + LENGTH(u54_1_itim));
142    PROVIDE(__u54_2_itim_start = ORIGIN(u54_2_itim));
143    PROVIDE(__u54_2_itim_end = ORIGIN(u54_2_itim) + LENGTH(u54_2_itim));
144    PROVIDE(__u54_3_itim_start = ORIGIN(u54_3_itim));
145    PROVIDE(__u54_3_itim_end = ORIGIN(u54_3_itim) + LENGTH(u54_3_itim));
146    PROVIDE(__u54_4_itim_start = ORIGIN(u54_4_itim));
147    PROVIDE(__u54_4_itim_end = ORIGIN(u54_4_itim) + LENGTH(u54_4_itim));
148
149    . = __envm_start;
150    .text_init : ALIGN(0x10)
151    {
152        *(.text.init)
153        *system_startup.o (.text .text* .rodata .rodata* .srodata*)
154        *mtrap.o (.text .text* .rodata .rodata* .srodata*)
155        *mss_h2f.o (.text .text* .rodata .rodata* .srodata*)
156        *mss_l2_cache.o (.text .text* .rodata .rodata* .srodata*)
157        . = ALIGN(0x10);
158    } >envm
159
160    .text : ALIGN(0x10)
161    {
162        __text_load = LOADADDR(.text);
163        . = ALIGN(0x10);
164        __text_start = .;
165        /* placed at the start of used scratchpad, used as check to verify enough available in code */
166        __l2_scratchpad_vma_start = .;
167
168        *(.text .text.* .gnu.linkonce.t.*)
169        *(.plt)
170        . = ALIGN(0x10);
171
172        KEEP (*crtbegin.o(.ctors))
173        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
174        KEEP (*(SORT(.ctors.*)))
175        KEEP (*crtend.o(.ctors))
176        KEEP (*crtbegin.o(.dtors))
177        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
178        KEEP (*(SORT(.dtors.*)))
179        KEEP (*crtend.o(.dtors))
180
181        *(.rodata .rodata.* .gnu.linkonce.r.*)
182        *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
183        *(.gcc_except_table)
184        *(.eh_frame_hdr)
185        *(.eh_frame)
186
187        KEEP (*(.init))
188        KEEP (*(.fini))
189
190        PROVIDE_HIDDEN (__preinit_array_start = .);
191        KEEP (*(.preinit_array))
192        PROVIDE_HIDDEN (__preinit_array_end = .);
193        PROVIDE_HIDDEN (__init_array_start = .);
194        KEEP (*(SORT(.init_array.*)))
195        KEEP (*(.init_array))
196        PROVIDE_HIDDEN (__init_array_end = .);
197        PROVIDE_HIDDEN (__fini_array_start = .);
198        KEEP (*(.fini_array))
199        KEEP (*(SORT(.fini_array.*)))
200        PROVIDE_HIDDEN (__fini_array_end = .);
201
202        *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
203        *(.srodata*)
204
205        . = ALIGN(0x10);
206        __text_end = .;
207    } >scratchpad AT> envm
208
209    /* short/global data section */
210    .sdata : ALIGN(0x10)
211    {
212        __sdata_load = LOADADDR(.sdata);
213        __sdata_start = .;
214        /* offset used with gp(gloabl pointer) are +/- 12 bits, so set point to middle of expected sdata range */
215        /* If sdata more than 4K, linker used direct addressing. Perhaps we should add check/warning to linker script if sdata is > 4k */
216        __global_pointer$ = . + 0x800;
217        *(.sdata .sdata.* .gnu.linkonce.s.*)
218        . = ALIGN(0x10);
219        __sdata_end = .;
220    } >scratchpad AT> envm
221
222    /* data section */
223    .data : ALIGN(0x10)
224    {
225        __data_load = LOADADDR(.data);
226        __data_start = .;
227        *(.got.plt) *(.got)
228        *(.shdata)
229        *(.data .data.* .gnu.linkonce.d.*)
230        . = ALIGN(0x10);
231        __data_end = .;
232    } > scratchpad AT> envm
233
234    /* sbss section */
235    .sbss : ALIGN(0x10)
236    {
237        __sbss_start = .;
238        *(.sbss .sbss.* .gnu.linkonce.sb.*)
239        *(.scommon)
240        . = ALIGN(0x10);
241        __sbss_end = .;
242    } > scratchpad
243
244    /* sbss section */
245    .bss : ALIGN(0x10)
246    {
247        __bss_start = .;
248        *(.shbss)
249        *(.bss .bss.* .gnu.linkonce.b.*)
250        *(COMMON)
251        . = ALIGN(0x10);
252        __bss_end = .;
253    } > scratchpad
254
255    /* End of uninitialized data segment */
256    _end = .;
257
258    .heap : ALIGN(0x10)
259    {
260        __heap_start = .;
261        . += HEAP_SIZE;
262        __heap_end = .;
263        . = ALIGN(0x10);
264        _heap_end = __heap_end;
265        __l2_scratchpad_vma_end = .;
266    } > scratchpad
267
268
269    /* must be on 4k boundary- corresponds to page size */
270    .stack_e51 : /* ALIGN(0x1000) */
271    {
272        PROVIDE(__stack_bottom_h0$ = .);
273        . += STACK_SIZE_E51_STARTUP;
274        PROVIDE(__stack_top_h0$ = .);
275    } > l2lim
276
277    /* must be on 4k boundary- corresponds to page size */
278    .stack_u54_1 : /* ALIGN(0x1000) */
279    {
280        PROVIDE(__stack_bottom_h1$ = .);
281        . += STACK_SIZE_U54_1_STARTUP;
282        PROVIDE(__stack_top_h1$ = .);
283    } > l2lim
284
285    /* must be on 4k boundary- corresponds to page size */
286    .stack_u54_2 : /* ALIGN(0x1000) */
287    {
288        PROVIDE(__stack_bottom_h2$ = .);
289        . += STACK_SIZE_U54_2_STARTUP;
290        PROVIDE(__stack_top_h2$ = .);
291    } > l2lim
292
293    /*  */
294    .stack_u54_3 : /* ALIGN(0x1000) */
295    {
296        PROVIDE(__stack_bottom_h3$ = .);
297         . += STACK_SIZE_U54_3_STARTUP;
298         PROVIDE(__stack_top_h3$ = .);
299    } > l2lim
300
301    /*  */
302    .stack_u54_4 : /* ALIGN(0x1000) */
303    {
304        PROVIDE(__stack_bottom_h4$ = .);
305        . += STACK_SIZE_U54_4_STARTUP;
306        PROVIDE(__stack_top_h4$ = .);
307    } > l2lim
308    /* application stacks defined below here */
309
310    /* must be on 4k boundary- corresponds to page size */
311    .app_stack_e51 : /* ALIGN(0x1000) */
312    {
313        PROVIDE(__app_stack_bottom_h0 = .);
314        . += STACK_SIZE_E51_APPLICATION;
315        PROVIDE(__app_stack_top_h0 = .);
316    } > scratchpad
317
318    /* must be on 4k boundary- corresponds to page size */
319    .app_stack_u54_1 : /* ALIGN(0x1000) */
320    {
321        PROVIDE(__app_stack_bottom_h1$ = .);
322        . += STACK_SIZE_U54_1_APPLICATION;
323        PROVIDE(__app_stack_top_h1 = .);
324    } > scratchpad
325
326    /*  */
327    .app_stack_u54_2 : /* ALIGN(0x1000) */
328    {
329        PROVIDE(__app_stack_bottom_h2 = .);
330        . += STACK_SIZE_U54_2_APPLICATION;
331        PROVIDE(__app_stack_top_h2 = .);
332    } > scratchpad
333
334    /*  */
335    .app_stack_u54_3 : /* ALIGN(0x1000) */
336    {
337        PROVIDE(__app_stack_bottom_h3 = .);
338        . += STACK_SIZE_U54_3_APPLICATION;
339        PROVIDE(__app_stack_top_h3 = .);
340    } > scratchpad
341
342    /*  */
343    .app_stack_u54_4 : /* ALIGN(0x1000) */
344    {
345        PROVIDE(__app_stack_bottom_h4 = .);
346        . += STACK_SIZE_U54_4_APPLICATION;
347        PROVIDE(__app_stack_top_h4 = .);
348    } > scratchpad
349
350    /*
351     * memory shared accross harts.
352     * The boot Hart Local Storage holds a pointer to this area for each hart if
353     * when enabled by setting MPFS_HAL_SHARED_MEM_ENABLED define in the
354     * mss_sw_config.h
355     */
356    .app_hart_common : /* ALIGN(0x1000) */
357    {
358        PROVIDE(__app_hart_common_start = .);
359        . += SIZE_OF_COMMON_HART_MEM;
360        PROVIDE(__app_hart_common_end = .);
361        /* place at the end of used scratchpad, used as check to verify enough available in code */
362        __l2_scratchpad_vma_end = .;
363    } > scratchpad
364
365    /*
366    *   The .ram_code section will contain the code That is run from RAM.
367    *   We are using this code to switch the clocks including envm clock.
368    *   This can not be done when running from envm
369    *   This will need to be copied to ram, before any of this code is run.
370    */
371    .ram_code :
372    {
373        . = ALIGN (4);
374        __sc_load = LOADADDR (.ram_code);
375        __sc_start = .;
376        *(.ram_codetext)        /* .ram_codetext sections (code) */
377        *(.ram_codetext*)       /* .ram_codetext* sections (code)  */
378        *(.ram_coderodata)      /* read-only data (constants) */
379        *(.ram_coderodata*)
380        . = ALIGN (4);
381        __sc_end = .;
382        /* place __start_of_free_lim$ after last allocation of l2lim */
383        PROVIDE(__start_of_free_lim$ = .);
384    } >switch_code AT> envm     /* On the MPFS for startup code use,  >switch_code AT>envm */
385}
386
387
388