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