]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_plic.h
Backup checkin of MiFive demo running in ReNode emulator.
[freertos] / FreeRTOS / Demo / RISC-V_IGLOO2_Creative_SoftConsole / riscv_hal / riscv_plic.h
1 /*******************************************************************************\r
2  * (c) Copyright 2016-2018 Microsemi SoC Products Group.  All rights reserved.\r
3  *\r
4  * @file riscv_plic.h\r
5  * @author Microsemi SoC Products Group\r
6  * @brief Mi-V soft processor PLIC and PRCI access data structures and functions.\r
7  *\r
8  * SVN $Revision: 9838 $\r
9  * SVN $Date: 2018-03-19 19:22:54 +0530 (Mon, 19 Mar 2018) $\r
10  */\r
11 #ifndef RISCV_PLIC_H\r
12 #define RISCV_PLIC_H\r
13 \r
14 #include <stdint.h>\r
15 \r
16 #include "encoding.h"\r
17 \r
18 #ifdef __cplusplus\r
19 extern "C" {\r
20 #endif\r
21 \r
22 #define PLIC_NUM_SOURCES 31\r
23 #define PLIC_NUM_PRIORITIES 0\r
24 \r
25 /*==============================================================================\r
26  * Interrupt numbers:\r
27  */\r
28 typedef enum\r
29 {\r
30     NoInterrupt_IRQn = 0,\r
31     External_1_IRQn  = 1,\r
32     External_2_IRQn  = 2,\r
33     External_3_IRQn  = 3, \r
34     External_4_IRQn  = 4,\r
35     External_5_IRQn  = 5,\r
36     External_6_IRQn  = 6,\r
37     External_7_IRQn  = 7,\r
38     External_8_IRQn  = 8,\r
39     External_9_IRQn  = 9,\r
40     External_10_IRQn = 10,\r
41     External_11_IRQn = 11,\r
42     External_12_IRQn = 12,\r
43     External_13_IRQn = 13,\r
44     External_14_IRQn = 14,\r
45     External_15_IRQn = 15,\r
46     External_16_IRQn = 16,\r
47     External_17_IRQn = 17,\r
48     External_18_IRQn = 18,\r
49     External_19_IRQn = 19,\r
50     External_20_IRQn = 20,\r
51     External_21_IRQn = 21,\r
52     External_22_IRQn = 22,\r
53     External_23_IRQn = 23,\r
54     External_24_IRQn = 24,\r
55     External_25_IRQn = 25,\r
56     External_26_IRQn = 26,\r
57     External_27_IRQn = 27,\r
58     External_28_IRQn = 28,\r
59     External_29_IRQn = 29,\r
60     External_30_IRQn = 30,\r
61     External_31_IRQn = 31\r
62 } IRQn_Type;\r
63 \r
64 \r
65 /*==============================================================================\r
66  * PLIC: Platform Level Interrupt Controller\r
67  */\r
68 #define PLIC_BASE_ADDR 0x40000000UL\r
69 \r
70 typedef struct\r
71 {\r
72     volatile uint32_t PRIORITY_THRESHOLD;\r
73     volatile uint32_t CLAIM_COMPLETE;\r
74     volatile uint32_t reserved[1022];\r
75 } IRQ_Target_Type;\r
76 \r
77 typedef struct\r
78 {\r
79     volatile uint32_t ENABLES[32];\r
80 } Target_Enables_Type;\r
81 \r
82 typedef struct\r
83 {\r
84     /*-------------------- Source Priority --------------------*/\r
85     volatile uint32_t SOURCE_PRIORITY[1024];\r
86     \r
87     /*-------------------- Pending array --------------------*/\r
88     volatile const uint32_t PENDING_ARRAY[32];\r
89     volatile uint32_t RESERVED1[992];\r
90     \r
91     /*-------------------- Target enables --------------------*/\r
92     volatile Target_Enables_Type TARGET_ENABLES[15808];\r
93 \r
94     volatile uint32_t RESERVED2[16384];\r
95     \r
96     /*--- Target Priority threshold and claim/complete---------*/\r
97     IRQ_Target_Type TARGET[15872];\r
98     \r
99 } PLIC_Type;\r
100 \r
101 \r
102 #define PLIC    ((PLIC_Type *)PLIC_BASE_ADDR)\r
103 \r
104 /*==============================================================================\r
105  * PRCI: Power, Reset, Clock, Interrupt\r
106  */\r
107 #define PRCI_BASE   0x44000000UL\r
108 \r
109 typedef struct\r
110 {\r
111     volatile uint32_t MSIP[4095];\r
112     volatile uint32_t reserved;\r
113     volatile uint64_t MTIMECMP[4095];\r
114     volatile const uint64_t MTIME;\r
115 } PRCI_Type;\r
116 \r
117 #define PRCI    ((PRCI_Type *)PRCI_BASE) \r
118 \r
119 /*==============================================================================\r
120  * The function PLIC_init() initializes the PLIC controller and enables the \r
121  * global external interrupt bit.\r
122  */\r
123 static inline void PLIC_init(void)\r
124 {\r
125     uint32_t inc;\r
126     unsigned long hart_id = read_csr(mhartid);\r
127 \r
128     /* Disable all interrupts for the current hart. */\r
129     for(inc = 0; inc < ((PLIC_NUM_SOURCES + 32u) / 32u); ++inc)\r
130     {\r
131         PLIC->TARGET_ENABLES[hart_id].ENABLES[inc] = 0;\r
132     }\r
133 \r
134     /* Set priorities to zero. */\r
135     /* Should this really be done??? Calling PLIC_init() on one hart will cause\r
136     * the priorities previously set by other harts to be messed up. */\r
137     for(inc = 0; inc < PLIC_NUM_SOURCES; ++inc)\r
138     {\r
139         PLIC->SOURCE_PRIORITY[inc] = 0;\r
140     }\r
141 \r
142     /* Set the threshold to zero. */\r
143     PLIC->TARGET[hart_id].PRIORITY_THRESHOLD = 0;\r
144 \r
145     /* Enable machine external interrupts. */\r
146 //    set_csr(mie, MIP_MEIP);\r
147 }\r
148 \r
149 /*==============================================================================\r
150  * The function PLIC_EnableIRQ() enables the external interrupt for the interrupt\r
151  * number indicated by the parameter IRQn.\r
152  */\r
153 static inline void PLIC_EnableIRQ(IRQn_Type IRQn)\r
154 {\r
155     unsigned long hart_id = read_csr(mhartid);\r
156     uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];\r
157     current |= (uint32_t)1 << (IRQn % 32);\r
158     PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;\r
159 }\r
160 \r
161 /*==============================================================================\r
162  * The function PLIC_DisableIRQ() disables the external interrupt for the interrupt\r
163  * number indicated by the parameter IRQn.\r
164 \r
165  * NOTE:\r
166  *      This function can be used to disable the external interrupt from outside\r
167  *      external interrupt handler function.\r
168  *      This function MUST NOT be used from within the External Interrupt handler.\r
169  *      If you wish to disable the external interrupt while the interrupt handler\r
170  *      for that external interrupt is executing then you must use the return value\r
171  *      EXT_IRQ_DISABLE to return from the extern interrupt handler.\r
172  */\r
173 static inline void PLIC_DisableIRQ(IRQn_Type IRQn)\r
174 {\r
175     unsigned long hart_id = read_csr(mhartid);\r
176     uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];\r
177 \r
178     current &= ~((uint32_t)1 << (IRQn % 32));\r
179 \r
180     PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;\r
181 }\r
182 \r
183 /*==============================================================================\r
184  * The function PLIC_SetPriority() sets the priority for the external interrupt \r
185  * for the interrupt number indicated by the parameter IRQn.\r
186  */\r
187 static inline void PLIC_SetPriority(IRQn_Type IRQn, uint32_t priority) \r
188 {\r
189     PLIC->SOURCE_PRIORITY[IRQn] = priority;\r
190 }\r
191 \r
192 /*==============================================================================\r
193  * The function PLIC_GetPriority() returns the priority for the external interrupt \r
194  * for the interrupt number indicated by the parameter IRQn.\r
195  */\r
196 static inline uint32_t PLIC_GetPriority(IRQn_Type IRQn)\r
197 {\r
198     return PLIC->SOURCE_PRIORITY[IRQn];\r
199 }\r
200 \r
201 /*==============================================================================\r
202  * The function PLIC_ClaimIRQ() claims the interrupt from the PLIC controller.\r
203  */\r
204 static inline uint32_t PLIC_ClaimIRQ(void)\r
205 {\r
206     unsigned long hart_id = read_csr(mhartid);\r
207 \r
208     return PLIC->TARGET[hart_id].CLAIM_COMPLETE;\r
209 }\r
210 \r
211 /*==============================================================================\r
212  * The function PLIC_CompleteIRQ() indicates to the PLIC controller the interrupt\r
213  * is processed and claim is complete.\r
214  */\r
215 static inline void PLIC_CompleteIRQ(uint32_t source)\r
216 {\r
217     unsigned long hart_id = read_csr(mhartid);\r
218 \r
219     PLIC->TARGET[hart_id].CLAIM_COMPLETE = source;\r
220 }\r
221 \r
222 /*==============================================================================\r
223  * The function raise_soft_interrupt() raises a synchronous software interrupt by\r
224  * writing into the MSIP register.\r
225  */\r
226 static inline void raise_soft_interrupt()\r
227 {\r
228     unsigned long hart_id = read_csr(mhartid);\r
229 \r
230     /*You need to make sure that the global interrupt is enabled*/\r
231     set_csr(mie, MIP_MSIP);       /*Enable software interrupt bit */\r
232     PRCI->MSIP[hart_id] = 0x01;   /*raise soft interrupt for hart0*/\r
233 }\r
234 \r
235 /*==============================================================================\r
236  * The function clear_soft_interrupt() clears a synchronous software interrupt by\r
237  * clearing the MSIP register.\r
238  */\r
239 static inline void clear_soft_interrupt()\r
240 {\r
241     unsigned long hart_id = read_csr(mhartid);\r
242     PRCI->MSIP[hart_id] = 0x00;   /*clear soft interrupt for hart0*/\r
243 }\r
244 \r
245 #ifdef __cplusplus\r
246 }\r
247 #endif\r
248 \r
249 #endif  /* RISCV_PLIC_H */\r