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