1 /*******************************************************************************
\r
2 * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
\r
5 * @author Microsemi SoC Products Group
\r
6 * @brief Mi-V soft processor PLIC and PRCI access data structures and functions.
\r
8 * SVN $Revision: 9838 $
\r
9 * SVN $Date: 2018-03-19 19:22:54 +0530 (Mon, 19 Mar 2018) $
\r
11 #ifndef RISCV_PLIC_H
\r
12 #define RISCV_PLIC_H
\r
16 #include "encoding.h"
\r
22 #define PLIC_NUM_SOURCES 31
\r
23 #define PLIC_NUM_PRIORITIES 0
\r
25 /*==============================================================================
\r
26 * Interrupt numbers:
\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
65 /*==============================================================================
\r
66 * PLIC: Platform Level Interrupt Controller
\r
68 #define PLIC_BASE_ADDR 0x40000000UL
\r
72 volatile uint32_t PRIORITY_THRESHOLD;
\r
73 volatile uint32_t CLAIM_COMPLETE;
\r
74 volatile uint32_t reserved[1022];
\r
79 volatile uint32_t ENABLES[32];
\r
80 } Target_Enables_Type;
\r
84 /*-------------------- Source Priority --------------------*/
\r
85 volatile uint32_t SOURCE_PRIORITY[1024];
\r
87 /*-------------------- Pending array --------------------*/
\r
88 volatile const uint32_t PENDING_ARRAY[32];
\r
89 volatile uint32_t RESERVED1[992];
\r
91 /*-------------------- Target enables --------------------*/
\r
92 volatile Target_Enables_Type TARGET_ENABLES[15808];
\r
94 volatile uint32_t RESERVED2[16384];
\r
96 /*--- Target Priority threshold and claim/complete---------*/
\r
97 IRQ_Target_Type TARGET[15872];
\r
102 #define PLIC ((PLIC_Type *)PLIC_BASE_ADDR)
\r
104 /*==============================================================================
\r
105 * PRCI: Power, Reset, Clock, Interrupt
\r
107 #define PRCI_BASE 0x44000000UL
\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
117 #define PRCI ((PRCI_Type *)PRCI_BASE)
\r
119 /*==============================================================================
\r
120 * The function PLIC_init() initializes the PLIC controller and enables the
\r
121 * global external interrupt bit.
\r
123 static inline void PLIC_init(void)
\r
126 unsigned long hart_id = read_csr(mhartid);
\r
128 /* Disable all interrupts for the current hart. */
\r
129 for(inc = 0; inc < ((PLIC_NUM_SOURCES + 32u) / 32u); ++inc)
\r
131 PLIC->TARGET_ENABLES[hart_id].ENABLES[inc] = 0;
\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
139 PLIC->SOURCE_PRIORITY[inc] = 0;
\r
142 /* Set the threshold to zero. */
\r
143 PLIC->TARGET[hart_id].PRIORITY_THRESHOLD = 0;
\r
145 /* Enable machine external interrupts. */
\r
146 // set_csr(mie, MIP_MEIP);
\r
149 /*==============================================================================
\r
150 * The function PLIC_EnableIRQ() enables the external interrupt for the interrupt
\r
151 * number indicated by the parameter IRQn.
\r
153 static inline void PLIC_EnableIRQ(IRQn_Type IRQn)
\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
161 /*==============================================================================
\r
162 * The function PLIC_DisableIRQ() disables the external interrupt for the interrupt
\r
163 * number indicated by the parameter IRQn.
\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
173 static inline void PLIC_DisableIRQ(IRQn_Type IRQn)
\r
175 unsigned long hart_id = read_csr(mhartid);
\r
176 uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];
\r
178 current &= ~((uint32_t)1 << (IRQn % 32));
\r
180 PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;
\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
187 static inline void PLIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
\r
189 PLIC->SOURCE_PRIORITY[IRQn] = priority;
\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
196 static inline uint32_t PLIC_GetPriority(IRQn_Type IRQn)
\r
198 return PLIC->SOURCE_PRIORITY[IRQn];
\r
201 /*==============================================================================
\r
202 * The function PLIC_ClaimIRQ() claims the interrupt from the PLIC controller.
\r
204 static inline uint32_t PLIC_ClaimIRQ(void)
\r
206 unsigned long hart_id = read_csr(mhartid);
\r
208 return PLIC->TARGET[hart_id].CLAIM_COMPLETE;
\r
211 /*==============================================================================
\r
212 * The function PLIC_CompleteIRQ() indicates to the PLIC controller the interrupt
\r
213 * is processed and claim is complete.
\r
215 static inline void PLIC_CompleteIRQ(uint32_t source)
\r
217 unsigned long hart_id = read_csr(mhartid);
\r
219 PLIC->TARGET[hart_id].CLAIM_COMPLETE = source;
\r
222 /*==============================================================================
\r
223 * The function raise_soft_interrupt() raises a synchronous software interrupt by
\r
224 * writing into the MSIP register.
\r
226 static inline void raise_soft_interrupt()
\r
228 unsigned long hart_id = read_csr(mhartid);
\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
235 /*==============================================================================
\r
236 * The function clear_soft_interrupt() clears a synchronous software interrupt by
\r
237 * clearing the MSIP register.
\r
239 static inline void clear_soft_interrupt()
\r
241 unsigned long hart_id = read_csr(mhartid);
\r
242 PRCI->MSIP[hart_id] = 0x00; /*clear soft interrupt for hart0*/
\r
249 #endif /* RISCV_PLIC_H */
\r