-
Notifications
You must be signed in to change notification settings - Fork 0
/
plic.c
87 lines (80 loc) · 2.67 KB
/
plic.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "platform.h"
#include "riscv.h"
#include "types.h"
#include "plic.h"
void plic_init(void)
{
int hart = r_tp();
/*
* Set priority for UART0.
*
* Each PLIC interrupt source can be assigned a priority by writing
* to its 32-bit memory-mapped priority register.
* The QEMU-virt (the same as FU540-C000) supports 7 levels of priority.
* A priority value of 0 is reserved to mean "never interrupt" and
* effectively disables the interrupt.
* Priority 1 is the lowest active priority, and priority 7 is the highest.
* Ties between global interrupts of the same priority are broken by
* the Interrupt ID; interrupts with the lowest ID have the highest
* effective priority.
*/
*(uint32_t *)PLIC_PRIORITY(UART0_IRQ) = 1;
/*
* Enable UART0
*
* Each global interrupt can be enabled by setting the corresponding
* bit in the enables registers.
*/
*(uint32_t *)PLIC_MENABLE(hart) = (1 << UART0_IRQ);
/*
* Set priority threshold for UART0.
*
* PLIC will mask all interrupts of a priority less than or equal to threshold.
* Maximum threshold is 7.
* For example, a threshold value of zero permits all interrupts with
* non-zero priority, whereas a value of 7 masks all interrupts.
* Notice, the threshold is global for PLIC, not for each interrupt source.
*/
*(uint32_t *)PLIC_MTHRESHOLD(hart) = 0;
/* Enable machine-mode external interrupts */
w_mie(r_mie() | MIE_MEIE);
/* Enable machine-mode global interrupts */
w_mstatus(r_mstatus() | MSTATUS_MIE);
}
/*
* DESCRIPTION:
* Query the PLIC what interrupt we should serve.
* Perform an interrupt claim by reading the Claim Register, which will
* return the ID of the highest-priority pending interrupt or zero if there
* is no pending interrupt. -> iid==0 reserved for no pending interrupt.
*
* A successful claim also atomically clears the corresponding pending bit
* on the interrupt source.
*
* RETURN VALUE:
* The ID of the highest-priority pending interrupt or zero if there
* is no pending interrupt.
*/
int plic_claim(void)
{
int hart = r_tp();
/* reset pending bit? */
int irq = *(uint32_t *)PLIC_MCLAIM(hart);
return irq;
}
/*
* DESCRIPTION:
* Writing the interrupt ID it received from the claim (irq) to the
* Complete Register would signal the PLIC we've served this IRQ.
*
* The PLIC does not check whether the completion ID is the same as the
* last claim ID for that target. If the completion ID does not match an
* interrupt source that is currently enabled for the target, the completion
* is silently ignored.
* RETURN VALUE: None
*/
void plic_complete(int irq)
{
int hart = r_tp();
*(uint32_t *)PLIC_MCOMPLETE(hart) = irq;
}