embox

Форк
0
98 строк · 3.6 Кб
1
/**
2
 * @file
3
 *
4
 * @brief PLIC interrupt driver for SiFive U54-MC Core
5
 *
6
 * @date 08.06.2024
7
 * @author Suraj Sonawane
8
 */
9
 
10
#include <assert.h>
11
#include <stdint.h>
12

13
#include <asm/interrupts.h>
14
#include <asm/regs.h>
15
#include <drivers/irqctrl.h>
16
#include <embox/unit.h>
17
#include <hal/reg.h>
18
#include <util/log.h>
19

20
#define SIFIVE_PLIC_BASE_ADDR            0x0C000000UL /* Base address for SiFive PLIC */
21
#define SIFIVE_PLIC_PRIORITY_OFFSET      0x00000000UL
22
#define SIFIVE_PLIC_PENDING_OFFSET       0x00001000UL
23
#define SIFIVE_PLIC_ENABLE_OFFSET        0x00002000UL
24
#define SIFIVE_PLIC_THRESHOLD_OFFSET     0x00200000UL
25
#define SIFIVE_PLIC_CLAIM_OFFSET         0x00200004UL
26
 
27
#define SIFIVE_PLIC_PRIORITY_REG(interrupt_id) (SIFIVE_PLIC_BASE_ADDR + SIFIVE_PLIC_PRIORITY_OFFSET + (interrupt_id) * 4)
28
#define SIFIVE_PLIC_PENDING_REG(word_index)    (SIFIVE_PLIC_BASE_ADDR + SIFIVE_PLIC_PENDING_OFFSET + (word_index) * 4)
29
#define SIFIVE_PLIC_ENABLE_REG(hart_id, word_index) (SIFIVE_PLIC_BASE_ADDR + SIFIVE_PLIC_ENABLE_OFFSET + (hart_id) * 0x80 + (word_index) * 4)
30
#define SIFIVE_PLIC_THRESHOLD_REG(hart_id)     (SIFIVE_PLIC_BASE_ADDR + SIFIVE_PLIC_THRESHOLD_OFFSET + (hart_id) * 0x1000)
31
#define SIFIVE_PLIC_CLAIM_REG(hart_id)         (SIFIVE_PLIC_BASE_ADDR + SIFIVE_PLIC_CLAIM_OFFSET + (hart_id) * 0x1000)
32
 
33
#define SIFIVE_PLIC_MAX_INTERRUPTS 511
34
#define SIFIVE_PLIC_MAX_PRIORITY 7
35

36
static int sifive_plic_init(void) {
37
    for (uint32_t hart_id = 0; hart_id < 4; hart_id++) {
38
        REG32_STORE(SIFIVE_PLIC_THRESHOLD_REG(hart_id), 0);
39
    }
40
    enable_external_interrupts();
41
    return 0;
42
}
43

44
void irqctrl_set_prio(unsigned int interrupt_nr, unsigned int prio) {
45
    if (interrupt_nr > 0 && interrupt_nr <= SIFIVE_PLIC_MAX_INTERRUPTS) {
46
        if (prio <= SIFIVE_PLIC_MAX_PRIORITY) {
47
            REG32_STORE(SIFIVE_PLIC_PRIORITY_REG(interrupt_nr), prio);
48
        } else {
49
            log_error("Priority value %u exceeds the maximum allowable priority %u",
50
                      prio, SIFIVE_PLIC_MAX_PRIORITY);
51
        }
52
    } else {
53
        log_error("Interrupt number %u is out of valid range (1 to %u)",
54
                  interrupt_nr, SIFIVE_PLIC_MAX_INTERRUPTS);
55
    }
56
}
57

58
void irqctrl_enable_in_cpu(uint32_t hart_id, unsigned int interrupt_nr) {
59
    if (interrupt_nr > 0 && interrupt_nr <= SIFIVE_PLIC_MAX_INTERRUPTS) {
60
        uint32_t reg;
61
        uint32_t word_index = interrupt_nr / 32;
62
        uint32_t bit_index = interrupt_nr % 32;
63

64
        REG32_STORE(SIFIVE_PLIC_PRIORITY_REG(interrupt_nr), 1);
65

66
        reg = REG32_LOAD(SIFIVE_PLIC_ENABLE_REG(hart_id, word_index));
67
        reg |= (1U << bit_index);
68
        REG32_STORE(SIFIVE_PLIC_ENABLE_REG(hart_id, word_index), reg);
69
    } else {
70
        log_error("Interrupt number %u is out of valid range (1 to %u)",
71
                  interrupt_nr, SIFIVE_PLIC_MAX_INTERRUPTS);
72
    }
73
}
74

75
void irqctrl_disable_in_cpu(uint32_t hart_id, unsigned int interrupt_nr) {
76
    if (interrupt_nr > 0 && interrupt_nr <= SIFIVE_PLIC_MAX_INTERRUPTS) {
77
        uint32_t reg;
78
        uint32_t word_index = interrupt_nr / 32;
79
        uint32_t bit_index = interrupt_nr % 32;
80

81
        reg = REG32_LOAD(SIFIVE_PLIC_ENABLE_REG(hart_id, word_index));
82
        reg &= ~(1U << bit_index);
83
        REG32_STORE(SIFIVE_PLIC_ENABLE_REG(hart_id, word_index), reg);
84
    } else {
85
        log_error("Interrupt number %u is out of valid range (1 to %u)",
86
                  interrupt_nr, SIFIVE_PLIC_MAX_INTERRUPTS);
87
    }
88
}
89

90
void irqctrl_eoi_in_cpu(uint32_t hart_id, unsigned int irq) {
91
    REG32_STORE(SIFIVE_PLIC_CLAIM_REG(hart_id), irq);
92
}
93

94
unsigned int irqctrl_get_intid_from_cpu(uint32_t hart_id) {
95
    return REG32_LOAD(SIFIVE_PLIC_CLAIM_REG(hart_id));
96
}
97

98
IRQCTRL_DEF(sifive_plic, sifive_plic_init);

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.