]>
Commit | Line | Data |
---|---|---|
dc7c9a1a WD |
1 | /* |
2 | * (C) Copyright 2002 | |
3 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
4 | * Marius Groeger <mgroeger@sysgo.de> | |
5 | * | |
6 | * (C) Copyright 2002 | |
7 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
8 | * Alex Zuepke <azu@sysgo.de> | |
9 | * | |
10 | * See file CREDITS for list of people who contributed to this | |
11 | * project. | |
12 | * | |
13 | * This program is free software; you can redistribute it and/or | |
14 | * modify it under the terms of the GNU General Public License as | |
15 | * published by the Free Software Foundation; either version 2 of | |
16 | * the License, or (at your option) any later version. | |
17 | * | |
18 | * This program is distributed in the hope that it will be useful, | |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | * GNU General Public License for more details. | |
22 | * | |
23 | * You should have received a copy of the GNU General Public License | |
24 | * along with this program; if not, write to the Free Software | |
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
26 | * MA 02111-1307 USA | |
27 | */ | |
28 | ||
29 | /* | |
30 | * CPU specific code | |
31 | */ | |
32 | ||
33 | #include <common.h> | |
34 | #include <command.h> | |
85ec0bcc | 35 | #include <asm/io.h> |
b783edae | 36 | #include <asm/arch/hardware.h> |
dc7c9a1a | 37 | |
2cbe571a WD |
38 | #if !defined(CONFIG_DBGU) && !defined(CONFIG_USART0) && !defined(CONFIG_USART1) |
39 | #error must define one of CONFIG_DBGU or CONFIG_USART0 or CONFIG_USART1 | |
4734cb78 WD |
40 | #endif |
41 | ||
dc7c9a1a WD |
42 | /* read co-processor 15, register #1 (control register) */ |
43 | static unsigned long read_p15_c1(void) | |
44 | { | |
45 | unsigned long value; | |
46 | ||
47 | __asm__ __volatile__( | |
48 | "mrc p15, 0, %0, c1, c0, 0 @ read control reg\n" | |
49 | : "=r" (value) | |
50 | : | |
51 | : "memory"); | |
52 | /*printf("p15/c1 is = %08lx\n", value); */ | |
53 | return value; | |
54 | } | |
55 | ||
56 | /* write to co-processor 15, register #1 (control register) */ | |
57 | static void write_p15_c1(unsigned long value) | |
58 | { | |
59 | /*printf("write %08lx to p15/c1\n", value); */ | |
60 | __asm__ __volatile__( | |
8bde7f77 | 61 | "mcr p15, 0, %0, c1, c0, 0 @ write it back\n" |
dc7c9a1a WD |
62 | : "=r" (value) |
63 | : | |
64 | : "memory"); | |
65 | ||
66 | read_p15_c1(); | |
67 | } | |
68 | ||
69 | static void cp_delay(void) | |
70 | { | |
71 | volatile int i; | |
72 | ||
73 | /* copro seems to need some delay between reading and writing */ | |
74 | for (i=0; i<100; i++); | |
75 | } | |
76 | /* See also ARM Ref. Man. */ | |
77 | #define C1_MMU (1<<0) /* mmu off/on */ | |
78 | #define C1_ALIGN (1<<1) /* alignment faults off/on */ | |
79 | #define C1_IDC (1<<2) /* icache and/or dcache off/on */ | |
80 | #define C1_WRITE_BUFFER (1<<3) /* write buffer off/on */ | |
81 | #define C1_BIG_ENDIAN (1<<7) /* big endian off/on */ | |
82 | #define C1_SYS_PROT (1<<8) /* system protection */ | |
83 | #define C1_ROM_PROT (1<<9) /* ROM protection */ | |
84 | #define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */ | |
85 | ||
86 | int cpu_init(void) | |
87 | { | |
a8c7c708 WD |
88 | /* |
89 | * setup up stacks if necessary | |
90 | */ | |
dc7c9a1a | 91 | #ifdef CONFIG_USE_IRQ |
a8c7c708 WD |
92 | DECLARE_GLOBAL_DATA_PTR; |
93 | ||
f6e20fc6 | 94 | IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4; |
a8c7c708 | 95 | FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; |
dc7c9a1a | 96 | #endif |
a8c7c708 | 97 | return 0; |
dc7c9a1a WD |
98 | } |
99 | ||
100 | int cleanup_before_linux(void) | |
101 | { | |
102 | /* | |
103 | * this function is called just before we call linux | |
104 | * it prepares the processor for linux | |
105 | * | |
106 | * we turn off caches etc ... | |
107 | * and we set the CPU-speed to 73 MHz - see start.S for details | |
108 | */ | |
109 | ||
110 | disable_interrupts(); | |
111 | return 0; | |
112 | } | |
113 | ||
114 | int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
115 | { | |
116 | ||
117 | #ifdef CFG_SOFT_RESET | |
118 | extern void reset_cpu(ulong addr); | |
119 | ||
120 | disable_interrupts(); | |
121 | reset_cpu(0); | |
122 | #else | |
4734cb78 | 123 | #ifdef CONFIG_DBGU |
cf33678e | 124 | AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU; |
4734cb78 | 125 | #endif |
2cbe571a WD |
126 | #ifdef CONFIG_USART0 |
127 | AT91PS_USART us = AT91C_BASE_US0; | |
128 | #endif | |
4734cb78 | 129 | #ifdef CONFIG_USART1 |
dc7c9a1a | 130 | AT91PS_USART us = AT91C_BASE_US1; |
4734cb78 | 131 | #endif |
dc7c9a1a WD |
132 | AT91PS_PIO pio = AT91C_BASE_PIOA; |
133 | ||
134 | /*shutdown the console to avoid strange chars during reset */ | |
135 | us->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX); | |
136 | ||
efe2a4d5 | 137 | #ifdef CONFIG_AT91RM9200DK |
dc7c9a1a WD |
138 | /* Clear PA19 to trigger the hard reset */ |
139 | pio->PIO_CODR = 0x00080000; | |
140 | pio->PIO_OER = 0x00080000; | |
141 | pio->PIO_PER = 0x00080000; | |
ed54e621 WD |
142 | #endif |
143 | #ifdef CONFIG_CMC_PU2 | |
144 | /* this is the way Linux does it */ | |
145 | #define AT91C_ST_RSTEN (0x1 << 16) | |
146 | #define AT91C_ST_EXTEN (0x1 << 17) | |
147 | #define AT91C_ST_WDRST (0x1 << 0) | |
148 | /* watchdog mode register */ | |
149 | #define ST_WDMR *((unsigned long *)0xfffffd08) | |
150 | /* system clock control register */ | |
151 | #define ST_CR *((unsigned long *)0xfffffd00) | |
152 | ST_WDMR = AT91C_ST_RSTEN | AT91C_ST_EXTEN | 1 ; | |
153 | ST_CR = AT91C_ST_WDRST; | |
dc7c9a1a | 154 | /* Never reached */ |
ed54e621 | 155 | #endif |
dc7c9a1a WD |
156 | #endif |
157 | return 0; | |
158 | } | |
159 | ||
160 | void icache_enable(void) | |
161 | { | |
162 | ulong reg; | |
163 | reg = read_p15_c1(); | |
164 | cp_delay(); | |
165 | write_p15_c1(reg | C1_IDC); | |
166 | } | |
167 | ||
168 | void icache_disable(void) | |
169 | { | |
170 | ulong reg; | |
171 | reg = read_p15_c1(); | |
172 | cp_delay(); | |
173 | write_p15_c1(reg & ~C1_IDC); | |
174 | } | |
175 | ||
176 | int icache_status(void) | |
177 | { | |
178 | return (read_p15_c1() & C1_IDC) != 0; | |
179 | return 0; | |
180 | } | |
181 | ||
182 | void dcache_enable(void) | |
183 | { | |
184 | ulong reg; | |
185 | reg = read_p15_c1(); | |
186 | cp_delay(); | |
187 | write_p15_c1(reg | C1_IDC); | |
188 | } | |
189 | ||
190 | void dcache_disable(void) | |
191 | { | |
192 | ulong reg; | |
193 | reg = read_p15_c1(); | |
194 | cp_delay(); | |
195 | write_p15_c1(reg & ~C1_IDC); | |
196 | } | |
197 | ||
198 | int dcache_status(void) | |
199 | { | |
200 | return (read_p15_c1() & C1_IDC) != 0; | |
201 | return 0; | |
202 | } |