Software APIs
dif_rv_plic.h
Go to the documentation of this file.
1// Copyright lowRISC contributors (OpenTitan project).
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_RV_PLIC_H_
6#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_RV_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
23#include "dt/dt_api.h" // Generated
27
28#include "sw/device/lib/dif/autogen/dif_rv_plic_autogen.h"
29
30#ifdef __cplusplus
31extern "C" {
32#endif // __cplusplus
33
34/**
35 * The lowest interrupt priority.
36 */
37extern const uint32_t kDifRvPlicMinPriority;
38
39/**
40 * The highest interrupt priority.
41 */
42extern const uint32_t kDifRvPlicMaxPriority;
43
44/**
45 * A PLIC interrupt source identifier.
46 *
47 * This corresponds to a specific interrupt, and not the device it originates
48 * from.
49 *
50 * This is an unsigned 32-bit value that is at least zero and is less than the
51 * `NumSrc` instantiation parameter of the `rv_plic` device.
52 *
53 * The value 0 corresponds to "No Interrupt".
54 */
56
57/**
58 * A PLIC interrupt target.
59 *
60 * This corresponds to a specific system that can service an interrupt. In
61 * OpenTitan's case, that is the Ibex core. If there were multiple cores in the
62 * system, each core would have its own specific interrupt target ID.
63 *
64 * This is an unsigned 32-bit value that is at least 0 and is less than the
65 * `NumTarget` instantiation parameter of the `rv_plic` device.
66 */
67typedef uint32_t dif_rv_plic_target_t;
68
69/**
70 * Resets the PLIC to a clean state.
71 *
72 *
73 * This function resets all the relevant PLIC registers, apart from the CC
74 * register. There is no reliable way of knowing the ID of an IRQ that has
75 * claimed the CC register, so we assume that the previous "owner" of the
76 * resource has cleared/completed the CC access.
77 *
78 * @param plic A PLIC handle.
79 * @return The result of the operation.
80 */
83
84/**
85 * Returns whether a particular interrupt is currently pending.
86 *
87 * @param plic A PLIC handle.
88 * @param irq An interrupt type.
89 * @param[out] is_pending Out-param for whether the interrupt is pending.
90 * @return The result of the operation.
91 */
95 bool *is_pending);
96
97/**
98 * Checks whether a particular interrupt is currently enabled or disabled.
99 *
100 * @param plic A PLIC handle.
101 * @param irq An interrupt type.
102 * @param target An interrupt target.
103 * @param[out] state Out-param toggle state of the interrupt.
104 * @return The result of the operation.
105 */
110 dif_toggle_t *state);
111
112/**
113 * Sets whether a particular interrupt is currently enabled or disabled.
114 *
115 * This operation does not affect IRQ generation in `target`, which
116 * must be configured in the corresponding peripheral itself.
117 *
118 * @param plic A PLIC handle.
119 * @param irq An interrupt type.
120 * @param target An interrupt target.
121 * @param state The new toggle state for the interrupt.
122 * @return The result of the operation.
123 */
128 dif_toggle_t state);
129
130/**
131 * Sets IRQ source priority (0-3).
132 *
133 * In order for the PLIC to set a Claim/Complete register and assert the
134 * external interrupt line to the target (Ibex, ...), the priority of the IRQ
135 * source must be higher than the threshold for this source.
136 *
137 * @param plic A PLIC handle.
138 * @param irq An interrupt type.
139 * @param priority Priority to set.
140 * @return The result of the operation.
141 */
145 uint32_t priority);
146
147/**
148 * Sets the target priority threshold.
149 *
150 * Sets the target priority threshold. PLIC will only interrupt a target when
151 * IRQ source priority is set higher than the priority threshold for the
152 * corresponding target.
153 *
154 * @param plic A PLIC handle.
155 * @param target Target to set the IRQ priority threshold for.
156 * @param threshold IRQ priority threshold to be set.
157 * @return The result of the operation.
158 */
162 uint32_t threshold);
163
164/**
165 * Claims an IRQ and gets the information about the source.
166 *
167 * Claims an IRQ and returns the IRQ related data to the caller. This function
168 * reads a target specific Claim/Complete register. #dif_rv_plic_irq_complete
169 * must be called in order to allow another interrupt with the same source id to
170 * be delivered. This usually would be done once the interrupt has been
171 * serviced.
172 *
173 * Another IRQ can be claimed before a prior IRQ is completed. In this way, this
174 * functionality is compatible with nested interrupt handling. The restriction
175 * is that you must Complete a Claimed IRQ before you will be able to claim an
176 * IRQ with the same ID. This allows a pair of Claim/Complete calls to be
177 * overlapped with another pair -- and there is no requirement that the
178 * interrupts should be Completed in the reverse order of when they were
179 * Claimed.
180 *
181 * @see #dif_rv_plic_irq_complete
182 *
183 * @param plic A PLIC handle.
184 * @param target Target that claimed the IRQ.
185 * @param[out] claim_data Data that describes the origin of the IRQ.
186 * @return The result of the operation.
187 */
191 dif_rv_plic_irq_id_t *claim_data);
192
193/**
194 * Completes the claimed IRQ.
195 *
196 * Finishes servicing of the claimed IRQ by writing the IRQ source ID back to a
197 * target specific Claim/Complete register. This function must be called after
198 * #dif_rv_plic_irq_claim, when the caller is prepared to service another IRQ
199 * with the same source ID. If a source ID is never Completed, then when future
200 * interrupts are Claimed, they will never have the source ID of the uncompleted
201 * IRQ.
202 *
203 * @see #dif_rv_plic_irq_claim
204 *
205 * @param plic A PLIC handle.
206 * @param target Target that claimed the IRQ.
207 * @param complete_data Previously claimed IRQ data that is used to signal
208 * PLIC of the IRQ servicing completion.
209 * @return The result of the operation.
210 */
214 dif_rv_plic_irq_id_t complete_data);
215
216/**
217 * Forces the software interrupt for a particular target.
218 *
219 * This function causes an interrupt to the `target` HART to be serviced as if
220 * hardware had asserted it.
221 *
222 * This function allows to synchronise between the HARTs, which otherwise
223 * would not be possible due to HART being only able to access own CSRs.
224 * NOTE: this is not an issue on Ibex, as it has only one HART.
225 *
226 * An interrupt handler is expected to call
227 * `dif_rv_plic_software_irq_acknowledge` when the interrupt has been handled.
228 *
229 * @param plic PLIC state data.
230 * @param target Target HART.
231 * @return `dif_result_t`.
232 */
235 dif_rv_plic_target_t target);
236
237/**
238 * Acknowledges the software interrupt for a particular target.
239 *
240 * This function indicates to the hardware that the software interrupt has been
241 * successfully serviced. It is expected to be called from a software interrupt
242 * handler.
243 *
244 * @param plic PLIC state data.
245 * @param target Target HART.
246 * @return `dif_result_t`.
247 */
250 dif_rv_plic_target_t target);
251
252/**
253 * Returns software interrupt pending state for a particular target.
254 *
255 * @param plic PLIC state data.
256 * @param target Target HART.
257 * @param[out] is_pending Flag indicating whether the interrupt is pending.
258 * @return `dif_result_t`.
259 */
263 bool *is_pending);
264
265#ifdef __cplusplus
266} // extern "C"
267#endif // __cplusplus
268
269#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_RV_PLIC_H_