Lines Matching full:plic
2 * SiFive PLIC (Platform Level Interrupt Controller)
6 * This provides a parameterizable interrupt controller based on SiFive's PLIC.
47 error_report("plic: invalid mode '%c'", c); in char_to_mode()
65 static void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool level) in sifive_plic_set_pending() argument
67 atomic_set_masked(&plic->pending[irq >> 5], 1 << (irq & 31), -!!level); in sifive_plic_set_pending()
70 static void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool level) in sifive_plic_set_claimed() argument
72 atomic_set_masked(&plic->claimed[irq >> 5], 1 << (irq & 31), -!!level); in sifive_plic_set_claimed()
75 static uint32_t sifive_plic_claimed(SiFivePLICState *plic, uint32_t addrid) in sifive_plic_claimed() argument
78 uint32_t max_prio = plic->target_priority[addrid]; in sifive_plic_claimed()
82 for (i = 0; i < plic->bitfield_words; i++) { in sifive_plic_claimed()
84 (plic->pending[i] & ~plic->claimed[i]) & in sifive_plic_claimed()
85 plic->enable[addrid * plic->bitfield_words + i]; in sifive_plic_claimed()
91 if (i == (plic->bitfield_words - 1)) { in sifive_plic_claimed()
93 * If plic->num_sources is not multiple of 32, num-of-irq in last in sifive_plic_claimed()
97 num_irq_in_word = plic->num_sources - ((plic->bitfield_words - 1) << 5); in sifive_plic_claimed()
102 uint32_t prio = plic->source_priority[irq]; in sifive_plic_claimed()
115 static void sifive_plic_update(SiFivePLICState *plic) in sifive_plic_update() argument
120 for (addrid = 0; addrid < plic->num_addrs; addrid++) { in sifive_plic_update()
121 uint32_t hartid = plic->addr_config[addrid].hartid; in sifive_plic_update()
122 PLICMode mode = plic->addr_config[addrid].mode; in sifive_plic_update()
123 bool level = !!sifive_plic_claimed(plic, addrid); in sifive_plic_update()
127 qemu_set_irq(plic->m_external_irqs[hartid - plic->hartid_base], level); in sifive_plic_update()
130 qemu_set_irq(plic->s_external_irqs[hartid - plic->hartid_base], level); in sifive_plic_update()
140 SiFivePLICState *plic = opaque; in sifive_plic_read() local
142 if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) { in sifive_plic_read()
143 uint32_t irq = (addr - plic->priority_base) >> 2; in sifive_plic_read()
145 return plic->source_priority[irq]; in sifive_plic_read()
146 } else if (addr_between(addr, plic->pending_base, in sifive_plic_read()
147 (plic->num_sources + 31) >> 3)) { in sifive_plic_read()
148 uint32_t word = (addr - plic->pending_base) >> 2; in sifive_plic_read()
150 return plic->pending[word]; in sifive_plic_read()
151 } else if (addr_between(addr, plic->enable_base, in sifive_plic_read()
152 plic->num_addrs * plic->enable_stride)) { in sifive_plic_read()
153 uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride; in sifive_plic_read()
154 uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2; in sifive_plic_read()
156 if (wordid < plic->bitfield_words) { in sifive_plic_read()
157 return plic->enable[addrid * plic->bitfield_words + wordid]; in sifive_plic_read()
159 } else if (addr_between(addr, plic->context_base, in sifive_plic_read()
160 plic->num_addrs * plic->context_stride)) { in sifive_plic_read()
161 uint32_t addrid = (addr - plic->context_base) / plic->context_stride; in sifive_plic_read()
162 uint32_t contextid = (addr & (plic->context_stride - 1)); in sifive_plic_read()
165 return plic->target_priority[addrid]; in sifive_plic_read()
167 uint32_t max_irq = sifive_plic_claimed(plic, addrid); in sifive_plic_read()
170 sifive_plic_set_pending(plic, max_irq, false); in sifive_plic_read()
171 sifive_plic_set_claimed(plic, max_irq, true); in sifive_plic_read()
174 sifive_plic_update(plic); in sifive_plic_read()
188 SiFivePLICState *plic = opaque; in sifive_plic_write() local
190 if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) { in sifive_plic_write()
191 uint32_t irq = (addr - plic->priority_base) >> 2; in sifive_plic_write()
198 } else if (((plic->num_priorities + 1) & plic->num_priorities) == 0) { in sifive_plic_write()
204 plic->source_priority[irq] = value % (plic->num_priorities + 1); in sifive_plic_write()
205 sifive_plic_update(plic); in sifive_plic_write()
206 } else if (value <= plic->num_priorities) { in sifive_plic_write()
207 plic->source_priority[irq] = value; in sifive_plic_write()
208 sifive_plic_update(plic); in sifive_plic_write()
210 } else if (addr_between(addr, plic->pending_base, in sifive_plic_write()
211 (plic->num_sources + 31) >> 3)) { in sifive_plic_write()
215 } else if (addr_between(addr, plic->enable_base, in sifive_plic_write()
216 plic->num_addrs * plic->enable_stride)) { in sifive_plic_write()
217 uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride; in sifive_plic_write()
218 uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2; in sifive_plic_write()
220 if (wordid < plic->bitfield_words) { in sifive_plic_write()
221 plic->enable[addrid * plic->bitfield_words + wordid] = value; in sifive_plic_write()
227 } else if (addr_between(addr, plic->context_base, in sifive_plic_write()
228 plic->num_addrs * plic->context_stride)) { in sifive_plic_write()
229 uint32_t addrid = (addr - plic->context_base) / plic->context_stride; in sifive_plic_write()
230 uint32_t contextid = (addr & (plic->context_stride - 1)); in sifive_plic_write()
233 if (((plic->num_priorities + 1) & plic->num_priorities) == 0) { in sifive_plic_write()
239 plic->target_priority[addrid] = value % in sifive_plic_write()
240 (plic->num_priorities + 1); in sifive_plic_write()
241 sifive_plic_update(plic); in sifive_plic_write()
242 } else if (value <= plic->num_priorities) { in sifive_plic_write()
243 plic->target_priority[addrid] = value; in sifive_plic_write()
244 sifive_plic_update(plic); in sifive_plic_write()
247 if (value < plic->num_sources) { in sifive_plic_write()
248 sifive_plic_set_claimed(plic, value, false); in sifive_plic_write()
249 sifive_plic_update(plic); in sifive_plic_write()
291 * parse PLIC hart/mode address offset config
297 static void parse_hart_config(SiFivePLICState *plic) in parse_hart_config() argument
305 p = plic->hart_config; in parse_hart_config()
316 error_report("plic: duplicate mode '%c' in config: %s", in parse_hart_config()
317 c, plic->hart_config); in parse_hart_config()
329 plic->num_addrs = addrid; in parse_hart_config()
330 plic->num_harts = hartid; in parse_hart_config()
333 plic->addr_config = g_new(PLICAddr, plic->num_addrs); in parse_hart_config()
334 addrid = 0, hartid = plic->hartid_base; in parse_hart_config()
335 p = plic->hart_config; in parse_hart_config()
344 plic->addr_config[addrid].addrid = addrid; in parse_hart_config()
345 plic->addr_config[addrid].hartid = hartid; in parse_hart_config()
346 plic->addr_config[addrid].mode = m; in parse_hart_config()
375 error_setg(errp, "plic: invalid number of interrupt sources"); in sifive_plic_realize()
398 * lost a interrupt in the case a PLIC is attached. The SEIP bit must be in sifive_plic_realize()
399 * hardware controlled when a PLIC is attached. in sifive_plic_realize()
474 * Create PLIC device. in type_init()
486 SiFivePLICState *plic; in type_init() local
504 plic = SIFIVE_PLIC(dev); in type_init()
506 for (i = 0; i < plic->num_addrs; i++) { in type_init()
507 int cpu_num = plic->addr_config[i].hartid; in type_init()
510 if (plic->addr_config[i].mode == PLICMode_M) { in type_init()
514 if (plic->addr_config[i].mode == PLICMode_S) { in type_init()