|
5 | 5 | #include "hal/plic.h" |
6 | 6 | #include "hal/mmio.h" |
7 | 7 | #include <stdbool.h> |
| 8 | +#include <stddef.h> |
8 | 9 | #include <stdint.h> |
9 | 10 |
|
10 | | -uint8_t plic_interrupt_priority_get(plic_t plic, uint8_t intr_id) |
| 11 | +#define array_len(arr) (sizeof(arr) / sizeof((arr)[0])) |
| 12 | + |
| 13 | +void plic_init(plic_t plic) |
| 14 | +{ |
| 15 | + plic_machine_interrupt_disable_all(plic); |
| 16 | + plic_supervisor_interrupt_disable_all(plic); |
| 17 | +} |
| 18 | + |
| 19 | +uint8_t plic_interrupt_priority_get(plic_t plic, uint32_t intr) |
11 | 20 | { |
12 | | - if (intr_id >= PLIC_NUM_SRC) { |
13 | | - return 0; |
| 21 | + if (intr == 0u) { |
| 22 | + return 0u; |
14 | 23 | } |
15 | | - return (DEV_READ(plic + PLIC_PRIO_REG + 4 * intr_id) & PLIC_PRIO_MASK); |
| 24 | + |
| 25 | + size_t id = __builtin_ctz(intr); |
| 26 | + plic_prio prio = VOLATILE_READ(plic->prio[id]); |
| 27 | + return prio.prio; |
16 | 28 | } |
17 | 29 |
|
18 | | -void plic_interrupt_priority_set(plic_t plic, uint8_t intr_id, uint8_t prio) |
| 30 | +void plic_interrupt_priority_set(plic_t plic, uint32_t intrs, uint8_t priority) |
19 | 31 | { |
20 | | - if (intr_id < PLIC_NUM_SRC) { |
21 | | - DEV_WRITE(plic + PLIC_PRIO_REG + 4 * intr_id, prio & PLIC_PRIO_MASK); |
| 32 | + if (intrs == 0u) { |
| 33 | + return; |
22 | 34 | } |
| 35 | + |
| 36 | + uint32_t remain = intrs; |
| 37 | + do { |
| 38 | + size_t id = __builtin_ctz(remain); |
| 39 | + remain &= ~(1u << id); |
| 40 | + plic_prio prio = { .prio = priority }; |
| 41 | + VOLATILE_WRITE(plic->prio[id], prio); |
| 42 | + } while (remain != 0u); |
| 43 | +} |
| 44 | + |
| 45 | +uint32_t plic_machine_interrupt_enable_get(plic_t plic) |
| 46 | +{ |
| 47 | + return VOLATILE_READ(plic->ie0); |
23 | 48 | } |
24 | 49 |
|
25 | | -bool plic_interrupt_is_pending(plic_t plic, uint8_t intr_id) |
| 50 | +uint32_t plic_supervisor_interrupt_enable_get(plic_t plic) |
26 | 51 | { |
27 | | - return ((DEV_READ(plic + PLIC_IP_REG) & (1 << intr_id)) != 0); |
| 52 | + return VOLATILE_READ(plic->ie1); |
28 | 53 | } |
29 | 54 |
|
30 | | -bool plic_machine_interrupt_enable_get(plic_t plic, uint8_t intr_id) |
| 55 | +void plic_machine_interrupt_enable_set(plic_t plic, uint32_t intrs) |
31 | 56 | { |
32 | | - return ((DEV_READ(plic + PLIC_IE0_REG) & (1 << intr_id)) != 0); |
| 57 | + VOLATILE_WRITE(plic->ie0, intrs); |
33 | 58 | } |
34 | 59 |
|
35 | | -bool plic_supervisor_interrupt_enable_get(plic_t plic, uint8_t intr_id) |
| 60 | +void plic_supervisor_interrupt_enable_set(plic_t plic, uint32_t intrs) |
36 | 61 | { |
37 | | - return ((DEV_READ(plic + PLIC_IE1_REG) & (1 << intr_id)) != 0); |
| 62 | + VOLATILE_WRITE(plic->ie1, intrs); |
38 | 63 | } |
39 | 64 |
|
40 | | -void plic_machine_interrupt_enable(plic_t plic, uint8_t intr_id) |
| 65 | +void plic_machine_interrupt_enable(plic_t plic, uint32_t intrs) |
41 | 66 | { |
42 | | - DEV_WRITE(plic + PLIC_IE0_REG, DEV_READ(plic + PLIC_IE0_REG) | (1 << intr_id)); |
| 67 | + uint32_t ie0 = VOLATILE_READ(plic->ie0); |
| 68 | + VOLATILE_WRITE(plic->ie0, ie0 |= intrs); |
43 | 69 | } |
44 | 70 |
|
45 | | -void plic_supervisor_interrupt_enable(plic_t plic, uint8_t intr_id) |
| 71 | +void plic_supervisor_interrupt_enable(plic_t plic, uint32_t intrs) |
46 | 72 | { |
47 | | - DEV_WRITE(plic + PLIC_IE1_REG, DEV_READ(plic + PLIC_IE1_REG) | (1 << intr_id)); |
| 73 | + uint32_t ie1 = VOLATILE_READ(plic->ie1); |
| 74 | + VOLATILE_WRITE(plic->ie1, ie1 |= intrs); |
48 | 75 | } |
49 | 76 |
|
50 | | -void plic_machine_interrupt_disable(plic_t plic, uint8_t intr_id) |
| 77 | +void plic_machine_interrupt_disable(plic_t plic, uint32_t intrs) |
51 | 78 | { |
52 | | - DEV_WRITE(plic + PLIC_IE0_REG, DEV_READ(plic + PLIC_IE0_REG) & ~(1 << intr_id)); |
| 79 | + uint32_t ie0 = VOLATILE_READ(plic->ie0); |
| 80 | + VOLATILE_WRITE(plic->ie0, ie0 & ~intrs); |
53 | 81 | } |
54 | 82 |
|
55 | | -void plic_supervisor_interrupt_disable(plic_t plic, uint8_t intr_id) |
| 83 | +void plic_supervisor_interrupt_disable(plic_t plic, uint32_t intrs) |
56 | 84 | { |
57 | | - DEV_WRITE(plic + PLIC_IE1_REG, DEV_READ(plic + PLIC_IE1_REG) & ~(1 << intr_id)); |
| 85 | + uint32_t ie1 = VOLATILE_READ(plic->ie1); |
| 86 | + VOLATILE_WRITE(plic->ie1, ie1 & ~intrs); |
58 | 87 | } |
59 | 88 |
|
60 | 89 | void plic_machine_interrupt_disable_all(plic_t plic) |
61 | 90 | { |
62 | | - DEV_WRITE(plic + PLIC_IE0_REG, 0); |
| 91 | + VOLATILE_WRITE(plic->ie0, 0u); |
63 | 92 | } |
64 | 93 |
|
65 | 94 | void plic_supervisor_interrupt_disable_all(plic_t plic) |
66 | 95 | { |
67 | | - DEV_WRITE(plic + PLIC_IE1_REG, 0); |
| 96 | + VOLATILE_WRITE(plic->ie1, 0u); |
68 | 97 | } |
69 | 98 |
|
70 | | -uint8_t plic_machine_priority_threshold_get(plic_t plic) |
| 99 | +bool plic_interrupt_all_pending(plic_t plic, uint32_t intrs) |
71 | 100 | { |
72 | | - return (DEV_READ(plic + PLIC_THRESHOLD0_REG) & PLIC_PRIO_MASK); |
| 101 | + return (VOLATILE_READ(plic->ip) & intrs) == intrs; |
73 | 102 | } |
74 | 103 |
|
75 | | -uint8_t plic_supervisor_priority_threshold_get(plic_t plic) |
| 104 | +bool plic_interrupt_any_pending(plic_t plic, uint32_t intrs) |
76 | 105 | { |
77 | | - return (DEV_READ(plic + PLIC_THRESHOLD1_REG) & PLIC_PRIO_MASK); |
| 106 | + return (VOLATILE_READ(plic->ip) & intrs) != 0u; |
78 | 107 | } |
79 | 108 |
|
80 | | -void plic_machine_priority_threshold_set(plic_t plic, uint8_t prio) |
| 109 | +uint8_t plic_machine_priority_threshold_get(plic_t plic) |
81 | 110 | { |
82 | | - DEV_WRITE(plic + PLIC_THRESHOLD0_REG, prio & PLIC_PRIO_MASK); |
| 111 | + plic_threshold0 threshold = VOLATILE_READ(plic->threshold0); |
| 112 | + return threshold.threshold0; |
83 | 113 | } |
84 | 114 |
|
85 | | -void plic_supervisor_priority_threshold_set(plic_t plic, uint8_t prio) |
| 115 | +uint8_t plic_supervisor_priority_threshold_get(plic_t plic) |
86 | 116 | { |
87 | | - DEV_WRITE(plic + PLIC_THRESHOLD1_REG, prio & PLIC_PRIO_MASK); |
| 117 | + plic_threshold1 threshold = VOLATILE_READ(plic->threshold1); |
| 118 | + return threshold.threshold1; |
88 | 119 | } |
89 | 120 |
|
90 | | -uint8_t plic_machine_interrupt_claim(plic_t plic) |
| 121 | +void plic_machine_priority_threshold_set(plic_t plic, uint8_t prio) |
91 | 122 | { |
92 | | - return (uint8_t)DEV_READ(plic + PLIC_CC0_REG); |
| 123 | + plic_threshold0 threshold = { .threshold0 = prio }; |
| 124 | + VOLATILE_WRITE(plic->threshold0, threshold); |
93 | 125 | } |
94 | 126 |
|
95 | | -uint8_t plic_supervisor_interrupt_claim(plic_t plic) |
| 127 | +void plic_supervisor_priority_threshold_set(plic_t plic, uint8_t prio) |
96 | 128 | { |
97 | | - return (uint8_t)DEV_READ(plic + PLIC_CC1_REG); |
| 129 | + plic_threshold1 threshold = { .threshold1 = prio }; |
| 130 | + VOLATILE_WRITE(plic->threshold1, threshold); |
98 | 131 | } |
99 | 132 |
|
100 | | -void plic_machine_interrupt_complete(plic_t plic, uint8_t intr_id) |
| 133 | +uint32_t plic_machine_interrupt_claim(plic_t plic) |
101 | 134 | { |
102 | | - DEV_WRITE(plic + PLIC_CC0_REG, (uint32_t)intr_id); |
| 135 | + plic_cc0 claim = VOLATILE_READ(plic->cc0); |
| 136 | + return (1u << claim.cc0); |
103 | 137 | } |
104 | 138 |
|
105 | | -void plic_supervisor_interrupt_complete(plic_t plic, uint8_t intr_id) |
| 139 | +uint32_t plic_supervisor_interrupt_claim(plic_t plic) |
106 | 140 | { |
107 | | - DEV_WRITE(plic + PLIC_CC1_REG, (uint32_t)intr_id); |
| 141 | + plic_cc1 claim = VOLATILE_READ(plic->cc1); |
| 142 | + return (1u << claim.cc1); |
108 | 143 | } |
109 | 144 |
|
110 | | -void plic_alert_trigger(plic_t plic) |
| 145 | +void plic_machine_interrupt_complete(plic_t plic, uint32_t intr) |
111 | 146 | { |
112 | | - DEV_WRITE(plic + PLIC_ALERT_TEST_REG, 1); |
| 147 | + if (intr == 0u) { |
| 148 | + return; |
| 149 | + } |
| 150 | + size_t id = __builtin_ctz(intr); |
| 151 | + plic_cc0 complete = { .cc0 = id }; |
| 152 | + VOLATILE_WRITE(plic->cc0, complete); |
113 | 153 | } |
114 | 154 |
|
115 | | -void plic_init(plic_t plic) |
| 155 | +void plic_supervisor_interrupt_complete(plic_t plic, uint32_t intr) |
116 | 156 | { |
117 | | - plic_machine_interrupt_disable_all(plic); |
118 | | - plic_supervisor_interrupt_disable_all(plic); |
| 157 | + if (intr == 0u) { |
| 158 | + return; |
| 159 | + } |
| 160 | + size_t id = __builtin_ctz(intr); |
| 161 | + plic_cc1 complete = { .cc1 = id }; |
| 162 | + VOLATILE_WRITE(plic->cc1, complete); |
119 | 163 | } |
0 commit comments