1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2011-01-13     weety      modified from mini2440
9  */
10 
11 #include <rthw.h>
12 #include <rtthread.h>
13 
14 #define ICACHE_MASK (rt_uint32_t)(1 << 12)
15 #define DCACHE_MASK (rt_uint32_t)(1 << 2)
16 
17 extern void machine_reset(void);
18 extern void machine_shutdown(void);
19 
20 #ifdef __GNUC__
cp15_rd(void)21 rt_inline rt_uint32_t cp15_rd(void)
22 {
23     rt_uint32_t i;
24 
25     asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
26     return i;
27 }
28 
cache_enable(rt_uint32_t bit)29 rt_inline void cache_enable(rt_uint32_t bit)
30 {
31     __asm__ __volatile__(           \
32         "mrc  p15,0,r0,c1,c0,0\n\t" \
33         "orr  r0,r0,%0\n\t"         \
34         "mcr  p15,0,r0,c1,c0,0"     \
35         :                           \
36         :"r" (bit)                  \
37         :"memory");
38 }
39 
cache_disable(rt_uint32_t bit)40 rt_inline void cache_disable(rt_uint32_t bit)
41 {
42     __asm__ __volatile__(           \
43         "mrc  p15,0,r0,c1,c0,0\n\t" \
44         "bic  r0,r0,%0\n\t"         \
45         "mcr  p15,0,r0,c1,c0,0"     \
46         :                           \
47         :"r" (bit)                  \
48         :"memory");
49 }
50 
51 
52 #endif
53 
54 #ifdef __CC_ARM
cp15_rd(void)55 rt_inline rt_uint32_t cp15_rd(void)
56 {
57     rt_uint32_t i;
58 
59     __asm
60     {
61         mrc p15, 0, i, c1, c0, 0
62     }
63 
64     return i;
65 }
66 
cache_enable(rt_uint32_t bit)67 rt_inline void cache_enable(rt_uint32_t bit)
68 {
69     rt_uint32_t value;
70 
71     __asm
72     {
73         mrc p15, 0, value, c1, c0, 0
74         orr value, value, bit
75         mcr p15, 0, value, c1, c0, 0
76     }
77 }
78 
cache_disable(rt_uint32_t bit)79 rt_inline void cache_disable(rt_uint32_t bit)
80 {
81     rt_uint32_t value;
82 
83     __asm
84     {
85         mrc p15, 0, value, c1, c0, 0
86         bic value, value, bit
87         mcr p15, 0, value, c1, c0, 0
88     }
89 }
90 #endif
91 
92 /**
93  * enable I-Cache
94  *
95  */
rt_hw_cpu_icache_enable()96 void rt_hw_cpu_icache_enable()
97 {
98     cache_enable(ICACHE_MASK);
99 }
100 
101 /**
102  * disable I-Cache
103  *
104  */
rt_hw_cpu_icache_disable()105 void rt_hw_cpu_icache_disable()
106 {
107     cache_disable(ICACHE_MASK);
108 }
109 
110 /**
111  * return the status of I-Cache
112  *
113  */
rt_hw_cpu_icache_status()114 rt_base_t rt_hw_cpu_icache_status()
115 {
116     return (cp15_rd() & ICACHE_MASK);
117 }
118 
119 /**
120  * enable D-Cache
121  *
122  */
rt_hw_cpu_dcache_enable()123 void rt_hw_cpu_dcache_enable()
124 {
125     cache_enable(DCACHE_MASK);
126 }
127 
128 /**
129  * disable D-Cache
130  *
131  */
rt_hw_cpu_dcache_disable()132 void rt_hw_cpu_dcache_disable()
133 {
134     cache_disable(DCACHE_MASK);
135 }
136 
137 /**
138  * return the status of D-Cache
139  *
140  */
rt_hw_cpu_dcache_status()141 rt_base_t rt_hw_cpu_dcache_status()
142 {
143     return (cp15_rd() & DCACHE_MASK);
144 }
145 
146 /**
147  * reset cpu by dog's time-out
148  *
149  */
rt_hw_cpu_reset()150 void rt_hw_cpu_reset()
151 {
152 
153     rt_kprintf("Restarting system...\n");
154     machine_reset();
155 
156     while(1);   /* loop forever and wait for reset to happen */
157 
158     /* NEVER REACHED */
159 }
160 
161 /**
162  *  shutdown CPU
163  *
164  */
rt_hw_cpu_shutdown(void)165 void rt_hw_cpu_shutdown(void)
166 {
167     rt_base_t level;
168     rt_kprintf("shutdown...\n");
169 
170     level = rt_hw_interrupt_disable();
171     machine_shutdown();
172     while (level)
173     {
174         RT_ASSERT(0);
175     }
176 }
177 
178 #ifdef RT_USING_CPU_FFS
179 /**
180  * This function finds the first bit set (beginning with the least significant bit)
181  * in value and return the index of that bit.
182  *
183  * Bits are numbered starting at 1 (the least significant bit).  A return value of
184  * zero from any of these functions means that the argument was zero.
185  *
186  * @return return the index of the first bit set. If value is 0, then this function
187  * shall return 0.
188  */
189 #if defined(__CC_ARM)
__rt_ffs(int value)190 int __rt_ffs(int value)
191 {
192     register rt_uint32_t x;
193 
194     if (value == 0)
195         return value;
196 
197     __asm
198     {
199         rsb x, value, #0
200         and x, x, value
201         clz x, x
202         rsb x, x, #32
203     }
204 
205     return x;
206 }
207 #elif defined(__IAR_SYSTEMS_ICC__)
__rt_ffs(int value)208 int __rt_ffs(int value)
209 {
210     if (value == 0)
211         return value;
212 
213     __ASM("RSB  r4, r0, #0");
214     __ASM("AND  r4, r4, r0");
215     __ASM("CLZ  r4, r4");
216     __ASM("RSB  r0, r4, #32");
217 }
218 #elif defined(__GNUC__)
__rt_ffs(int value)219 int __rt_ffs(int value)
220 {
221     if (value == 0)
222         return value;
223 
224     value &= (-value);
225     asm ("clz %0, %1": "=r"(value) :"r"(value));
226 
227     return (32 - value);
228 }
229 #endif
230 
231 #endif
232 
233 
234 /*@}*/
235