1 /*
2 
3 Copyright (c) 2009-2020 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_erratas.h"
30 #include "system_nrf9160.h"
31 
32 /*lint ++flb "Enter library region" */
33 
34 
35 #define __SYSTEM_CLOCK      (64000000UL)     /*!< nRF9160 Application core uses a fixed System Clock Frequency of 64MHz */
36 
37 #define TRACE_PIN_CNF_VALUE (   (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | \
38                                 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | \
39                                 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | \
40                                 (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | \
41                                 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) )
42 #define TRACE_TRACECLK_PIN   (21)
43 #define TRACE_TRACEDATA0_PIN (22)
44 #define TRACE_TRACEDATA1_PIN (23)
45 #define TRACE_TRACEDATA2_PIN (24)
46 #define TRACE_TRACEDATA3_PIN (25)
47 
48 #if defined ( __CC_ARM )
49     uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK;
50 #elif defined ( __ICCARM__ )
51     __root uint32_t SystemCoreClock = __SYSTEM_CLOCK;
52 #elif defined ( __GNUC__ )
53     uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK;
54 #endif
55 
56 /* Global values used used in Secure mode SystemInit. */
57 #if !defined(NRF_TRUSTZONE_NONSECURE)
58     /* Global values used by UICR erase fix algorithm. */
59     static uint32_t uicr_erased_value;
60     static uint32_t uicr_new_value;
61 #endif
62 
63 /* Errata are only handled in secure mode since they usually need access to FICR. */
64 #if !defined(NRF_TRUSTZONE_NONSECURE)
65     static bool uicr_HFXOSRC_erased(void);
66     static bool uicr_HFXOCNT_erased(void);
67 #endif
68 
SystemCoreClockUpdate(void)69 void SystemCoreClockUpdate(void)
70 {
71     SystemCoreClock = __SYSTEM_CLOCK;
72 }
73 
SystemInit(void)74 void SystemInit(void)
75 {
76     #if !defined(NRF_TRUSTZONE_NONSECURE)
77         /* Perform Secure-mode initialization routines. */
78 
79         /* Set all ARM SAU regions to NonSecure if TrustZone extensions are enabled.
80         * Nordic SPU should handle Secure Attribution tasks */
81         #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
82           SAU->CTRL |= (1 << SAU_CTRL_ALLNS_Pos);
83         #endif
84 
85         /* Workaround for Errata 6 "POWER: SLEEPENTER and SLEEPEXIT events asserted after pin reset" found at the Errata document
86             for your device located at https://infocenter.nordicsemi.com/index.jsp  */
87         if (nrf91_errata_6()){
88             NRF_POWER_S->EVENTS_SLEEPENTER = (POWER_EVENTS_SLEEPENTER_EVENTS_SLEEPENTER_NotGenerated << POWER_EVENTS_SLEEPENTER_EVENTS_SLEEPENTER_Pos);
89             NRF_POWER_S->EVENTS_SLEEPEXIT = (POWER_EVENTS_SLEEPEXIT_EVENTS_SLEEPEXIT_NotGenerated << POWER_EVENTS_SLEEPEXIT_EVENTS_SLEEPEXIT_Pos);
90         }
91 
92         /* Workaround for Errata 14 "REGULATORS: LDO mode at startup" found at the Errata document
93             for your device located at https://infocenter.nordicsemi.com/index.jsp  */
94         if (nrf91_errata_14()){
95             *((volatile uint32_t *)0x50004A38) = 0x01ul;
96             NRF_REGULATORS_S->DCDCEN = REGULATORS_DCDCEN_DCDCEN_Enabled << REGULATORS_DCDCEN_DCDCEN_Pos;
97         }
98 
99         /* Workaround for Errata 15 "REGULATORS: LDO mode at startup" found at the Errata document
100             for your device located at https://infocenter.nordicsemi.com/index.jsp  */
101         if (nrf91_errata_15()){
102             NRF_REGULATORS_S->DCDCEN = REGULATORS_DCDCEN_DCDCEN_Enabled << REGULATORS_DCDCEN_DCDCEN_Pos;
103         }
104 
105         /* Workaround for Errata 20 "RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document
106             for your device located at https://infocenter.nordicsemi.com/index.jsp  */
107         if (nrf91_errata_20()){
108             *((volatile uint32_t *)0x5003AEE4) = 0xE;
109         }
110 
111         /* Workaround for Errata 31 "XOSC32k Startup Failure" found at the Errata document
112             for your device located at https://infocenter.nordicsemi.com/index.jsp  */
113         if (nrf91_errata_31()){
114             *((volatile uint32_t *)0x5000470Cul) = 0x0;
115             *((volatile uint32_t *)0x50004710ul) = 0x1;
116         }
117 
118         /* Trimming of the device. Copy all the trimming values from FICR into the target addresses. Trim
119          until one ADDR is not initialized. */
120         uint32_t index = 0;
121         for (index = 0; index < 256ul && NRF_FICR_S->TRIMCNF[index].ADDR != 0xFFFFFFFFul; index++){
122           #if defined ( __ICCARM__ )
123               #pragma diag_suppress=Pa082
124           #endif
125           *(volatile uint32_t *)NRF_FICR_S->TRIMCNF[index].ADDR = NRF_FICR_S->TRIMCNF[index].DATA;
126           #if defined ( __ICCARM__ )
127               #pragma diag_default=Pa082
128           #endif
129         }
130 
131         /* Set UICR->HFXOSRC and UICR->HFXOCNT to working defaults if UICR was erased */
132         if (uicr_HFXOSRC_erased() || uicr_HFXOCNT_erased()) {
133           /* Wait for pending NVMC operations to finish */
134           while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
135 
136           /* Enable write mode in NVMC */
137           NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Wen;
138           while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
139 
140           if (uicr_HFXOSRC_erased()){
141             /* Write default value to UICR->HFXOSRC */
142             uicr_erased_value = NRF_UICR_S->HFXOSRC;
143             uicr_new_value = (uicr_erased_value & ~UICR_HFXOSRC_HFXOSRC_Msk) | UICR_HFXOSRC_HFXOSRC_TCXO;
144             NRF_UICR_S->HFXOSRC = uicr_new_value;
145             while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
146           }
147 
148           if (uicr_HFXOCNT_erased()){
149             /* Write default value to UICR->HFXOCNT */
150             uicr_erased_value = NRF_UICR_S->HFXOCNT;
151             uicr_new_value = (uicr_erased_value & ~UICR_HFXOCNT_HFXOCNT_Msk) | 0x20;
152             NRF_UICR_S->HFXOCNT = uicr_new_value;
153             while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
154           }
155 
156           /* Enable read mode in NVMC */
157           NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Ren;
158           while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
159 
160           /* Reset to apply clock select update */
161           NVIC_SystemReset();
162         }
163 
164         /* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product
165            Specification to see which ones). */
166         #if defined (ENABLE_TRACE)
167             // Enable Trace And Debug peripheral
168             NRF_TAD_S->ENABLE = TAD_ENABLE_ENABLE_Msk;
169             NRF_TAD_S->CLOCKSTART = TAD_CLOCKSTART_START_Msk;
170 
171             // Set up Trace pads SPU firewall
172             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1 << TRACE_TRACECLK_PIN);
173             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1 << TRACE_TRACEDATA0_PIN);
174             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1 << TRACE_TRACEDATA1_PIN);
175             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1 << TRACE_TRACEDATA2_PIN);
176             NRF_SPU_S->GPIOPORT[0].PERM &= ~(1 << TRACE_TRACEDATA3_PIN);
177 
178             // Configure trace port pads
179             NRF_P0_S->PIN_CNF[TRACE_TRACECLK_PIN] =   TRACE_PIN_CNF_VALUE;
180             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA0_PIN] = TRACE_PIN_CNF_VALUE;
181             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA1_PIN] = TRACE_PIN_CNF_VALUE;
182             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA2_PIN] = TRACE_PIN_CNF_VALUE;
183             NRF_P0_S->PIN_CNF[TRACE_TRACEDATA3_PIN] = TRACE_PIN_CNF_VALUE;
184 
185             // Select trace pins
186             NRF_TAD_S->PSEL.TRACECLK   = TRACE_TRACECLK_PIN;
187             NRF_TAD_S->PSEL.TRACEDATA0 = TRACE_TRACEDATA0_PIN;
188             NRF_TAD_S->PSEL.TRACEDATA1 = TRACE_TRACEDATA1_PIN;
189             NRF_TAD_S->PSEL.TRACEDATA2 = TRACE_TRACEDATA2_PIN;
190             NRF_TAD_S->PSEL.TRACEDATA3 = TRACE_TRACEDATA3_PIN;
191 
192             // Set trace port speed to 32 MHz
193             NRF_TAD_S->TRACEPORTSPEED = TAD_TRACEPORTSPEED_TRACEPORTSPEED_32MHz;
194 
195             *((uint32_t *)(0xE0053000ul)) = 0x00000001ul;
196 
197             *((uint32_t *)(0xE005AFB0ul))  = 0xC5ACCE55ul;
198             *((uint32_t *)(0xE005A000ul)) &= 0xFFFFFF00ul;
199             *((uint32_t *)(0xE005A004ul))  = 0x00000009ul;
200             *((uint32_t *)(0xE005A000ul))  = 0x00000303ul;
201             *((uint32_t *)(0xE005AFB0ul))  = 0x00000000ul;
202 
203             *((uint32_t *)(0xE005BFB0ul))  = 0xC5ACCE55ul;
204             *((uint32_t *)(0xE005B000ul)) &= 0xFFFFFF00ul;
205             *((uint32_t *)(0xE005B004ul))  = 0x00003000ul;
206             *((uint32_t *)(0xE005B000ul))  = 0x00000308ul;
207             *((uint32_t *)(0xE005BFB0ul))  = 0x00000000ul;
208 
209             *((uint32_t *)(0xE0058FB0ul)) = 0xC5ACCE55ul;
210             *((uint32_t *)(0xE0058000ul)) = 0x00000000ul;
211             *((uint32_t *)(0xE0058004ul)) = 0x00000000ul;
212             *((uint32_t *)(0xE0058FB0ul)) = 0x00000000ul;
213 
214             /* Rom table does not list ETB, or TPIU base addresses.
215              * Some debug probes may require manual configuration of these peripherals to enable tracing.
216              * ETB_BASE = 0xE0051000
217              * TPIU_BASE = 0xE0054000
218              */
219         #endif
220 
221         /* Allow Non-Secure code to run FPU instructions.
222          * If only the secure code should control FPU power state these registers should be configured accordingly in the secure application code. */
223         SCB->NSACR |= (3UL << 10);
224     #endif
225 
226     /* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the
227     * compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit
228     * operations are not used in your code. */
229     #if (__FPU_USED == 1)
230       SCB->CPACR |= (3UL << 20) | (3UL << 22);
231       __DSB();
232       __ISB();
233     #endif
234 
235     SystemCoreClockUpdate();
236 }
237 
238 
239 #if !defined(NRF_TRUSTZONE_NONSECURE)
240 
uicr_HFXOCNT_erased()241     bool uicr_HFXOCNT_erased()
242     {
243         if (NRF_UICR_S->HFXOCNT == 0xFFFFFFFFul) {
244             return true;
245         }
246         return false;
247     }
248 
249 
uicr_HFXOSRC_erased()250     bool uicr_HFXOSRC_erased()
251     {
252         if ((NRF_UICR_S->HFXOSRC & UICR_HFXOSRC_HFXOSRC_Msk) != UICR_HFXOSRC_HFXOSRC_TCXO) {
253             return true;
254         }
255         return false;
256     }
257 #endif
258 
259 /*lint --flb "Leave library region" */
260