1 /*******************************************************************************
2  * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * MPFS HAL Embedded Software
7  *
8  */
9 /*******************************************************************************
10  * @file mss_mpu.h
11  * @author Microchip-FPGA Embedded Systems Solutions
12  * @brief PolarFire SoC MSS MPU driver APIs for configuring access regions for
13  * the external masters.
14  *
15  */
16 /*=========================================================================*//**
17 
18  *//*=========================================================================*/
19 #ifndef MSS_MPU_H
20 #define MSS_MPU_H
21 
22 #include <stdint.h>
23 
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 #ifndef SIFIVE_HIFIVE_UNLEASHED
30 
31 /***************************************************************************//**
32 
33  */
34 #define MPU_MODE_READ_ACCESS       (1U << 0U)
35 #define MPU_MODE_WRITE_ACCESS      (1U << 1U)
36 #define MPU_MODE_EXEC_ACCESS       (1U << 2U)
37 
38 typedef enum {
39     MSS_MPU_FIC0    = 0x00,
40     MSS_MPU_FIC1,
41     MSS_MPU_FIC2,
42     MSS_MPU_CRYPTO,
43     MSS_MPU_GEM0,
44     MSS_MPU_GEM1,
45     MSS_MPU_USB,
46     MSS_MPU_MMC,
47     MSS_MPU_SCB,
48     MSS_MPU_TRACE,
49     MSS_MPU_SEG0,
50     MSS_MPU_SEG1,
51 } mss_mpu_mport_t;
52 
53 typedef enum {
54     MSS_MPU_AM_OFF    = 0x00U,
55     MSS_MPU_AM_NAPOT  = 0x03U,
56 } mss_mpu_addrm_t;
57 
58 typedef enum {
59     MSS_MPU_PMP_REGION0    = 0x00,
60     MSS_MPU_PMP_REGION1,
61     MSS_MPU_PMP_REGION2,
62     MSS_MPU_PMP_REGION3,
63     MSS_MPU_PMP_REGION4,
64     MSS_MPU_PMP_REGION5,
65     MSS_MPU_PMP_REGION6,
66     MSS_MPU_PMP_REGION7,
67     MSS_MPU_PMP_REGION8,
68     MSS_MPU_PMP_REGION9,
69     MSS_MPU_PMP_REGION10,
70     MSS_MPU_PMP_REGION11,
71     MSS_MPU_PMP_REGION12,
72     MSS_MPU_PMP_REGION13,
73     MSS_MPU_PMP_REGION14,
74     MSS_MPU_PMP_REGION15,
75 } mss_mpu_pmp_region_t;
76 
77 extern uint8_t num_pmp_lut[10];
78 
79 #ifndef __I
80 #define __I  const volatile
81 #endif
82 #ifndef __IO
83 #define __IO volatile
84 #endif
85 #ifndef __O
86 #define __O volatile
87 #endif
88 
89 
90 typedef struct {
91     union {
92         struct
93         {
94             __IO uint64_t  pmp   : 38;
95             __IO uint64_t  rsrvd : 18;
96             __IO uint64_t  mode  : 8;
97         } MPUCFG_TypeDef;
98         uint64_t raw;
99     };
100 } MPU_CFG;
101 
102 typedef struct
103 {
104     __IO uint64_t  addr   : 38;
105     __IO uint64_t  rw     : 1;
106     __IO uint64_t  id     : 4;
107     __IO uint64_t  failed : 1;
108     __IO uint64_t  padding : (64-44);
109 } MPU_FailStatus_TypeDef;
110 
111 typedef struct
112 {
113     MPU_CFG               PMPCFG[16U];
114     __IO MPU_FailStatus_TypeDef  STATUS;
115 } MPU_TypeDef;
116 
117 
118 
119 #define MSS_MPU(master)                ( (MPU_TypeDef*) (0x20005000UL + ((master) << 8U)))
120 
121 
122 uint8_t mpu_configure(void);
123 
124 
125 uint8_t MSS_MPU_configure(mss_mpu_mport_t master_port,
126                                         mss_mpu_pmp_region_t pmp_region,
127                                         uint64_t base,
128                                         uint64_t size,
129                                         uint8_t permission,
130                                         mss_mpu_addrm_t matching_mode,
131                                         uint8_t lock_en);
132 
133 uint8_t MSS_MPU_get_config(mss_mpu_mport_t master_port,
134                            mss_mpu_pmp_region_t pmp_region,
135                            uint64_t* base,
136                            uint64_t* size,
137                            uint8_t* permission,
138                            mss_mpu_addrm_t* matching_mode,
139                            uint8_t* lock_en);
140 
MSS_MPU_lock_region(mss_mpu_mport_t master_port,mss_mpu_pmp_region_t pmp_region)141 static inline uint8_t MSS_MPU_lock_region(mss_mpu_mport_t master_port,
142                                         mss_mpu_pmp_region_t pmp_region)
143 {
144     if(pmp_region < num_pmp_lut[master_port])
145     {
146         MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.mode |= (0x1U << 7U);
147         return (0U);
148     }
149     else
150     {
151         return (1U);
152     }
153 }
154 
155 /*permission value could be bitwise or of:
156  * MPU_MODE_READ_ACCESS
157  * MPU_MODE_WRITE_ACCESS
158  * MPU_MODE_EXEC_ACCESS
159  *
160  * */
MSS_MPU_set_permission(mss_mpu_mport_t master_port,mss_mpu_pmp_region_t pmp_region,uint8_t permission)161 static inline uint8_t MSS_MPU_set_permission(mss_mpu_mport_t master_port,
162                                              mss_mpu_pmp_region_t pmp_region,
163                                              uint8_t permission)
164 {
165     if(pmp_region < num_pmp_lut[master_port])
166     {
167         MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.mode |= permission;
168         return (0U);
169     }
170     else
171     {
172         return (1U);
173     }
174 }
175 
MSS_MPU_get_permission(mss_mpu_mport_t master_port,mss_mpu_pmp_region_t pmp_region,uint8_t * permission)176 static inline uint8_t MSS_MPU_get_permission(mss_mpu_mport_t master_port,
177                                              mss_mpu_pmp_region_t pmp_region,
178                                              uint8_t* permission)
179 {
180     if(pmp_region < num_pmp_lut[master_port])
181     {
182         *permission = MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.mode & 0x7U;
183         return (0U);
184     }
185     else
186     {
187         return (1U);
188     }
189 }
190 
191 /*read the Fail status register when there is a MPU access failure.
192  See the return type MPU_FailStatus_TypeDef for the details of the STATUS bitfield.
193  The status failed bit(offset 42) needs to be reset using the corresponding bit
194  in SYSREG->mpu_violation_sr
195  */
MSS_MPU_get_failstatus(mss_mpu_mport_t master_port)196 static inline MPU_FailStatus_TypeDef MSS_MPU_get_failstatus(mss_mpu_mport_t master_port)
197 {
198     return (MSS_MPU(master_port)->STATUS);
199 }
200 
201 #endif /* ! SIFIVE_HIFIVE_UNLEASHED */
202 
203 #ifdef __cplusplus
204 }
205 #endif
206 
207 
208 #endif /* MSS_MPU_H */
209