1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
4 *
5 */
6
7 #include "tfm_hal_device_header.h"
8 #include "Driver_Flash_RPI.h"
9 #include "RTE_Device.h"
10
11 #include "armv8m_mpu.h"
12
13 #ifdef TFM_MULTI_CORE_TOPOLOGY
14 #include "platform_multicore.h"
15 #include "hardware/structs/sio.h"
16 #endif
17
18 #if (RTE_FLASH0)
19
20 #define RP2350_FLASH_PAGE_SIZE 0x100 /* 256B */
21 #define RP2350_FLASH_SECTOR_SIZE 0x1000 /* 4KB */
22 #define RP2350_FLASH_SIZE PICO_FLASH_SIZE_BYTES
23 #define RP2350_FLASH_ERASE_VALUE 0xFF
24
25 static ARM_FLASH_INFO RP2350_FLASH_DEV_DATA = {
26 .sector_info = NULL, /* Uniform sector layout */
27 .sector_count = RP2350_FLASH_SIZE/ RP2350_FLASH_SECTOR_SIZE,
28 .sector_size = RP2350_FLASH_SECTOR_SIZE,
29 .page_size = RP2350_FLASH_PAGE_SIZE,
30 .program_unit = RP2350_FLASH_PAGE_SIZE, /* page aligned, page multipled */
31 .erased_value = RP2350_FLASH_ERASE_VALUE
32 };
33
34 #define MPU_REGION_NUMBER 8
35 #define SEC_STATE_NUM 2
36
37 struct mpu_state_save {
38 uint32_t mpu;
39 uint32_t shcsr;
40 uint32_t mair[2];
41 ARM_MPU_Region_t mpu_table[MPU_REGION_NUMBER];
42 };
43
44 static struct mpu_state_save mpu_state[SEC_STATE_NUM];
45 static uint32_t irq_state = 0;
46 MPU_Type* mpu_p[SEC_STATE_NUM] = {MPU, MPU_NS};
47 SCB_Type* scb_p[SEC_STATE_NUM] = {SCB, SCB_NS};
48
__save_disable_irq(void)49 static inline uint32_t __save_disable_irq(void)
50 {
51 uint32_t result = 0;
52
53 /* Claim lock of Flash */
54 #ifdef TFM_MULTI_CORE_TOPOLOGY
55 while(!*FLASH_SPINLOCK);
56 #endif
57 __ASM volatile ("mrs %0, primask \n cpsid i" : "=r" (result) :: "memory");
58 #ifdef TFM_MULTI_CORE_TOPOLOGY
59 /* Signal Core1 to wait for flash */
60 sio_hw->doorbell_out_set = FLASH_DOORBELL_MASK;
61 if (CORE1_RUNNING)
62 {
63 /* Wait for Core1 to clear doorbell */
64 while(sio_hw->doorbell_out_set & FLASH_DOORBELL_MASK);
65 }
66 #endif
67 return result;
68 }
69
__restore_irq(uint32_t status)70 static inline void __restore_irq(uint32_t status)
71 {
72 __ASM volatile ("msr primask, %0" :: "r" (status) : "memory");
73 /* Release lock of Flash */
74 #ifdef TFM_MULTI_CORE_TOPOLOGY
75 *FLASH_SPINLOCK = 0x1;
76 #endif
77 }
78
79 /* This function must be placed in RAM, so when MPU configuration is saved and
80 flash is protected by a non-executable region MemManageFault is avoided.
81 Since PRIVDEFENA is set the system memory map is enabled for privileged code
82 and execution from RAM is available */
__not_in_flash_func(mpu_state_save)83 static void __not_in_flash_func(mpu_state_save)
84 (struct rp2350_flash_dev_t* flash_dev)
85 {
86 static const uint8_t mpu_attr_num = 0;
87 uint32_t memory_base = flash_dev->base;
88 uint32_t memory_limit = flash_dev->base + flash_dev->size -1;
89
90 irq_state = __save_disable_irq();
91
92 for(int i=0; i<SEC_STATE_NUM; i++) {
93
94 mpu_state[i].shcsr = scb_p[i]->SHCSR;
95 mpu_state[i].mpu = mpu_p[i]->CTRL;
96
97 if(mpu_p[i] == MPU) {
98 ARM_MPU_Disable();
99 } else {
100 ARM_MPU_Disable_NS();
101 }
102
103 for(uint8_t j = 0; j < MPU_REGION_NUMBER; j++) {
104 mpu_p[i]->RNR = j;
105 mpu_state[i].mpu_table[j].RBAR = mpu_p[i]->RBAR;
106 mpu_state[i].mpu_table[j].RLAR = mpu_p[i]->RLAR;
107 mpu_p[i]->RBAR = 0;
108 mpu_p[i]->RLAR = 0;
109 }
110
111 mpu_state[i].mair[0] = mpu_p[i]->MAIR[0];
112 mpu_state[i].mair[1] = mpu_p[i]->MAIR[1];
113
114 mpu_p[i]->MAIR[0] = 0;
115 mpu_p[i]->MAIR[1] = 0;
116
117 /* Attr0 : Device memory, nGnRE */
118 if(mpu_p[i] == MPU) {
119 ARM_MPU_SetMemAttr(mpu_attr_num,
120 ARM_MPU_ATTR(ARM_MPU_ATTR_DEVICE,
121 ARM_MPU_ATTR_DEVICE_nGnRE));
122 } else {
123 ARM_MPU_SetMemAttr_NS(mpu_attr_num,
124 ARM_MPU_ATTR(ARM_MPU_ATTR_DEVICE,
125 ARM_MPU_ATTR_DEVICE_nGnRE));
126 }
127
128 mpu_p[i]->RNR = 0;
129 mpu_p[i]->RBAR = ARM_MPU_RBAR(memory_base,
130 ARM_MPU_SH_NON,
131 1,
132 0,
133 1);
134 #ifdef TFM_PXN_ENABLE
135 mpu_p[i]->RLAR = ARM_MPU_RLAR_PXN(memory_limit, 1, mpu_attr_num);
136 #else
137 mpu_p[i]->RLAR = ARM_MPU_RLAR(memory_limit, mpu_attr_num);
138 #endif
139
140 if(mpu_p[i] == MPU) {
141 ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
142 } else {
143 ARM_MPU_Enable_NS(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
144 }
145 }
146 }
147
__not_in_flash_func(mpu_state_restore)148 static void __not_in_flash_func(mpu_state_restore)(void)
149 {
150 for(int i=0; i<SEC_STATE_NUM; i++) {
151
152 if(mpu_p[i] == MPU) {
153 ARM_MPU_Disable();
154 } else {
155 ARM_MPU_Disable_NS();
156 }
157
158 for(uint8_t j = 0; j < MPU_REGION_NUMBER; j++) {
159 mpu_p[i]->RNR = j;
160 mpu_p[i]->RBAR = mpu_state[i].mpu_table[j].RBAR;
161 mpu_p[i]->RLAR = mpu_state[i].mpu_table[j].RLAR;
162 }
163
164 mpu_p[i]->MAIR[0] = mpu_state[i].mair[0];
165 mpu_p[i]->MAIR[1] = mpu_state[i].mair[1];
166
167 __DMB();
168 mpu_p[i]->CTRL = mpu_state[i].mpu;
169 #ifdef SCB_SHCSR_MEMFAULTENA_Msk
170 scb_p[i]->SHCSR = mpu_state[i].shcsr;
171 #endif
172 __DSB();
173 __ISB();
174
175 }
176
177 __restore_irq(irq_state);
178 }
179
180 static rp2350_flash_dev_t RP2350_FLASH_DEV = {
181 .data = &RP2350_FLASH_DEV_DATA,
182 .base = XIP_BASE,
183 .size = RP2350_FLASH_SIZE,
184 .save_mpu_state = mpu_state_save,
185 .restore_mpu_state = mpu_state_restore
186 };
187
188
189 RPI_RP2350_FLASH(RP2350_FLASH_DEV, RP2350_FLASH);
190 #endif /* RTE_FLASH0 */
191