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