blob: 7decc50269faa0800c430aeb917e84666601aa92 [file] [log] [blame]
Xiaohu.Huangf78b48b2022-01-17 10:41:38 +08001/*
2 * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11
12#include "n200_func.h"
13#include "register.h"
14#include "common.h"
15#include "n200_timer.h"
16#include "riscv_encoding.h"
17
18// Configure PMP to make all the address space accesable and executable
19void pmp_open_all_space(void){
20 // Config entry0 addr to all 1s to make the range cover all space
21 asm volatile ("li x6, 0xffffffff":::"x6");
22 asm volatile ("csrw pmpaddr0, x6":::);
23 // Config entry0 cfg to make it NAPOT address mode, and R/W/X okay
24 asm volatile ("li x6, 0x7f":::"x6");
25 asm volatile ("csrw pmpcfg0, x6":::);
26}
27
28void switch_m2u_mode(void){
29 clear_csr (mstatus,MSTATUS_MPP);
30 //printf("\nIn the m2u function, the mstatus is 0x%x\n", read_csr(mstatus));
31 //printf("\nIn the m2u function, the mepc is 0x%x\n", read_csr(mepc));
32 asm volatile ("la x6, 1f ":::"x6");
33 asm volatile ("csrw mepc, x6":::);
34 asm volatile ("mret":::);
35 asm volatile ("1:":::);
36}
37
38uint32_t mtime_lo(void)
39{
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080040#ifdef configSOC_TIMER_AS_TICK
41 return *(volatile uint32_t *)TIMERE_LOW_REG;
42#else
43 return *(volatile uint32_t *)(TIMER_CTRL_ADDR + TIMER_MTIME);
44#endif
Xiaohu.Huangf78b48b2022-01-17 10:41:38 +080045}
46
47
48uint32_t mtime_hi(void)
49{
Xiaohu.Huanga2c5a042022-03-12 22:41:09 +080050#ifdef configSOC_TIMER_AS_TICK
51 return *(volatile uint32_t *)TIMERE_HIG_REG;
52#else
53 return *(volatile uint32_t *)(TIMER_CTRL_ADDR + TIMER_MTIME + 4);
54#endif
Xiaohu.Huangf78b48b2022-01-17 10:41:38 +080055}
56
57uint64_t get_timer_value(void)
58{
59 while (1) {
60 uint32_t hi = mtime_hi();
61 uint32_t lo = mtime_lo();
62 if (hi == mtime_hi())
63 return ((uint64_t)hi << 32) | lo;
64 }
65}
66
67uint32_t get_timer_freq(void)
68{
69 return TIMER_FREQ;
70}
71
72uint64_t get_instret_value(void)
73{
74 while (1) {
75 uint32_t hi = read_csr(minstreth);
76 uint32_t lo = read_csr(minstret);
77 if (hi == read_csr(minstreth))
78 return ((uint64_t)hi << 32) | lo;
79 }
80}
81
82uint64_t get_cycle_value(void)
83{
84 while (1) {
85 uint32_t hi = read_csr(mcycleh);
86 uint32_t lo = read_csr(mcycle);
87 if (hi == read_csr(mcycleh))
88 return ((uint64_t)hi << 32) | lo;
89 }
90}
91
92unsigned long interrupt_status_get(void)
93{
94 return read_csr(mstatus) >> 0x3;
95}
96
97void interrupt_disable(void)
98{
99 clear_csr(mstatus, MSTATUS_MIE);
100}
101
102void interrupt_enable(void)
103{
104 set_csr(mstatus, MSTATUS_MIE);
105}
106
107#ifndef CONFIG_N200_REVA
108
109uint32_t __attribute__((noinline)) measure_cpu_freq(size_t n)
110{
111 uint32_t start_mtime, delta_mtime;
112 uint32_t mtime_freq = get_timer_freq();
113
114 // Don't start measuruing until we see an mtime tick
115 uint32_t tmp = mtime_lo();
116 do {
117 start_mtime = mtime_lo();
118 } while (start_mtime == tmp);
119
120 uint32_t start_mcycle = read_csr(mcycle);
121
122 do {
123 delta_mtime = mtime_lo() - start_mtime;
124 } while (delta_mtime < n);
125
126 uint32_t delta_mcycle = read_csr(mcycle) - start_mcycle;
127
128 return (delta_mcycle / delta_mtime) * mtime_freq
129 + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime;
130}
131
132uint32_t get_cpu_freq(void)
133{
134 uint32_t cpu_freq;
135
136 // warm up
137 measure_cpu_freq(1);
138 // measure for real
139 cpu_freq = measure_cpu_freq(100);
140
141 return cpu_freq;
142}
143
144unsigned int xPortIsIsrContext(void)
145{
146 return (read_csr_msubmode & 0xff);
147}
148
149#else
150
151unsigned int xPortIsIsrContext(void)
152{
153 return read_csr_msubmode;
154}
155
156#endif