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