embox
94 строки · 2.6 Кб
1/**
2* @file
3*
4* @brief Implementation of the RISC-V Core Local Interruptor (CLINT) for interrupt control, including support for SiFive multi-hart architectures.
5*
6* @date 05.07.2024
7* @authored by Suraj Ravindra Sonawane
8*/
9
10#include <stdint.h>11#include <drivers/irqctrl.h>12#include <hal/reg.h>13#include <asm/interrupts.h>14#include <drivers/interrupt/riscv_clint.h>15
16#define CLINT_ADDR OPTION_GET(NUMBER, base_addr)17#define MSIP_OFFSET OPTION_GET(NUMBER, msip_offset)18#define MTIMECMP_OFFSET OPTION_GET(NUMBER, mtimecmp_offset)19#define MTIME_OFFSET OPTION_GET(NUMBER, mtime_offset)20
21#define MSIP_ADDR(hart) (CLINT_ADDR + MSIP_OFFSET + ((hart) * 4))22#define MTIMECMP_ADDR(hart) (CLINT_ADDR + MTIMECMP_OFFSET + ((hart) * 8))23#define MTIME_ADDR (CLINT_ADDR + MTIME_OFFSET)24
25/**
26* Initializes the CLINT.
27*
28* This function initializes the CLINT by clearing the MSIP (Software Interrupt) and setting MTIMECMP
29* to its maximum value (0xFFFFFFFFFFFFFFFF).
30*
31* @return 0 on success.
32*/
33int clint_init(void) __attribute__((unused));34int clint_init(void) {35// Initial configuration: clear MSIP and set MTIMECMP to max value for all harts36for (int hart = 0; hart < 5; hart++) {37REG32_STORE(MSIP_ADDR(hart), 0);38REG64_STORE(MTIMECMP_ADDR(hart), 0xFFFFFFFFFFFFFFFF);39}40REG64_STORE(MTIME_ADDR, 0);41enable_software_interrupts();42return 0;43}
44
45/**
46* Configures the Software Interrupt (MSIP).
47*
48* This function configures the MSIP by writing a specific value (0 or 1) to its address.
49*
50* @param value The value (0 or 1) to set for MSIP.
51* @param hart_id The hart id (only for SiFive CLINT).
52*/
53void clint_configure_msip(uint8_t value54#ifdef SIFIVE_CLINT55, int hart_id56#endif57) {58#ifdef SIFIVE_CLINT59REG32_STORE(MSIP_ADDR(hart_id), value & 1);60#else61REG32_STORE(MSIP_ADDR(0), value & 1);62#endif63}
64
65/**
66* Sets the MTIMECMP register value.
67*
68* This function sets the MTIMECMP register to the provided 64-bit value.
69*
70* @param value The value to set for MTIMECMP.
71* @param hart_id The hart id (only for SiFive CLINT).
72*/
73void clint_set_mtimecmp(uint64_t value74#ifdef SIFIVE_CLINT75, int hart_id76#endif77) {78#ifdef SIFIVE_CLINT79REG64_STORE(MTIMECMP_ADDR(hart_id), value); // Write 'value' to MTIMECMP_ADDR for the specific hart80#else81REG64_STORE(MTIMECMP_ADDR(0), value);82#endif83}
84
85/**
86* Retrieves the current value of MTIME.
87*
88* This function reads and returns the current value of MTIME.
89*
90* @return The current value of MTIME.
91*/
92uint64_t clint_get_mtime(void) {93return REG64_LOAD(MTIME_ADDR);94}