]>
Commit | Line | Data |
---|---|---|
c7de829c WD |
1 | #include <common.h> |
2 | #include <asm/processor.h> | |
3 | #include <memio.h> | |
4 | #include <linux/ctype.h> | |
5 | ||
6 | static __inline__ unsigned long | |
7 | get_msr(void) | |
8 | { | |
9 | unsigned long msr; | |
10 | ||
11 | asm volatile("mfmsr %0" : "=r" (msr) :); | |
12 | return msr; | |
13 | } | |
14 | ||
15 | static __inline__ void | |
16 | set_msr(unsigned long msr) | |
17 | { | |
8bde7f77 | 18 | asm volatile("mtmsr %0" : : "r" (msr)); |
c7de829c WD |
19 | } |
20 | ||
21 | static __inline__ unsigned long | |
22 | get_dec(void) | |
23 | { | |
24 | unsigned long val; | |
25 | ||
26 | asm volatile("mfdec %0" : "=r" (val) :); | |
27 | return val; | |
28 | } | |
29 | ||
30 | ||
31 | static __inline__ void | |
32 | set_dec(unsigned long val) | |
33 | { | |
8bde7f77 | 34 | asm volatile("mtdec %0" : : "r" (val)); |
c7de829c WD |
35 | } |
36 | ||
37 | ||
38 | void | |
39 | enable_interrupts(void) | |
40 | { | |
41 | set_msr (get_msr() | MSR_EE); | |
42 | } | |
43 | ||
44 | /* returns flag if MSR_EE was set before */ | |
45 | int | |
46 | disable_interrupts(void) | |
47 | { | |
48 | ulong msr; | |
49 | ||
50 | msr = get_msr(); | |
51 | set_msr (msr & ~MSR_EE); | |
52 | return ((msr & MSR_EE) != 0); | |
53 | } | |
54 | ||
55 | u8 in8(u32 port) | |
56 | { | |
57 | return in_byte(port); | |
58 | } | |
59 | ||
60 | void out8(u32 port, u8 val) | |
61 | { | |
62 | out_byte(port, val); | |
63 | } | |
64 | ||
65 | unsigned long in32(u32 port) | |
66 | { | |
67 | return in_long(port); | |
68 | } | |
69 | ||
70 | unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) | |
71 | { | |
8bde7f77 WD |
72 | unsigned long result = 0,value; |
73 | ||
74 | if (*cp == '0') { | |
75 | cp++; | |
76 | if ((*cp == 'x') && isxdigit(cp[1])) { | |
77 | base = 16; | |
78 | cp++; | |
79 | } | |
80 | if (!base) { | |
81 | base = 8; | |
82 | } | |
83 | } | |
84 | if (!base) { | |
85 | base = 10; | |
86 | } | |
87 | while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) | |
88 | ? toupper(*cp) : *cp)-'A'+10) < base) { | |
89 | result = result*base + value; | |
90 | cp++; | |
91 | } | |
92 | if (endp) | |
93 | *endp = (char *)cp; | |
94 | return result; | |
c7de829c WD |
95 | } |
96 | ||
97 | long simple_strtol(const char *cp,char **endp,unsigned int base) | |
98 | { | |
8bde7f77 WD |
99 | if(*cp=='-') |
100 | return -simple_strtoul(cp+1,endp,base); | |
101 | return simple_strtoul(cp,endp,base); | |
c7de829c WD |
102 | } |
103 | ||
104 | static inline void | |
105 | soft_restart(unsigned long addr) | |
106 | { | |
8bde7f77 WD |
107 | /* SRR0 has system reset vector, SRR1 has default MSR value */ |
108 | /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ | |
c7de829c | 109 | |
8bde7f77 WD |
110 | __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr)); |
111 | __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4"); | |
112 | __asm__ __volatile__ ("mtspr 27, 4"); | |
113 | __asm__ __volatile__ ("rfi"); | |
c7de829c | 114 | |
8bde7f77 | 115 | while(1); /* not reached */ |
c7de829c WD |
116 | } |
117 | ||
118 | void | |
119 | do_reset (void) | |
120 | { | |
8bde7f77 WD |
121 | ulong addr; |
122 | /* flush and disable I/D cache */ | |
123 | __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3"); | |
124 | __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5"); | |
125 | __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4"); | |
126 | __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5"); | |
127 | __asm__ __volatile__ ("sync"); | |
128 | __asm__ __volatile__ ("mtspr 1008, 4"); | |
129 | __asm__ __volatile__ ("isync"); | |
130 | __asm__ __volatile__ ("sync"); | |
131 | __asm__ __volatile__ ("mtspr 1008, 5"); | |
132 | __asm__ __volatile__ ("isync"); | |
133 | __asm__ __volatile__ ("sync"); | |
c7de829c WD |
134 | |
135 | #ifdef CFG_RESET_ADDRESS | |
8bde7f77 | 136 | addr = CFG_RESET_ADDRESS; |
c7de829c | 137 | #else |
8bde7f77 WD |
138 | /* |
139 | * note: when CFG_MONITOR_BASE points to a RAM address, | |
140 | * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid | |
141 | * address. Better pick an address known to be invalid on your | |
142 | * system and assign it to CFG_RESET_ADDRESS. | |
143 | */ | |
144 | addr = CFG_MONITOR_BASE - sizeof (ulong); | |
c7de829c | 145 | #endif |
8bde7f77 WD |
146 | soft_restart(addr); |
147 | while(1); /* not reached */ | |
c7de829c | 148 | } |