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