]> git.sur5r.net Git - u-boot/blob - cpu/mpc824x/cpu.c
Initial revision
[u-boot] / 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 int do_reset (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc,
96                           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
130 /* ------------------------------------------------------------------------- */
131
132 /*
133  * Get timebase clock frequency (like cpu_clk in Hz)
134  * This is the sys_logic_clk (memory bus) divided by 4
135  */
136 unsigned long get_tbclk (void)
137 {
138         return ((get_bus_freq (0) + 2L) / 4L);
139 }
140
141 /* ------------------------------------------------------------------------- */
142
143 /*
144  * The MPC824x has an integrated PCI controller known as the MPC107.
145  * The following are MPC107 Bridge Controller and PCI Support functions
146  *
147  */
148
149 /*
150  *  This procedure reads a 32-bit address MPC107 register, and returns
151  *  a 32 bit value.  It swaps the address to little endian before
152  *  writing it to config address, and swaps the value to big endian
153  *  before returning to the caller.
154  */
155 unsigned int mpc824x_mpc107_getreg (unsigned int regNum)
156 {
157         unsigned int temp;
158
159         /* swap the addr. to little endian */
160         *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
161         temp = *(volatile unsigned int *) CHRP_REG_DATA;
162         return PCISWAP (temp);          /* swap the data upon return */
163 }
164
165 /*
166  *  This procedure writes a 32-bit address MPC107 register.  It swaps
167  *  the address to little endian before writing it to config address.
168  */
169
170 void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal)
171 {
172         /* swap the addr. to little endian */
173         *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
174         *(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal);
175         return;
176 }
177
178
179 /*
180  *  Write a byte (8 bits) to a memory location.
181  */
182 void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data)
183 {
184         *(unsigned char *) addr = data;
185         __asm__ ("sync");
186 }
187
188 /*
189  *  Write a word (16 bits) to a memory location after the value
190  *  has been byte swapped (big to little endian or vice versa)
191  */
192
193 void mpc824x_mpc107_write16 (unsigned int address, unsigned short data)
194 {
195         *(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data);
196         __asm__ ("sync");
197 }
198
199 /*
200  *  Write a long word (32 bits) to a memory location after the value
201  *  has been byte swapped (big to little endian or vice versa)
202  */
203
204 void mpc824x_mpc107_write32 (unsigned int address, unsigned int data)
205 {
206         *(volatile unsigned int *) address = LONGSWAP (data);
207         __asm__ ("sync");
208 }
209
210 /*
211  *  Read a byte (8 bits) from a memory location.
212  */
213 unsigned char mpc824x_mpc107_read8 (unsigned int addr)
214 {
215         return *(volatile unsigned char *) addr;
216 }
217
218
219 /*
220  *  Read a word (16 bits) from a memory location, and byte swap the
221  *  value before returning to the caller.
222  */
223 unsigned short mpc824x_mpc107_read16 (unsigned int address)
224 {
225         unsigned short retVal;
226
227         retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address);
228         return retVal;
229 }
230
231
232 /*
233  *  Read a long word (32 bits) from a memory location, and byte
234  *  swap the value before returning to the caller.
235  */
236 unsigned int mpc824x_mpc107_read32 (unsigned int address)
237 {
238         unsigned int retVal;
239
240         retVal = LONGSWAP (*(unsigned int *) address);
241         return (retVal);
242 }
243
244
245 /*
246  *  Read a register in the Embedded Utilities Memory Block address
247  *  space.
248  *  Input: regNum - register number + utility base address.  Example,
249  *         the base address of EPIC is 0x40000, the register number
250  *         being passed is 0x40000+the address of the target register.
251  *         (See epic.h for register addresses).
252  *  Output:  The 32 bit little endian value of the register.
253  */
254
255 unsigned int mpc824x_eummbar_read (unsigned int regNum)
256 {
257         unsigned int temp;
258
259         temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum);
260         temp = PCISWAP (temp);
261         return temp;
262 }
263
264
265 /*
266  *  Write a value to a register in the Embedded Utilities Memory
267  *  Block address space.
268  *  Input: regNum - register number + utility base address.  Example,
269  *                  the base address of EPIC is 0x40000, the register
270  *                  number is 0x40000+the address of the target register.
271  *                  (See epic.h for register addresses).
272  *         regVal - value to be written to the register.
273  */
274
275 void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal)
276 {
277         *(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal);
278         return;
279 }
280
281 /* ------------------------------------------------------------------------- */