1/*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
4 * Copyright (c) 2019-2021, Renesas Electronics Corporation. All rights
5 * reserved.
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * There are three supported memory layouts for the ARMv7-M architecture:
10 *
11 * Layout 1 - Single region:
12 * - All sections are placed in one contiguous region.
13 * - This layout uses only the mem0 memory region.
14 * - The memory is considered RXW by the linker, but the sections can be
15 *   configured later on with different attributes using the MPU.
16 * - The main stack is placed at the end of mem0.
17 * - This layout is mainly used by second-stage firmware that is loaded directly
18 *   into a single RAM.
19 *
20 * Layout 2 - Dual region with relocation:
21 * - One region is used for .text and .data (storage).
22 * - A second region is used for the remaining sections.
23 * - This layout uses memory regions mem0 and mem1 as the first and second
24 *   regions, respectively.
25 * - The main stack is placed at the end of mem1.
26 * - This layout is mainly used by ROM firmware which uses part of the RAM for
27 *   the data sections.
28 *
29 * Layout 3 - Dual region without relocation
30 * - One region is used only for the .text section.
31 * - A second region is used for all data sections.
32 * - This layout uses memory regions mem0 and mem1 as the first and second
33 *   regions, respectively.
34 * - The main stack is placed at the end of mem1.
35 * - The main difference from layout 2 is that there is no relocation of the
36 *   .data section.
37 * - This layout is mainly used by second-stage firmware loaded directly into
38 *   two RAM regions. One of the RAM regions is attached to the instruction bus,
39 *   which improves the performance as data and instruction accesses are
40 *   independent.
41 *
42 */
43
44#define ARCH_MEM_MODE_SINGLE_REGION             0
45#define ARCH_MEM_MODE_DUAL_REGION_RELOCATION    1
46#define ARCH_MEM_MODE_DUAL_REGION_NO_RELOCATION 2
47
48#include <fmw_memory.h>
49
50#define STACK_ALIGNMENT 8
51
52/*
53 * Input validation
54 */
55
56#ifndef FMW_MEM_MODE
57    #error "FMW_MEM_MODE has not been configured"
58#endif
59
60#ifndef FMW_STACK_SIZE
61    #error "FMW_STACK_SIZE has not been configured"
62#endif
63
64#ifndef FMW_MEM0_BASE
65    #error "FMW_MEM0_BASE has not been configured"
66#endif
67
68#ifndef FMW_MEM0_SIZE
69    #error "FMW_MEM0_SIZE has not been configured"
70#endif
71
72#if ((FMW_MEM_MODE != ARCH_MEM_MODE_SINGLE_REGION) && \
73     (FMW_MEM_MODE != ARCH_MEM_MODE_DUAL_REGION_RELOCATION) && \
74     (FMW_MEM_MODE != ARCH_MEM_MODE_DUAL_REGION_NO_RELOCATION))
75    #error "FMW_MEM_MODE has been configured improperly"
76#endif
77
78#if FMW_MEM_MODE != ARCH_MEM_MODE_SINGLE_REGION
79    #ifndef FIRMWARE_MEM1_BASE
80        #error "FIRMWARE_MEM1_BASE has not been configured"
81    #endif
82
83    #ifndef FIRMWARE_MEM1_SIZE
84        #error "FIRMWARE_MEM1_SIZE has not been configured"
85    #endif
86#endif
87
88/*
89 * Calculate stack region in the data memory.
90 */
91
92#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION
93    ASSERT(FMW_STACK_SIZE < FMW_MEM0_SIZE,
94        "FMW_STACK_SIZE does not fit in MEM0")
95    #define UNALIGNED_STACK_BASE \
96        (FMW_MEM0_BASE + FMW_MEM0_SIZE - FMW_STACK_SIZE)
97#else
98    ASSERT(FMW_STACK_SIZE < FIRMWARE_MEM1_SIZE,
99        "FMW_STACK_SIZE does not fit in MEM1")
100    #define UNALIGNED_STACK_BASE \
101        (FIRMWARE_MEM1_BASE + FIRMWARE_MEM1_SIZE - FMW_STACK_SIZE)
102#endif
103
104#define STACK_BASE \
105    ( \
106        ((UNALIGNED_STACK_BASE + STACK_ALIGNMENT - 1) / STACK_ALIGNMENT) \
107            * STACK_ALIGNMENT \
108    )
109
110#define STACK_SIZE \
111    (( \
112        ((STACK_BASE + FMW_STACK_SIZE) / STACK_ALIGNMENT) \
113            * STACK_ALIGNMENT \
114    ) - STACK_BASE)
115
116ASSERT(STACK_SIZE > 0, "FMW_STACK_SIZE is too small")
117
118ENTRY(_entrypoint)
119
120MEMORY {
121#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION
122    /* Only one memory region with read, execute and write attributes */
123    mem0 (rxw): ORIGIN = FMW_MEM0_BASE, LENGTH = FMW_MEM0_SIZE - \
124                                                      FMW_STACK_SIZE
125#else
126    mem0 (rx):  ORIGIN = FMW_MEM0_BASE, LENGTH = FMW_MEM0_SIZE
127    mem1 (rxw): ORIGIN = FIRMWARE_MEM1_BASE, LENGTH = FIRMWARE_MEM1_SIZE - \
128                                                      FMW_STACK_SIZE
129#endif
130    stack (rw):  ORIGIN = STACK_BASE, LENGTH = STACK_SIZE
131    sram (rxw): ORIGIN = ((0xE6302000)), LENGTH = (0x00001000)
132}
133
134SECTIONS {
135    .text : {
136        *(.vectors)
137        *(.entrypoint)
138        *(.text*)
139        *(.rodata*)
140        *(.note.gnu.build-id)
141    } > mem0
142
143    __text__ = .;
144
145    __sram_copy_start__ = .;
146    .system_ram : {
147        __system_ram_start__ = .;
148        *(.system_ram*)
149        *iic_dvfs.o(.rodata)
150        __system_ram_end__ = .;
151    } > sram AT> mem0
152
153    . = __text__ + SIZEOF(.system_ram);
154
155    /*
156     * Define a linker symbol to mark start of the RW memory area for this
157     * image.
158     */
159    __RW_START__ = . ;
160
161    .data : {
162        . = ALIGN(4);
163        *(.data*)
164        . = ALIGN(4);
165#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION
166    } > mem0 /* .data follows .text in mem0 */
167#elif FMW_MEM_MODE == ARCH_MEM_MODE_DUAL_REGION_NO_RELOCATION
168    } > mem1 /* .data is the first section in mem1 */
169#elif FMW_MEM_MODE == ARCH_MEM_MODE_DUAL_REGION_RELOCATION
170    } > mem1 AT>mem0  /* Run-time image is at mem1, but loaded from mem0 */
171#else
172    ASSERT(0, "Unrecognized FMW_MEM_MODE")
173#endif
174
175    .bss : {
176        . = ALIGN(4);
177        *(.bss*)
178        . = ALIGN(4);
179#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION
180    } > mem0  /* Run-time image is at mem1, but loaded from mem0 */
181#else
182    } > mem1 /* .bss follows .data in mem1 */
183#endif
184
185    .stack (NOLOAD) : {
186        . = . + STACK_SIZE;
187    } > stack
188    __RW_END__ = .;
189
190    /*
191     * Define a linker symbol to mark end of the RW memory area for this
192     * image.
193     */
194
195    __TEXT_START__ = LOADADDR(.text);
196    __TEXT_SIZE__ = SIZEOF(.text);
197    __TEXT_END__ = __TEXT_START__ + __TEXT_SIZE__;
198
199    __STACK_START__ = LOADADDR(.stack);
200    __STACK_SIZE__ = SIZEOF(.stack);
201    __STACK_END__ = __STACK_START__ + __STACK_SIZE__;
202    __STACK_TOP__ = __STACK_END__;
203    __STACK_SP3_SIZE__ = 0x400;
204    __STACK_SP0_TOP__ = __STACK_END__ - __STACK_SP3_SIZE__;
205
206    __DATA_LMA_START__ = LOADADDR(.data);
207    __DATA_START__ = ADDR(.data);
208    __DATA_SIZE__ = SIZEOF(.data);
209
210    __BSS_START__ = ADDR(.bss);
211    __BSS_SIZE__ = SIZEOF(.bss);
212    __BSS_END__ = __BSS_START__ + __BSS_SIZE__;
213
214    __HEAP_START__ = __BSS_START__ + __BSS_SIZE__;
215    __HEAP_END__ = __STACK_START__;
216    __HEAP_SIZE__ = __HEAP_END__ - __HEAP_START__;
217}
218