summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c
blob: 59f6fbe483fb6009fef478488a1de37ee2f1a054 (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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* Copyright 2018 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */

#include <metal/machine/platform.h>

#ifdef METAL_SIFIVE_GLOBAL_EXTERNAL_INTERRUPTS0

#include <metal/io.h>
#include <metal/shutdown.h>
#include <metal/drivers/sifive_global-external-interrupts0.h>
#include <metal/machine.h>

void __metal_driver_sifive_global_external_interrupt_init(struct metal_interrupt *controller)
{
    struct __metal_driver_sifive_global_external_interrupts0 *global0;

    global0 = (struct __metal_driver_sifive_global_external_interrupts0 *)(controller);
    if ( !global0->init_done ) {
        struct metal_interrupt *intc =
	    __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);

	if (intc) {
	    intc->vtable->interrupt_init(intc);
	    /* Register its interrupts with with parent controller */
            for (int i = 0;
		 i < __metal_driver_sifive_global_external_interrupts0_num_interrupts(controller);
		 i++) {
	    	intc->vtable->interrupt_register(intc,
		    __metal_driver_sifive_global_external_interrupts0_interrupt_lines(controller, i),
						 NULL, controller);
	    }
            global0->init_done = 1;
	}
    }
}

int __metal_driver_sifive_global_external_interrupt_register(struct metal_interrupt *controller,
                                                           int id, metal_interrupt_handler_t isr,
                                                           void *priv)
{
    int rc = -1;

    if (id != 0) {
        struct metal_interrupt *intc =
	    __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);

        /* Enable its interrupts with parent controller */
        if (intc) {
            rc = intc->vtable->interrupt_register(intc, id, isr, priv);
        }
    }
    return rc;
}

int __metal_driver_sifive_global_external_interrupt_enable(struct metal_interrupt *controller, int id)
{
    int rc = -1;

    if (id != 0) {
        struct metal_interrupt *intc =
	    __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);

        /* Enable its interrupts with parent controller */
        if (intc) {
            rc = intc->vtable->interrupt_enable(intc, id);
        }
    }
    return rc;
}

int __metal_driver_sifive_global_external_interrupt_disable(struct metal_interrupt *controller, int id)
{
    int rc = -1;

    if (id != 0) {
        struct metal_interrupt *intc =
	    __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);

        /* Enable its interrupts with parent controller */
        if (intc) {
            rc = intc->vtable->interrupt_disable(intc, id);
        }
    }
    return rc;
}

int __metal_driver_sifive_global_external_command_request (struct metal_interrupt *controller,
                                                         int command, void *data)
{
    int idx;
    int rc = -1;

    switch (command) {
    case METAL_MAX_INTERRUPT_GET:
        rc = __metal_driver_sifive_global_external_interrupts0_num_interrupts(controller);
        break;
    case METAL_INDEX_INTERRUPT_GET:
        rc = 0;
        if (data) {
            idx = *(int *)data;
            rc = __metal_driver_sifive_global_external_interrupts0_interrupt_lines(controller, idx);
        }
        break;
    default:
        break;
    }

    return rc;
}

__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_global_external_interrupts0) = {
    .global0_vtable.interrupt_init     = __metal_driver_sifive_global_external_interrupt_init,
    .global0_vtable.interrupt_register = __metal_driver_sifive_global_external_interrupt_register,
    .global0_vtable.interrupt_enable   = __metal_driver_sifive_global_external_interrupt_enable,
    .global0_vtable.interrupt_disable  = __metal_driver_sifive_global_external_interrupt_disable,
    .global0_vtable.command_request    = __metal_driver_sifive_global_external_command_request,
};

#endif