Software APIs
dif_plic.h
Go to the documentation of this file.
1 // Copyright lowRISC contributors.
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PLIC_H_
6 #define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PLIC_H_
7 
8 /**
9  * @file
10  * @brief <a href="/hw/ip/rv_plic/doc/">PLIC</a> Device Interface Functions
11  *
12  * The PLIC should be largely compatible with the (currently draft) [RISC-V PLIC
13  * specification][plic], but tailored for the OpenTitan rv_plic register
14  * addresses. We intend to make the addresses compatible with the PLIC
15  * specification in the near future.
16  *
17  * [plic]: https://github.com/riscv/riscv-plic-spec/blob/master/riscv-plic.adoc
18  */
19 
20 #include <stdbool.h>
21 #include <stdint.h>
22 
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif // __cplusplus
29 
30 /**
31  * A toggle state: enabled, or disabled.
32  *
33  * This enum may be used instead of a `bool` when describing an enabled/disabled
34  * state.
35  */
36 typedef enum dif_plic_toggle {
37  /*
38  * The "enabled" state.
39  */
40  kDifPlicToggleEnabled,
41  /**
42  * The "disabled" state.
43  */
46 
47 /**
48  * Hardware instantiation parameters for PLIC.
49  *
50  * This struct describes information about the underlying hardware that is
51  * not determined until the hardware design is used as part of a top-level
52  * design.
53  */
54 typedef struct dif_plic_params {
55  /**
56  * The base address for the PLIC hardware registers.
57  */
60 
61 /**
62  * A handle to PLIC.
63  *
64  * This type should be treated as opaque by users.
65  */
66 typedef struct dif_plic {
67  dif_plic_params_t params;
68 } dif_plic_t;
69 
70 /**
71  * The result of a PLIC operation.
72  */
73 typedef enum dif_plic_result {
74  /**
75  * Indicates that the operation succeeded.
76  */
78  /**
79  * Indicates some unspecified failure.
80  */
82  /**
83  * Indicates that some parameter passed into a function failed a
84  * precondition.
85  *
86  * When this value is returned, no hardware operations occurred.
87  */
90 
91 /**
92  * The lowest interrupt priority.
93  */
94 extern const uint32_t kDifPlicMinPriority;
95 
96 /**
97  * The highest interrupt priority.
98  */
99 extern const uint32_t kDifPlicMaxPriority;
100 
101 /**
102  * A PLIC interrupt source identifier.
103  *
104  * This corresponds to a specific interrupt, and not the device it originates
105  * from.
106  *
107  * This is an unsigned 32-bit value that is at least zero and is less than the
108  * `NumSrc` instantiation parameter of the `rv_plic` device.
109  *
110  * The value 0 corresponds to "No Interrupt".
111  */
112 typedef uint32_t dif_plic_irq_id_t;
113 
114 /**
115  * A PLIC interrupt target.
116  *
117  * This corresponds to a specific system that can service an interrupt. In
118  * OpenTitan's case, that is the Ibex core. If there were multiple cores in the
119  * system, each core would have its own specific interrupt target ID.
120  *
121  * This is an unsigned 32-bit value that is at least 0 and is less than the
122  * `NumTarget` instantiation parameter of the `rv_plic` device.
123  */
124 typedef uint32_t dif_plic_target_t;
125 
126 /**
127  * An interrupt trigger type.
128  */
129 typedef enum dif_plic_irq_trigger {
130  /**
131  * Trigger on an edge (when the signal changes from low to high).
132  */
134  /**
135  * Trigger on a level (when the signal remains high).
136  */
139 
140 /**
141  * Creates a new handle for PLIC.
142  *
143  * This function does not actuate the hardware.
144  *
145  * @param params Hardware instantiation parameters.
146  * @param[out] plic Out param for the initialized handle.
147  * @return The result of the operation.
148  */
151 
152 /**
153  * Returns whether a particular interrupt is currently pending.
154  *
155  * @param plic A PLIC handle.
156  * @param irq An interrupt type.
157  * @param[out] is_pending Out-param for whether the interrupt is pending.
158  * @return The result of the operation.
159  */
162  dif_plic_irq_id_t irq,
163  bool *is_pending);
164 
165 /**
166  * Checks whether a particular interrupt is currently enabled or disabled.
167  *
168  * @param plic A PLIC handle.
169  * @param irq An interrupt type.
170  * @param target An interrupt target.
171  * @param[out] state Out-param toggle state of the interrupt.
172  * @return The result of the operation.
173  */
176  dif_plic_irq_id_t irq,
177  dif_plic_target_t target,
178  dif_plic_toggle_t *state);
179 
180 /**
181  * Sets whether a particular interrupt is currently enabled or disabled.
182  *
183  * This operation does not affect IRQ generation in `target`, which
184  * must be configured in the corresponding peripheral itself.
185  *
186  * @param plic A PLIC handle.
187  * @param irq An interrupt type.
188  * @param target An interrupt target.
189  * @param state The new toggle state for the interrupt.
190  * @return The result of the operation.
191  */
194  dif_plic_irq_id_t irq,
195  dif_plic_target_t target,
196  dif_plic_toggle_t state);
197 
198 /**
199  * Sets the IRQ trigger type.
200  *
201  * Sets the behaviour of the Interrupt Gateway for a particular IRQ to be edge
202  * or level triggered.
203  *
204  * @param plic A PLIC handle.
205  * @param irq An interrupt type.
206  * @param trigger A trigger type.
207  * @return The result of the operation.
208  */
211  dif_plic_irq_id_t irq,
212  dif_plic_irq_trigger_t trigger);
213 
214 /**
215  * Sets IRQ source priority (0-3).
216  *
217  * In order for the PLIC to set a Claim/Complete register and assert the
218  * external interrupt line to the target (Ibex, ...), the priority of the IRQ
219  * source must be higher than the threshold for this source.
220  *
221  * @param plic A PLIC handle.
222  * @param irq An interrupt type.
223  * @param priority Priority to set.
224  * @return The result of the operation.
225  */
228  dif_plic_irq_id_t irq,
229  uint32_t priority);
230 
231 /**
232  * Sets the target priority threshold.
233  *
234  * Sets the target priority threshold. PLIC will only interrupt a target when
235  * IRQ source priority is set higher than the priority threshold for the
236  * corresponding target.
237  *
238  * @param plic A PLIC handle.
239  * @param target Target to set the IRQ priority threshold for.
240  * @param threshold IRQ priority threshold to be set.
241  * @return The result of the operation.
242  */
245  dif_plic_target_t target,
246  uint32_t threshold);
247 
248 /**
249  * Claims an IRQ and gets the information about the source.
250  *
251  * Claims an IRQ and returns the IRQ related data to the caller. This function
252  * reads a target specific Claim/Complete register. #dif_plic_irq_complete must
253  * be called in order to allow another interrupt with the same source id to be
254  * delivered. This usually would be done once the interrupt has been serviced.
255  *
256  * Another IRQ can be claimed before a prior IRQ is completed. In this way, this
257  * functionality is compatible with nested interrupt handling. The restriction
258  * is that you must Complete a Claimed IRQ before you will be able to claim an
259  * IRQ with the same ID. This allows a pair of Claim/Complete calls to be
260  * overlapped with another pair -- and there is no requirement that the
261  * interrupts should be Completed in the reverse order of when they were
262  * Claimed.
263  *
264  * @see #dif_plic_irq_complete
265  *
266  * @param plic A PLIC handle.
267  * @param target Target that claimed the IRQ.
268  * @param[out] claim_data Data that describes the origin of the IRQ.
269  * @return The result of the operation.
270  */
273  dif_plic_target_t target,
274  dif_plic_irq_id_t *claim_data);
275 
276 /**
277  * Completes the claimed IRQ.
278  *
279  * Finishes servicing of the claimed IRQ by writing the IRQ source ID back to a
280  * target specific Claim/Complete register. This function must be called after
281  * #dif_plic_irq_claim, when the caller is prepared to service another IRQ with
282  * the same source ID. If a source ID is never Completed, then when future
283  * interrupts are Claimed, they will never have the source ID of the uncompleted
284  * IRQ.
285  *
286  * @see #dif_plic_irq_claim
287  *
288  * @param plic A PLIC handle.
289  * @param target Target that claimed the IRQ.
290  * @param[out] complete_data Previously claimed IRQ data that is used to signal
291  * PLIC of the IRQ servicing completion.
292  * @return The result of the operation.
293  */
296  dif_plic_target_t target,
297  const dif_plic_irq_id_t *complete_data);
298 
299 /**
300  * Forces the software interrupt for a particular target.
301  *
302  * This function causes an interrupt to the `target` HART to be serviced as if
303  * hardware had asserted it.
304  *
305  * This function allows to synchronise between the HARTs, which otherwise
306  * would not be possible due to HART being only able to access own CSRs.
307  * NOTE: this is not an issue on Ibex, as it has only one HART.
308  *
309  * An interrupt handler is expected to call `dif_plic_software_irq_acknowledge`
310  * when the interrupt has been handled.
311  *
312  * @param plic PLIC state data.
313  * @param target Target HART.
314  * @return `dif_plic_result_t`.
315  */
318  dif_plic_target_t target);
319 
320 /**
321  * Acknowledges the software interrupt for a particular target.
322  *
323  * This function indicates to the hardware that the software interrupt has been
324  * successfully serviced. It is expected to be called from a software interrupt
325  * handler.
326  *
327  * @param plic PLIC state data.
328  * @param target Target HART.
329  * @return `dif_plic_result_t`.
330  */
333  dif_plic_target_t target);
334 
335 /**
336  * Returns software interrupt pending state for a particular target.
337  *
338  * @param plic PLIC state data.
339  * @param target Target HART.
340  * @param[out] is_pending Flag indicating whether the interrupt is pending.
341  * @return `dif_plic_result_t`.
342  */
345  dif_plic_target_t target,
346  bool *is_pending);
347 
348 #ifdef __cplusplus
349 } // extern "C"
350 #endif // __cplusplus
351 
352 #endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PLIC_H_