1 /*
2 
3 Copyright (c) 2009-2024 ARM Limited. All rights reserved.
4 
5     SPDX-License-Identifier: Apache-2.0
6 
7 Licensed under the Apache License, Version 2.0 (the License); you may
8 not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10 
11     www.apache.org/licenses/LICENSE-2.0
12 
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an AS IS BASIS, WITHOUT
15 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 
19 NOTICE: This file has been modified by Nordic Semiconductor ASA.
20 
21 */
22 
23 /* NOTE: Template files (including this one) are application specific and therefore expected to
24    be copied into the application project folder prior to its use! */
25 
26 #include <stdint.h>
27 #include <stdbool.h>
28 #include "nrf.h"
29 #include "nrf_peripherals.h"
30 #include "nrf53_erratas.h"
31 #include "system_nrf53.h"
32 #include "system_nrf53_approtect.h"
33 
34 /*lint ++flb "Enter library region" */
35 
36 void SystemStoreFICRNS(void);
37 void SystemLockFICRNS(void);
38 
39 
40 /* NRF5340 application core uses a variable System Clock Frequency that starts at 64MHz */
41 #define __SYSTEM_CLOCK_MAX      (128000000UL)
42 #define __SYSTEM_CLOCK_DEFAULT  ( 64000000UL)
43 
44 #define TRACE_PIN_CNF_VALUE (   (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | \
45                                 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | \
46                                 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | \
47                                 (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | \
48                                 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | \
49                                 (GPIO_PIN_CNF_MCUSEL_TND << GPIO_PIN_CNF_MCUSEL_Pos))
50 
51 #define TRACE_TRACECLK_PIN   TAD_PSEL_TRACECLK_PIN_Traceclk
52 #define TRACE_TRACEDATA0_PIN TAD_PSEL_TRACEDATA0_PIN_Tracedata0
53 #define TRACE_TRACEDATA1_PIN TAD_PSEL_TRACEDATA1_PIN_Tracedata1
54 #define TRACE_TRACEDATA2_PIN TAD_PSEL_TRACEDATA2_PIN_Tracedata2
55 #define TRACE_TRACEDATA3_PIN TAD_PSEL_TRACEDATA3_PIN_Tracedata3
56 
57 #if defined ( __CC_ARM ) || defined ( __GNUC__ )
58     uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_DEFAULT;
59 #elif defined ( __ICCARM__ )
60     __root uint32_t SystemCoreClock = __SYSTEM_CLOCK_DEFAULT;
61 #endif
62 
SystemCoreClockUpdate(void)63 void SystemCoreClockUpdate(void)
64 {
65 #if defined(NRF_TRUSTZONE_NONSECURE)
66     SystemCoreClock = __SYSTEM_CLOCK_MAX >> (NRF_CLOCK_NS->HFCLKCTRL & (CLOCK_HFCLKCTRL_HCLK_Msk));
67 #else
68     SystemCoreClock = __SYSTEM_CLOCK_MAX >> (NRF_CLOCK_S->HFCLKCTRL & (CLOCK_HFCLKCTRL_HCLK_Msk));
69 #endif
70 }
71 
SystemInit(void)72 void SystemInit(void)
73 {
74     #if !defined(NRF_TRUSTZONE_NONSECURE)
75         /* Perform Secure-mode initialization routines. */
76 
77         /* Set all ARM SAU regions to NonSecure if TrustZone extensions are enabled.
78         * Nordic SPU should handle Secure Attribution tasks */
79         #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
80             SAU->CTRL |= (1ul << SAU_CTRL_ALLNS_Pos);
81         #endif
82 
83         /* Workaround for Errata 97 "ERASEPROTECT, APPROTECT, or startup problems" found at the Errata document
84            for your device located at https://infocenter.nordicsemi.com/index.jsp  */
85         if (nrf53_errata_97())
86         {
87             if (*((volatile uint32_t *)0x50004A20ul) == 0ul)
88             {
89                 *((volatile uint32_t *)0x50004A20ul) = 0xDul;
90                 *((volatile uint32_t *)0x5000491Cul) = 0x1ul;
91                 *((volatile uint32_t *)0x5000491Cul) = 0x0ul;
92             }
93         }
94 
95         /* Trimming of the device. Copy all the trimming values from FICR into the target addresses. Trim
96          until one ADDR is not initialized. */
97         uint32_t index = 0ul;
98         for (index = 0ul; index < 32ul && NRF_FICR_S->TRIMCNF[index].ADDR != 0xFFFFFFFFul; index++){
99             #if defined ( __ICCARM__ )
100                 /* IAR will complain about the order of volatile pointer accesses. */
101                 #pragma diag_suppress=Pa082
102             #endif
103             *((volatile uint32_t *)NRF_FICR_S->TRIMCNF[index].ADDR) = NRF_FICR_S->TRIMCNF[index].DATA;
104             #if defined ( __ICCARM__ )
105                 #pragma diag_default=Pa082
106             #endif
107         }
108 
109         /* errata 64 must be before errata 42, as errata 42 is dependant on the changes in errata 64*/
110         /* Workaround for Errata 64 "VREGMAIN has invalid configuration when CPU is running at 128 MHz" found at the Errata document
111            for your device located at https://infocenter.nordicsemi.com/index.jsp  */
112         if (nrf53_errata_64())
113         {
114             *((volatile uint32_t *)0x5000470Cul) = 0x29ul;
115             *((volatile uint32_t *)0x5000473Cul) = 0x3ul;
116         }
117 
118         /* Workaround for Errata 42 "Reset value of HFCLKCTRL is invalid" found at the Errata document
119            for your device located at https://infocenter.nordicsemi.com/index.jsp  */
120         if (nrf53_errata_42())
121         {
122             *((volatile uint32_t *)0x50039530ul) = 0xBEEF0044ul;
123             NRF_CLOCK_S->HFCLKCTRL = CLOCK_HFCLKCTRL_HCLK_Div2 << CLOCK_HFCLKCTRL_HCLK_Pos;
124         }
125 
126         /* Workaround for Errata 46 "Higher power consumption of LFRC" found at the Errata document
127            for your device located at https://infocenter.nordicsemi.com/index.jsp  */
128         if (nrf53_errata_46())
129         {
130             *((volatile uint32_t *)0x5003254Cul) = 0ul;
131         }
132 
133         /* Workaround for Errata 49 "SLEEPENTER and SLEEPEXIT events asserted after pin reset" found at the Errata document
134            for your device located at https://infocenter.nordicsemi.com/index.jsp  */
135         if (nrf53_errata_49())
136         {
137             if (NRF_RESET_S->RESETREAS & RESET_RESETREAS_RESETPIN_Msk)
138             {
139                 NRF_POWER_S->EVENTS_SLEEPENTER = 0ul;
140                 NRF_POWER_S->EVENTS_SLEEPEXIT = 0ul;
141             }
142         }
143 
144         /* Workaround for Errata 55 "Bits in RESETREAS are set when they should not be" found at the Errata document
145            for your device located at https://infocenter.nordicsemi.com/index.jsp  */
146         if (nrf53_errata_55())
147         {
148             if (NRF_RESET_S->RESETREAS & RESET_RESETREAS_RESETPIN_Msk){
149                 NRF_RESET_S->RESETREAS = ~RESET_RESETREAS_RESETPIN_Msk;
150             }
151         }
152 
153         /* Workaround for Errata 69 "VREGMAIN configuration is not retained in System OFF" found at the Errata document
154            for your device located at https://infocenter.nordicsemi.com/index.jsp  */
155         if (nrf53_errata_69())
156         {
157             *((volatile uint32_t *)0x5000470Cul) =0x65ul;
158         }
159 
160         if (nrf53_errata_140())
161         {
162             if (*(volatile uint32_t *)0x50032420ul & 0x80000000ul)
163             {
164                 /* Reset occured during calibration */
165                 NRF_CLOCK_S->LFCLKSRC = CLOCK_LFCLKSRC_SRC_LFSYNT;
166                 NRF_CLOCK_S->TASKS_LFCLKSTART = 1ul;
167                 while (NRF_CLOCK_S->EVENTS_LFCLKSTARTED == 0ul) {}
168                 NRF_CLOCK_S->EVENTS_LFCLKSTARTED = 0ul;
169                 NRF_CLOCK_S->TASKS_LFCLKSTOP = 1ul;
170                 NRF_CLOCK_S->LFCLKSRC = CLOCK_LFCLKSRC_SRC_LFRC;
171             }
172         }
173 
174         if (nrf53_errata_160())
175         {
176             *((volatile uint32_t *)0x5000470Cul) = 0x7Eul;
177             *((volatile uint32_t *)0x5000493Cul) = 0x7Eul;
178             *((volatile uint32_t *)0x50002118ul) = 0x7Ful;
179             *((volatile uint32_t *)0x50039E04ul) = 0x0ul;
180             *((volatile uint32_t *)0x50039E08ul) = 0x0ul;
181             *((volatile uint32_t *)0x50101110ul) = 0x0ul;
182             *((volatile uint32_t *)0x50002124ul) = 0x0ul;
183             *((volatile uint32_t *)0x5000212Cul) = 0x0ul;
184             *((volatile uint32_t *)0x502012A0ul) = 0x0ul;
185         }
186 
187         #if !defined(NRF_SKIP_FICR_NS_COPY_TO_RAM)
188             SystemStoreFICRNS();
189         #endif
190 
191         #if defined(CONFIG_NFCT_PINS_AS_GPIOS)
192 
193             if ((NRF_UICR_S->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos))
194             {
195                 NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
196 
197                 while (NRF_NVMC_S->READY == NVMC_READY_READY_Busy);
198                 NRF_UICR_S->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk;
199 
200                 while (NRF_NVMC_S->READY == NVMC_READY_READY_Busy);
201                 NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
202 
203                 while (NRF_NVMC_S->READY == NVMC_READY_READY_Busy);
204                 NVIC_SystemReset();
205             }
206 
207         #endif
208 
209         /* Enable SWO trace functionality. If ENABLE_SWO is not defined, SWO pin will be used as GPIO (see Product
210            Specification to see which one). */
211         #if defined (ENABLE_SWO)
212             // Enable Trace And Debug peripheral
213             NRF_TAD_S->ENABLE = TAD_ENABLE_ENABLE_Msk;
214             NRF_TAD_S->CLOCKSTART = TAD_CLOCKSTART_START_Msk;
215 
216             // Set up Trace pad SPU firewall
217             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA0_PIN);
218 
219             // Configure trace port pad
220             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA0_PIN] = TRACE_PIN_CNF_VALUE;
221 
222             // Select trace pin
223             NRF_TAD_S->PSEL.TRACEDATA0 = TRACE_TRACEDATA0_PIN;
224 
225             // Set trace port speed to 64 MHz
226             NRF_TAD_S->TRACEPORTSPEED = TAD_TRACEPORTSPEED_TRACEPORTSPEED_64MHz;
227         #endif
228 
229         /* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product
230            Specification to see which ones). */
231         #if defined (ENABLE_TRACE)
232             // Enable Trace And Debug peripheral
233             NRF_TAD_S->ENABLE = TAD_ENABLE_ENABLE_Msk;
234             NRF_TAD_S->CLOCKSTART = TAD_CLOCKSTART_START_Msk;
235 
236             // Set up Trace pads SPU firewall
237             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACECLK_PIN);
238             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA0_PIN);
239             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA1_PIN);
240             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA2_PIN);
241             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA3_PIN);
242 
243             // Configure trace port pads
244             NRF_P0_S->PIN_CNF[TRACE_TRACECLK_PIN] =   TRACE_PIN_CNF_VALUE;
245             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA0_PIN] = TRACE_PIN_CNF_VALUE;
246             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA1_PIN] = TRACE_PIN_CNF_VALUE;
247             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA2_PIN] = TRACE_PIN_CNF_VALUE;
248             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA3_PIN] = TRACE_PIN_CNF_VALUE;
249 
250             // Select trace pins
251             NRF_TAD_S->PSEL.TRACECLK   = TRACE_TRACECLK_PIN;
252             NRF_TAD_S->PSEL.TRACEDATA0 = TRACE_TRACEDATA0_PIN;
253             NRF_TAD_S->PSEL.TRACEDATA1 = TRACE_TRACEDATA1_PIN;
254             NRF_TAD_S->PSEL.TRACEDATA2 = TRACE_TRACEDATA2_PIN;
255             NRF_TAD_S->PSEL.TRACEDATA3 = TRACE_TRACEDATA3_PIN;
256 
257             // Set trace port speed to 64 MHz
258             NRF_TAD_S->TRACEPORTSPEED = TAD_TRACEPORTSPEED_TRACEPORTSPEED_64MHz;
259 
260         #endif
261 
262         /* Allow Non-Secure code to run FPU instructions.
263          * If only the secure code should control FPU power state these registers should be configured accordingly in the secure application code. */
264         SCB->NSACR |= (3UL << 10ul);
265 
266         /* Handle fw-branch APPROTECT setup. */
267         nrf53_handle_approtect();
268 
269     #endif
270 
271     /* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the
272     * compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit
273     * operations are not used in your code. */
274     #if (__FPU_USED == 1ul)
275         SCB->CPACR |= (3UL << 20ul) | (3UL << 22ul);
276         __DSB();
277         __ISB();
278     #endif
279 }
280 
281 /* Workaround to allow NS code to access FICR. Override NRF_FICR_NS to move FICR_NS buffer. */
282 #define FICR_SIZE 0x1000ul
283 #define RAM_BASE 0x20000000ul
284 #define RAM_END  0x2FFFFFFFul
285 
286 /* Copy FICR_S to FICR_NS RAM region */
SystemStoreFICRNS()287 void SystemStoreFICRNS()
288 {
289     if ((uint32_t)NRF_FICR_NS < RAM_BASE || (uint32_t)NRF_FICR_NS + FICR_SIZE > RAM_END)
290     {
291         /* FICR_NS is not in RAM. */
292         return;
293     }
294     /* Copy FICR to NS-accessible RAM block. */
295     volatile uint32_t * from            = (volatile uint32_t *)((uint32_t)NRF_FICR_S + (FICR_SIZE - sizeof(uint32_t)));
296     volatile uint32_t * to              = (volatile uint32_t *)((uint32_t)NRF_FICR_NS + (FICR_SIZE - sizeof(uint32_t)));
297     volatile uint32_t * copy_from_end   = (volatile uint32_t *)NRF_FICR_S;
298     while (from >= copy_from_end)
299     {
300         *(to--) = *(from--);
301     }
302 
303     /* Make RAM region NS. */
304     uint32_t ram_region = ((uint32_t)NRF_FICR_NS - (uint32_t)RAM_BASE) / SPU_RAMREGION_SIZE;
305     NRF_SPU_S->RAMREGION[ram_region].PERM &= ~(1ul << SPU_RAMREGION_PERM_SECATTR_Pos);
306 }
307 
308 /* Block write and execute access to FICR RAM region */
SystemLockFICRNS()309 void SystemLockFICRNS()
310 {
311     if ((uint32_t)NRF_FICR_NS < RAM_BASE || (uint32_t)NRF_FICR_NS + FICR_SIZE > RAM_END)
312     {
313         /* FICR_NS is not in RAM. */
314         return;
315     }
316 
317     uint32_t ram_region = ((uint32_t)NRF_FICR_NS - (uint32_t)RAM_BASE) / SPU_RAMREGION_SIZE;
318     NRF_SPU_S->RAMREGION[ram_region].PERM &=
319         ~(
320             (1ul << SPU_RAMREGION_PERM_WRITE_Pos) |
321             (1ul << SPU_RAMREGION_PERM_EXECUTE_Pos)
322         );
323     NRF_SPU_S->RAMREGION[ram_region].PERM |= 1ul << SPU_RAMREGION_PERM_LOCK_Pos;
324 }
325 
326 /*lint --flb "Leave library region" */
327