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