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