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 */ 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 */ 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 */ 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 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