NMSIS-Core  Version 1.4.0
NMSIS-Core support for Nuclei processor-based devices
core_feature_pma.h
1 /*
2  * Copyright (c) 2019 Nuclei Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #ifndef __CORE_FEATURE_PMA_H__
19 #define __CORE_FEATURE_PMA_H__
25 #ifdef __cplusplus
26  extern "C" {
27 #endif
28 
29 #include "core_compatiable.h"
30 
31 #if defined(__PMA_PRESENT) && (__PMA_PRESENT==1)
32 
33 /* ===== PMA functions ===== */
53 #define PMA_REGION_TYPE_SECSHARE (1UL << 3)
54 #define PMA_REGION_TYPE_NC (1UL << 2)
55 #define PMA_REGION_TYPE_DEV (1UL << 1)
56 #define PMA_REGION_TYPE_CA (0)
57 #define PMA_REGION_ENA (1UL << 0)
58 #define PMA_REGION_DIS (0)
60 typedef struct PMA_CONFIG {
64  unsigned long region_base;
68  unsigned long region_size;
75  uint16_t region_type;
79  uint16_t region_enable;
80 } pma_config;
81 
99 __STATIC_FORCEINLINE long PMA_SetRegion(unsigned long entry_idx, pma_config *pma_cfg)
100 {
101  // 4KB aligned
102  unsigned long size = (pma_cfg->region_size >> 12) << 12;
103  unsigned long base_addr = (pma_cfg->region_base >> 12) << 12;
104 
105  if ((entry_idx + 1) > __PMA_CSR_NUM) {
106  return -1;
107  }
108 
109  rv_csr_t mask = (unsigned long)(~(size - 1));
110  rv_csr_t base = pma_cfg->region_type | base_addr | pma_cfg->region_enable;
111 
112  switch (entry_idx) {
113  // Bit[MXLEN-1:PA_SIZE] of mattri(n)_mask is reserved 0
114  case 0: __RV_CSR_WRITE(CSR_MATTRI0_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI0_BASE, base); break;
115  case 1: __RV_CSR_WRITE(CSR_MATTRI1_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI1_BASE, base); break;
116  case 2: __RV_CSR_WRITE(CSR_MATTRI2_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI2_BASE, base); break;
117  case 3: __RV_CSR_WRITE(CSR_MATTRI3_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI3_BASE, base); break;
118  case 4: __RV_CSR_WRITE(CSR_MATTRI4_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI4_BASE, base); break;
119  case 5: __RV_CSR_WRITE(CSR_MATTRI5_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI5_BASE, base); break;
120  case 6: __RV_CSR_WRITE(CSR_MATTRI6_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI6_BASE, base); break;
121  case 7: __RV_CSR_WRITE(CSR_MATTRI7_MASK, mask); __RV_CSR_WRITE(CSR_MATTRI7_BASE, base); break;
122  default: return -1;
123  }
124 
125  return 0;
126 }
127 
139 __STATIC_FORCEINLINE long PMA_GetRegion(unsigned long entry_idx, pma_config *pma_cfg)
140 {
141  rv_csr_t mask, base;
142  uint32_t mpasize = *(uint32_t *)__IINFO_MPASIZE_ADDR;
143 
144  if ((entry_idx + 1) > __PMA_CSR_NUM) {
145  return -1;
146  }
147 
148  switch (entry_idx) {
149  case 0: mask = __RV_CSR_READ(CSR_MATTRI0_MASK); base = __RV_CSR_READ(CSR_MATTRI0_BASE); break;
150  case 1: mask = __RV_CSR_READ(CSR_MATTRI1_MASK); base = __RV_CSR_READ(CSR_MATTRI1_BASE); break;
151  case 2: mask = __RV_CSR_READ(CSR_MATTRI2_MASK); base = __RV_CSR_READ(CSR_MATTRI2_BASE); break;
152  case 3: mask = __RV_CSR_READ(CSR_MATTRI3_MASK); base = __RV_CSR_READ(CSR_MATTRI3_BASE); break;
153  case 4: mask = __RV_CSR_READ(CSR_MATTRI4_MASK); base = __RV_CSR_READ(CSR_MATTRI4_BASE); break;
154  case 5: mask = __RV_CSR_READ(CSR_MATTRI5_MASK); base = __RV_CSR_READ(CSR_MATTRI5_BASE); break;
155  case 6: mask = __RV_CSR_READ(CSR_MATTRI6_MASK); base = __RV_CSR_READ(CSR_MATTRI6_BASE); break;
156  case 7: mask = __RV_CSR_READ(CSR_MATTRI7_MASK); base = __RV_CSR_READ(CSR_MATTRI7_BASE); break;
157  default: return -1;
158  }
159 
160  pma_cfg->region_type = (unsigned long)(base & 0x0E);
161  pma_cfg->region_base = (unsigned long)((base >> 12) << 12);
162  pma_cfg->region_size = (unsigned long)(1UL << (mask == 0 ? mpasize : __CTZ(mask)));
163  pma_cfg->region_enable = (uint16_t)(base & 0x01);
164 
165  return 0;
166 }
167 
181 __STATIC_FORCEINLINE long PMA_SetRegion_S(unsigned long entry_idx, pma_config *pma_cfg)
182 {
183  // 4KB aligned
184  unsigned long size = (pma_cfg->region_size >> 12) << 12;
185  unsigned long base_addr = (pma_cfg->region_base >> 12) << 12;
186 
187  if ((entry_idx + 1) > __PMA_SEC_CSR_NUM) {
188  return -1;
189  }
190 
191  rv_csr_t mask = (unsigned long)(~(size - 1));
192  rv_csr_t base = base_addr | pma_cfg->region_enable;
193 
194  switch (entry_idx) {
195  // Bit[MXLEN-1:PA_SIZE] of sattri(n)_mask is reserved 0
196  case 0: __RV_CSR_WRITE(CSR_SATTRI0_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI0_BASE, base); break;
197  case 1: __RV_CSR_WRITE(CSR_SATTRI1_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI1_BASE, base); break;
198  case 2: __RV_CSR_WRITE(CSR_SATTRI2_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI2_BASE, base); break;
199  case 3: __RV_CSR_WRITE(CSR_SATTRI3_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI3_BASE, base); break;
200  case 4: __RV_CSR_WRITE(CSR_SATTRI4_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI4_BASE, base); break;
201  case 5: __RV_CSR_WRITE(CSR_SATTRI5_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI5_BASE, base); break;
202  case 6: __RV_CSR_WRITE(CSR_SATTRI6_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI6_BASE, base); break;
203  case 7: __RV_CSR_WRITE(CSR_SATTRI7_MASK, mask); __RV_CSR_WRITE(CSR_SATTRI7_BASE, base); break;
204  default: return -1;
205  }
206 
207  return 0;
208 }
209 
219 __STATIC_FORCEINLINE long PMA_GetRegion_S(unsigned long entry_idx, pma_config *pma_cfg)
220 {
221  rv_csr_t mask, base;
222  uint32_t mpasize = *(uint32_t *)__IINFO_MPASIZE_ADDR;
223 
224  if ((entry_idx + 1) > __PMA_SEC_CSR_NUM) {
225  return -1;
226  }
227 
228  switch (entry_idx) {
229  case 0: mask = __RV_CSR_READ(CSR_SATTRI0_MASK); base = __RV_CSR_READ(CSR_SATTRI0_BASE); break;
230  case 1: mask = __RV_CSR_READ(CSR_SATTRI1_MASK); base = __RV_CSR_READ(CSR_SATTRI1_BASE); break;
231  case 2: mask = __RV_CSR_READ(CSR_SATTRI2_MASK); base = __RV_CSR_READ(CSR_SATTRI2_BASE); break;
232  case 3: mask = __RV_CSR_READ(CSR_SATTRI3_MASK); base = __RV_CSR_READ(CSR_SATTRI3_BASE); break;
233  case 4: mask = __RV_CSR_READ(CSR_SATTRI4_MASK); base = __RV_CSR_READ(CSR_SATTRI4_BASE); break;
234  case 5: mask = __RV_CSR_READ(CSR_SATTRI5_MASK); base = __RV_CSR_READ(CSR_SATTRI5_BASE); break;
235  case 6: mask = __RV_CSR_READ(CSR_SATTRI6_MASK); base = __RV_CSR_READ(CSR_SATTRI6_BASE); break;
236  case 7: mask = __RV_CSR_READ(CSR_SATTRI7_MASK); base = __RV_CSR_READ(CSR_SATTRI7_BASE); break;
237  default: return -1;
238  }
239 
240  pma_cfg->region_base = (unsigned long)((base >> 12) << 12);
241  pma_cfg->region_size = (unsigned long)(1UL << (mask == 0 ? mpasize : __CTZ(mask)));
242  pma_cfg->region_enable = (uint16_t)(base & 0x01);
243 
244  return 0;
245 }
246 
247 #if defined(__PMA_MACRO_PRESENT) && (__PMA_MACRO_PRESENT == 1)
261 __STATIC_FORCEINLINE void PMA_EnableHwDevRegion(unsigned long entry_idx)
262 {
263  __RV_CSR_SET(CSR_MMACRO_DEV_EN, 1UL << entry_idx);
264 }
265 
279 __STATIC_FORCEINLINE void PMA_DisableHwDevRegion(unsigned long entry_idx)
280 {
281  __RV_CSR_CLEAR(CSR_MMACRO_DEV_EN, 1UL << entry_idx);
282 }
283 
297 __STATIC_FORCEINLINE void PMA_EnableHwNCRegion(unsigned long entry_idx)
298 {
299  __RV_CSR_SET(CSR_MMACRO_NOC_EN, 1UL << entry_idx);
300 }
301 
315 __STATIC_FORCEINLINE void PMA_DisableHwNCRegion(unsigned long entry_idx)
316 {
317  __RV_CSR_CLEAR(CSR_MMACRO_NOC_EN, 1UL << entry_idx);
318 }
319 
333 __STATIC_FORCEINLINE void PMA_EnableHwCARegion(unsigned long entry_idx)
334 {
335  __RV_CSR_SET(CSR_MMACRO_CA_EN, 1UL << entry_idx);
336 }
337 
351 __STATIC_FORCEINLINE void PMA_DisableHwCARegion(unsigned long entry_idx)
352 {
353  __RV_CSR_CLEAR(CSR_MMACRO_CA_EN, 1UL << entry_idx);
354 }
355 #endif /* defined(__PMA_MACRO_PRESENT) && (__PMA_MACRO_PRESENT == 1) */ /* End of Doxygen Group NMSIS_Core_PMA_Functions */
357 #endif /* defined(__PMA_PRESENT) && (__PMA_PRESENT==1) */
358 
359 #ifdef __cplusplus
360 }
361 #endif
362 #endif /* __CORE_FEATURE_PMA_H__ */
__STATIC_FORCEINLINE unsigned long __CTZ(unsigned long data)
Count tailing zero.
#define __RV_CSR_CLEAR(csr, val)
CSR operation Macro for csrc instruction.
#define __RV_CSR_READ(csr)
CSR operation Macro for csrr instruction.
#define __RV_CSR_WRITE(csr, val)
CSR operation Macro for csrw instruction.
#define __RV_CSR_SET(csr, val)
CSR operation Macro for csrs instruction.
#define CSR_MMACRO_CA_EN
#define CSR_SATTRI1_MASK
#define CSR_MATTRI6_BASE
#define CSR_SATTRI1_BASE
#define CSR_MATTRI7_BASE
#define CSR_SATTRI3_MASK
#define CSR_MATTRI4_MASK
#define CSR_SATTRI0_MASK
#define CSR_SATTRI3_BASE
#define CSR_MMACRO_DEV_EN
#define CSR_MATTRI3_MASK
#define CSR_MATTRI5_BASE
#define CSR_SATTRI5_BASE
#define CSR_MATTRI2_BASE
#define CSR_MATTRI3_BASE
#define CSR_MATTRI6_MASK
#define CSR_SATTRI7_MASK
#define CSR_MATTRI2_MASK
#define CSR_SATTRI4_BASE
#define CSR_MATTRI4_BASE
#define CSR_MATTRI5_MASK
#define CSR_MATTRI0_MASK
#define CSR_SATTRI0_BASE
#define CSR_SATTRI5_MASK
#define CSR_SATTRI6_BASE
#define CSR_MATTRI0_BASE
#define CSR_MATTRI7_MASK
#define CSR_SATTRI2_MASK
#define CSR_SATTRI7_BASE
#define CSR_MATTRI1_BASE
#define CSR_MATTRI1_MASK
#define CSR_SATTRI2_BASE
#define CSR_MMACRO_NOC_EN
#define CSR_SATTRI4_MASK
#define CSR_SATTRI6_MASK
#define __STATIC_FORCEINLINE
Define a static function that should be always inlined by the compiler.
Definition: nmsis_gcc.h:70
__STATIC_FORCEINLINE void PMA_EnableHwNCRegion(unsigned long entry_idx)
Enable hardware defined Non-Cacheable regions.
__STATIC_FORCEINLINE void PMA_DisableHwNCRegion(unsigned long entry_idx)
Disable hardware defined Non-Cacheable regions.
__STATIC_FORCEINLINE void PMA_DisableHwCARegion(unsigned long entry_idx)
Disable hardware defined Cacheable regions.
__STATIC_FORCEINLINE long PMA_GetRegion_S(unsigned long entry_idx, pma_config *pma_cfg)
Get the region info of Secure S-Mode world sharing with Non-Secure S-Mode world.
__STATIC_FORCEINLINE void PMA_EnableHwDevRegion(unsigned long entry_idx)
Enable hardware defined Device regions.
__STATIC_FORCEINLINE long PMA_SetRegion(unsigned long entry_idx, pma_config *pma_cfg)
Configure one region in machine mode.
__STATIC_FORCEINLINE void PMA_EnableHwCARegion(unsigned long entry_idx)
Enable hardware defined Cacheable regions.
__STATIC_FORCEINLINE long PMA_GetRegion(unsigned long entry_idx, pma_config *pma_cfg)
Get the region info in machine mode.
__STATIC_FORCEINLINE void PMA_DisableHwDevRegion(unsigned long entry_idx)
Disable hardware defined Device regions.
__STATIC_FORCEINLINE long PMA_SetRegion_S(unsigned long entry_idx, pma_config *pma_cfg)
Configure one region for Secure S-Mode world to share with Non-Secure S-Mode world.
unsigned long rv_csr_t
Type of Control and Status Register(CSR), depends on the XLEN defined in RISC-V.
unsigned long region_base
Base physical address, which needs to be 4K byte aligned.
uint16_t region_type
Type could be PMA_REGION_TYPE_SECSHARE, PMA_REGION_TYPE_NC, PMA_REGION_TYPE_DEV, PMA_REGION_TYPE_CA P...
uint16_t region_enable
Enable or disable the region, could be PMA_REGION_ENA, PMA_REGION_DIS.
unsigned long region_size
Region size, which needs to be 4K byte aligned; the region_base should be integer multiples of region...