1 /*
2 * File : cpuport.c
3 * This file is part of RT-Thread RTOS
4 * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
5 *
6 * The license and distribution terms for this file may be
7 * found in the file LICENSE in this distribution or at
8 * http://www.rt-thread.org/license/LICENSE
9 *
10 * Change Logs:
11 * Date Author Notes
12 * 2010-07-09 Bernard first version
13 * 2010-09-11 Bernard add CPU reset implementation
14 * 2015-07-06 chinesebear modified for loongson 1c
15 */
16
17 #include <rtthread.h>
18 #include "ls1c.h"
19
20 register rt_uint32_t $GP __asm__ ("$28");
21
22 /**
23 * @addtogroup Loongson LS1B
24 */
25
26 /*@{*/
27
28 /**
29 * this function will reset CPU
30 *
31 */
rt_hw_cpu_reset(void)32 void rt_hw_cpu_reset(void)
33 {
34 /* open the watch-dog */
35 WDT_EN = 0x01; /* watch dog enable */
36 WDT_TIMER = 0x01; /* watch dog will be timeout after 1 tick */
37 WDT_SET = 0x01; /* watch dog start */
38
39 rt_kprintf("reboot system...\n");
40 while (1);
41 }
42
43 /**
44 * this function will shutdown CPU
45 *
46 */
rt_hw_cpu_shutdown(void)47 void rt_hw_cpu_shutdown(void)
48 {
49 rt_kprintf("shutdown...\n");
50
51 while (1);
52 }
53
54 extern rt_uint32_t cp0_get_cause(void);
55 extern rt_uint32_t cp0_get_status(void);
56 extern rt_uint32_t cp0_get_hi(void);
57 extern rt_uint32_t cp0_get_lo(void);
58
59 /**
60 * This function will initialize thread stack
61 *
62 * @param tentry the entry of thread
63 * @param parameter the parameter of entry
64 * @param stack_addr the beginning stack address
65 * @param texit the function will be called when thread exit
66 *
67 * @return stack address
68 */
rt_hw_stack_init(void * tentry,void * parameter,rt_uint8_t * stack_addr,void * texit)69 rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit)
70 {
71 rt_uint32_t *stk;
72 static rt_uint32_t g_sr = 0;
73 static rt_uint32_t g_gp = 0;
74
75 if (g_sr == 0)
76 {
77 g_sr = cp0_get_status();
78 g_sr &= 0xfffffffe;
79 g_sr |= 0x8401;
80
81 g_gp = $GP;
82 }
83
84 /** Start at stack top */
85 stk = (rt_uint32_t *)stack_addr;
86 *(stk) = (rt_uint32_t) tentry; /* pc: Entry Point */
87 *(--stk) = (rt_uint32_t) 0xeeee; /* c0_cause */
88 *(--stk) = (rt_uint32_t) 0xffff; /* c0_badvaddr */
89 *(--stk) = (rt_uint32_t) cp0_get_lo(); /* lo */
90 *(--stk) = (rt_uint32_t) cp0_get_hi(); /* hi */
91 *(--stk) = (rt_uint32_t) g_sr; /* C0_SR: HW2 = En, IE = En */
92 *(--stk) = (rt_uint32_t) texit; /* ra */
93 *(--stk) = (rt_uint32_t) 0x0000001e; /* s8 */
94 *(--stk) = (rt_uint32_t) stack_addr; /* sp */
95 *(--stk) = (rt_uint32_t) g_gp; /* gp */
96 *(--stk) = (rt_uint32_t) 0x0000001b; /* k1 */
97 *(--stk) = (rt_uint32_t) 0x0000001a; /* k0 */
98 *(--stk) = (rt_uint32_t) 0x00000019; /* t9 */
99 *(--stk) = (rt_uint32_t) 0x00000018; /* t8 */
100 *(--stk) = (rt_uint32_t) 0x00000017; /* s7 */
101 *(--stk) = (rt_uint32_t) 0x00000016; /* s6 */
102 *(--stk) = (rt_uint32_t) 0x00000015; /* s5 */
103 *(--stk) = (rt_uint32_t) 0x00000014; /* s4 */
104 *(--stk) = (rt_uint32_t) 0x00000013; /* s3 */
105 *(--stk) = (rt_uint32_t) 0x00000012; /* s2 */
106 *(--stk) = (rt_uint32_t) 0x00000011; /* s1 */
107 *(--stk) = (rt_uint32_t) 0x00000010; /* s0 */
108 *(--stk) = (rt_uint32_t) 0x0000000f; /* t7 */
109 *(--stk) = (rt_uint32_t) 0x0000000e; /* t6 */
110 *(--stk) = (rt_uint32_t) 0x0000000d; /* t5 */
111 *(--stk) = (rt_uint32_t) 0x0000000c; /* t4 */
112 *(--stk) = (rt_uint32_t) 0x0000000b; /* t3 */
113 *(--stk) = (rt_uint32_t) 0x0000000a; /* t2 */
114 *(--stk) = (rt_uint32_t) 0x00000009; /* t1 */
115 *(--stk) = (rt_uint32_t) 0x00000008; /* t0 */
116 *(--stk) = (rt_uint32_t) 0x00000007; /* a3 */
117 *(--stk) = (rt_uint32_t) 0x00000006; /* a2 */
118 *(--stk) = (rt_uint32_t) 0x00000005; /* a1 */
119 *(--stk) = (rt_uint32_t) parameter; /* a0 */
120 *(--stk) = (rt_uint32_t) 0x00000003; /* v1 */
121 *(--stk) = (rt_uint32_t) 0x00000002; /* v0 */
122 *(--stk) = (rt_uint32_t) 0x00000001; /* at */
123 *(--stk) = (rt_uint32_t) 0x00000000; /* zero */
124
125 /* return task's current stack address */
126 return (rt_uint8_t *)stk;
127 }
128
129 #define cache_op(op,addr) \
130 __asm__ __volatile__( \
131 " .set push \n" \
132 " .set noreorder \n" \
133 " .set mips3\n\t \n" \
134 " cache %0, %1 \n" \
135 " .set pop \n" \
136 : \
137 : "i" (op), "R" (*(unsigned char *)(addr)))
138
139 #if defined(CONFIG_CPU_LOONGSON2)
140 #define Hit_Invalidate_I 0x00
141 #else
142 #define Hit_Invalidate_I 0x10
143 #endif
144 #define Hit_Invalidate_D 0x11
145 #define CONFIG_SYS_CACHELINE_SIZE 32
146 #define Hit_Writeback_Inv_D 0x15
147
148
flush_cache(unsigned long start_addr,unsigned long size)149 void flush_cache(unsigned long start_addr, unsigned long size)
150 {
151 unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
152 unsigned long addr = start_addr & ~(lsize - 1);
153 unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
154
155 while (1) {
156 cache_op(Hit_Writeback_Inv_D, addr);
157 cache_op(Hit_Invalidate_I, addr);
158 if (addr == aend)
159 break;
160 addr += lsize;
161 }
162 }
163
164
165 /*@}*/
166
167