4effb12ace9803e0d9a721c18670006cccaf7203
[u-boot.git] / cpu / mpc824x / cpu.c
1 /*
2  * (C) Copyright 2000 - 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <config.h>
25 #include <mpc824x.h>
26 #include <common.h>
27 #include <command.h>
28
29 int checkcpu (void)
30 {
31         DECLARE_GLOBAL_DATA_PTR;
32
33         unsigned int pvr = get_pvr ();
34         unsigned int version = pvr >> 16;
35         unsigned char revision;
36         ulong clock = gd->cpu_clk;
37         char buf[32];
38
39         puts ("CPU:   ");
40
41         switch (version) {
42         case CPU_TYPE_8240:
43                 puts ("MPC8240");
44                 break;
45
46         case CPU_TYPE_8245:
47                 puts ("MPC8245");
48                 break;
49
50         default:
51                 return -1;              /*not valid for this source */
52         }
53
54         CONFIG_READ_BYTE (REVID, revision);
55
56         if (revision) {
57                 printf (" Revision %d.%d",
58                         (revision & 0xf0) >> 4,
59                         (revision & 0x0f));
60         } else {
61                 return -1;              /* no valid CPU revision info */
62         }
63
64         printf (" at %s MHz:", strmhz (buf, clock));
65
66         printf (" %u kB I-Cache", checkicache () >> 10);
67         printf (" %u kB D-Cache", checkdcache () >> 10);
68
69         puts ("\n");
70
71         return 0;
72 }
73
74 /* ------------------------------------------------------------------------- */
75 /* L1 i-cache                                                                */
76
77 int checkicache (void)
78 {
79          /*TODO*/
80          return 128 * 4 * 32;
81 };
82
83 /* ------------------------------------------------------------------------- */
84 /* L1 d-cache                                                                */
85
86 int checkdcache (void)
87 {
88          /*TODO*/
89          return 128 * 4 * 32;
90
91 };
92
93 /*------------------------------------------------------------------- */
94
95 #ifndef CONFIG_LINKSTATION
96 int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
97 {
98         ulong msr, addr;
99
100         /* Interrupts and MMU off */
101         __asm__ ("mtspr    81, 0");
102
103         /* Interrupts and MMU off */
104         __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
105
106         msr &= ~0x1030;
107         __asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
108
109         /*
110          * Trying to execute the next instruction at a non-existing address
111          * should cause a machine check, resulting in reset
112          */
113 #ifdef CFG_RESET_ADDRESS
114         addr = CFG_RESET_ADDRESS;
115 #else
116         /*
117          * note: when CFG_MONITOR_BASE points to a RAM address,
118          * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid
119          * address. Better pick an address known to be invalid on
120          * your system and assign it to CFG_RESET_ADDRESS.
121          * "(ulong)-1" used to be a good choice for many systems...
122          */
123         addr = CFG_MONITOR_BASE - sizeof (ulong);
124 #endif
125         ((void (*)(void)) addr) ();
126         return 1;
127
128 }
129 #endif
130
131 /* ------------------------------------------------------------------------- */
132
133 /*
134  * Get timebase clock frequency (like cpu_clk in Hz)
135  * This is the sys_logic_clk (memory bus) divided by 4
136  */
137 unsigned long get_tbclk (void)
138 {
139         return ((get_bus_freq (0) + 2L) / 4L);
140 }
141
142 /* ------------------------------------------------------------------------- */
143
144 /*
145  * The MPC824x has an integrated PCI controller known as the MPC107.
146  * The following are MPC107 Bridge Controller and PCI Support functions
147  *
148  */
149
150 /*
151  *  This procedure reads a 32-bit address MPC107 register, and returns
152  *  a 32 bit value.  It swaps the address to little endian before
153  *  writing it to config address, and swaps the value to big endian
154  *  before returning to the caller.
155  */
156 unsigned int mpc824x_mpc107_getreg (unsigned int regNum)
157 {
158         unsigned int temp;
159
160         /* swap the addr. to little endian */
161         *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
162         temp = *(volatile unsigned int *) CHRP_REG_DATA;
163         return PCISWAP (temp);          /* swap the data upon return */
164 }
165
166 /*
167  *  This procedure writes a 32-bit address MPC107 register.  It swaps
168  *  the address to little endian before writing it to config address.
169  */
170
171 void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal)
172 {
173         /* swap the addr. to little endian */
174         *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
175         *(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal);
176         return;
177 }
178
179
180 /*
181  *  Write a byte (8 bits) to a memory location.
182  */
183 void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data)
184 {
185         *(unsigned char *) addr = data;
186         __asm__ ("sync");
187 }
188
189 /*
190  *  Write a word (16 bits) to a memory location after the value
191  *  has been byte swapped (big to little endian or vice versa)
192  */
193
194 void mpc824x_mpc107_write16 (unsigned int address, unsigned short data)
195 {
196         *(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data);
197         __asm__ ("sync");
198 }
199
200 /*
201  *  Write a long word (32 bits) to a memory location after the value
202  *  has been byte swapped (big to little endian or vice versa)
203  */
204
205 void mpc824x_mpc107_write32 (unsigned int address, unsigned int data)
206 {
207         *(volatile unsigned int *) address = LONGSWAP (data);
208         __asm__ ("sync");
209 }
210
211 /*
212  *  Read a byte (8 bits) from a memory location.
213  */
214 unsigned char mpc824x_mpc107_read8 (unsigned int addr)
215 {
216         return *(volatile unsigned char *) addr;
217 }
218
219
220 /*
221  *  Read a word (16 bits) from a memory location, and byte swap the
222  *  value before returning to the caller.
223  */
224 unsigned short mpc824x_mpc107_read16 (unsigned int address)
225 {
226         unsigned short retVal;
227
228         retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address);
229         return retVal;
230 }
231
232
233 /*
234  *  Read a long word (32 bits) from a memory location, and byte
235  *  swap the value before returning to the caller.
236  */
237 unsigned int mpc824x_mpc107_read32 (unsigned int address)
238 {
239         unsigned int retVal;
240
241         retVal = LONGSWAP (*(unsigned int *) address);
242         return (retVal);
243 }
244
245
246 /*
247  *  Read a register in the Embedded Utilities Memory Block address
248  *  space.
249  *  Input: regNum - register number + utility base address.  Example,
250  *         the base address of EPIC is 0x40000, the register number
251  *         being passed is 0x40000+the address of the target register.
252  *         (See epic.h for register addresses).
253  *  Output:  The 32 bit little endian value of the register.
254  */
255
256 unsigned int mpc824x_eummbar_read (unsigned int regNum)
257 {
258         unsigned int temp;
259
260         temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum);
261         temp = PCISWAP (temp);
262         return temp;
263 }
264
265
266 /*
267  *  Write a value to a register in the Embedded Utilities Memory
268  *  Block address space.
269  *  Input: regNum - register number + utility base address.  Example,
270  *                  the base address of EPIC is 0x40000, the register
271  *                  number is 0x40000+the address of the target register.
272  *                  (See epic.h for register addresses).
273  *         regVal - value to be written to the register.
274  */
275
276 void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal)
277 {
278         *(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal);
279         return;
280 }
281
282 /* ------------------------------------------------------------------------- */