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  * @file mss_util.c
12  * @author Microchip-FPGA Embedded Systems Solutions
13  * @brief Utility functions
14  *
15  */
16 #include <stddef.h>
17 #include <stdbool.h>
18 #include "mpfs_hal/mss_hal.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /*------------------------------------------------------------------------------
25  *
26  */
enable_interrupts(void)27 void enable_interrupts(void) {
28     __enable_irq();
29 }
30 
31 /*------------------------------------------------------------------------------
32  *
33  */
disable_interrupts(void)34 uint64_t disable_interrupts(void) {
35     uint64_t psr;
36     psr = read_csr(mstatus);
37     __disable_irq();
38     return(psr);
39 }
40 
41 /*------------------------------------------------------------------------------
42  *
43  */
restore_interrupts(uint64_t saved_psr)44 void restore_interrupts(uint64_t saved_psr) {
45     write_csr(mstatus, saved_psr);
46 }
47 
48 /*------------------------------------------------------------------------------
49  * Disable all interrupts.
50  */
__disable_irq(void)51 void __disable_irq(void)
52 {
53     clear_csr(mstatus, MSTATUS_MIE);
54     clear_csr(mstatus, MSTATUS_MPIE);
55 }
56 
__disable_all_irqs(void)57 void __disable_all_irqs(void)
58 {
59     __disable_irq();
60     write_csr(mie, 0x00U);
61     write_csr(mip, 0x00);
62 }
63 
64 /*------------------------------------------------------------------------------
65  * Enable all interrupts.
66  */
__enable_irq(void)67 void __enable_irq(void)
68 {
69     set_csr(mstatus, MSTATUS_MIE);  /* mstatus Register- Machine Interrupt Enable */
70 }
71 
72 /*------------------------------------------------------------------------------
73  * Enable particular local interrupt
74  */
__enable_local_irq(uint8_t local_interrupt)75 void __enable_local_irq(uint8_t local_interrupt)
76 {
77     if((local_interrupt > (int8_t)0) && (local_interrupt <= LOCAL_INT_MAX))
78     {
79         set_csr(mie, (0x1LLU << (int8_t)(local_interrupt + 16U)));  /* mie Register- Machine Interrupt Enable Register */
80     }
81 }
82 
83 /*------------------------------------------------------------------------------
84  * Disable particular local interrupt
85  */
__disable_local_irq(uint8_t local_interrupt)86 void __disable_local_irq(uint8_t local_interrupt)
87 {
88     if((local_interrupt > (int8_t)0) && (local_interrupt <= LOCAL_INT_MAX))
89     {
90         clear_csr(mie, (0x1LLU << (int8_t)(local_interrupt + 16U)));  /* mie Register- Machine Interrupt Enable Register */
91     }
92 }
93 
94 /**
95  * readmcycle(void)
96  * @return returns the mcycle count from hart CSR
97  */
readmcycle(void)98 uint64_t readmcycle(void)
99 {
100     return (read_csr(mcycle));
101 }
102 
sleep_ms(uint64_t msecs)103 void sleep_ms(uint64_t msecs)
104 {
105     uint64_t starttime = readmtime();
106     volatile uint64_t endtime = 0U;
107 
108     while(endtime < (starttime+msecs)) {
109         endtime = readmtime();
110     }
111 }
112 
113 /**
114  * sleep_cycles(uint64_t ncycles)
115  * @param number of cycles to sleep
116  */
sleep_cycles(uint64_t ncycles)117 void sleep_cycles(uint64_t ncycles)
118 {
119     uint64_t starttime = readmcycle();
120     volatile uint64_t endtime = 0U;
121 
122     while(endtime < (starttime + ncycles)) {
123         endtime = readmcycle();
124     }
125 }
126 
127 /**
128  * get_program_counter(void)
129  * @return returns the program counter
130  */
get_program_counter(void)131 __attribute__((aligned(16))) uint64_t get_program_counter(void)
132 {
133     uint64_t prog_counter;
134     asm volatile ("auipc %0, 0" : "=r"(prog_counter));
135     return (prog_counter);
136 }
137 
138 /**
139  * get_stack_pointer(void)
140  * @return Return the stack pointer
141  */
get_stack_pointer(void)142 uint64_t get_stack_pointer(void)
143 {
144     uint64_t stack_pointer;
145     asm volatile ("addi %0, sp, 0" : "=r"(stack_pointer));
146     return (stack_pointer);
147 }
148 
149 /**
150  * Return the tp register
151  * The tp register holds the value of the Hart Common memory HLS once not in an
152  * interrupt. If the tp value is used in an interrupt, it is saved first and
153  * restored on exit. This conforms to OpenSBI implementation.
154  *
155  * @return returns the tp register value
156  */
get_tp_reg(void)157 uint64_t get_tp_reg(void)
158 {
159     uint64_t tp_reg_val;
160     asm volatile ("addi %0, tp, 0" : "=r"(tp_reg_val));
161     return (tp_reg_val);
162 }
163 
164 #ifdef PRINTF_DEBUG_SUPPORTED
display_address_of_interest(uint64_t * address_of_interest,int nb_locations)165 void display_address_of_interest(uint64_t * address_of_interest, int nb_locations) {
166   uint64_t * p_addr_of_interest = address_of_interest;
167   int inc;
168   mpfs_printf(" Displaying address of interest: 0x%lx\n", p_addr_of_interest);
169 
170   for (inc = 0U; inc < nb_locations; ++inc) {
171     mpfs_printf("  address of interest: 0x%lx: 0x%lx\n", p_addr_of_interest, *p_addr_of_interest);
172     p_addr_of_interest = p_addr_of_interest + 8;
173   }
174 }
175 #endif
176 
177 #ifdef __cplusplus
178 }
179 #endif
180