1 /*******************************************************************************
2  * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * MPFS HAL Embedded Software
7  *
8  */
9 
10 /*******************************************************************************
11  *
12  * @file mss_clint.h
13  * @author Microchip-FPGA Embedded Systems Solutions
14  * @brief CLINT access data structures and functions.
15  *
16  */
17 #ifndef MSS_CLINT_H
18 #define MSS_CLINT_H
19 
20 #include <stdint.h>
21 #include "encoding.h"
22 #include "atomic.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 #define RTC_PRESCALER 100U
29 #define SUCCESS 0U
30 #define ERROR   1U
31 
32 
33 /*==============================================================================
34  * CLINT: Core Local Interrupter
35  */
36 typedef struct CLINT_Type_t
37 {
38     volatile uint32_t MSIP[5];
39     volatile uint32_t reserved1[(0x4000U - 0x14U)/4U];
40     volatile uint64_t MTIMECMP[5];  /* mtime compare value for each hart. When mtime equals this value, interrupt is generated for particular hart */
41     volatile uint32_t reserved2[((0xbff8U - 0x4028U)/4U)];
42     volatile uint64_t MTIME;    /* contains the current mtime value */
43 } CLINT_Type;
44 
45 #define CLINT    ((CLINT_Type *)CLINT_BASE)
46 
47 
48 /*==============================================================================
49  * The function raise_soft_interrupt() raises a synchronous software interrupt by
50  * writing into the MSIP register.
51  */
raise_soft_interrupt(unsigned long hart_id)52 static inline void raise_soft_interrupt(unsigned long hart_id)
53 {
54     /*You need to make sure that the global interrupt is enabled*/
55     /*Note:  set_csr(mie, MIP_MSIP) needs to be set on hart you are setting sw interrupt */
56     CLINT->MSIP[hart_id] = 0x01U;   /*raise soft interrupt for hart(x) where x== hart ID*/
57     mb();
58 }
59 
60 /*==============================================================================
61  * The function clear_soft_interrupt() clears a synchronous software interrupt by
62  * clearing the MSIP register.
63  */
clear_soft_interrupt(void)64 static inline void clear_soft_interrupt(void)
65 {
66     volatile uint32_t reg;
67     uint64_t hart_id = read_csr(mhartid);
68     CLINT->MSIP[hart_id] = 0x00U;   /*clear soft interrupt for hart0*/
69     reg = CLINT->MSIP[hart_id];     /* we read back to make sure it has been written before moving on */
70                                     /* todo: verify line above guaranteed and best way to achieve result */
71     (void)reg;                      /* use reg to avoid compiler warning */
72 }
73 
74 /*
75  * return mtime
76  */
77 uint64_t readmtime(void);
78 
79 /**
80  * call once at startup
81  * @return
82  */
83 void reset_mtime(void);
84 
85 /**
86  * Configure system tick
87  * @return SUCCESS or FAIL
88  */
89 uint32_t SysTick_Config(void);
90 
91 /**
92  * Disable system tick interrupt
93  */
94 void disable_systick(void);
95 
96 /*------------------------------------------------------------------------------
97  * RISC-V interrupt handler for machine timer interrupts.
98  */
99 void handle_m_timer_interrupt(void);
100 
101 /**
102  *
103  */
104 void handle_m_soft_interrupt(void);
105 
106 #ifdef __cplusplus
107 }
108 #endif
109 
110 #endif  /*  MSS_CLINT_H */
111