summaryrefslogtreecommitdiff
path: root/ports/risc-v64/gnu/example_build/qemu_virt/plic.c
blob: 01e5c71a416d63da4cbdcda9aab778114e9e6d66 (plain)
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
#include "plic.h"
#include <stddef.h>
irq_callback callbacks[MAX_CALLBACK_NUM];

void plic_irq_enable(int irqno)
{
	int hart = riscv_get_core();
	*(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) | (1 << irqno));
	return;
}

void plic_irq_disable(int irqno)
{
	int hart = riscv_get_core();
        *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) & (~(1 << irqno)));
        return;
}

void plic_prio_set(int irqno, int prio)
{
	PLIC_SET_PRIO(irqno, prio);
}

int  plic_prio_get(int irqno)
{
	return PLIC_GET_PRIO(irqno);
}

int  plic_register_callback(int irqno, irq_callback callback)
{
	if(!(irqno >=0 && irqno < MAX_CALLBACK_NUM))
		return -1;
	callbacks[irqno] = callback;
	return 0;
}

int  plic_unregister_callback(int irqno)
{
	return plic_register_callback(irqno, NULL);
}

int  plic_init(void)
{
	for(int i=0;i<MAX_CALLBACK_NUM;i++)
	{
		callbacks[i] = NULL;
	}
	return 0;
}

int  plic_claim(void)
{
	int hart = riscv_get_core();
	return (*(uint32_t*)PLIC_MCLAIM(hart));
}

void plic_complete(int irqno)
{
	int hart = riscv_get_core();
	*(uint32_t*)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno;
	return;
}

int  plic_irq_intr(void)
{
	int ret = -1;
	int irqno = plic_claim();
	if(callbacks[irqno] != NULL)
		ret = (callbacks[irqno])(irqno);
	plic_complete(irqno);
	return ret;
}