]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc824x/cpu.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / powerpc / 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 DECLARE_GLOBAL_DATA_PTR;
30
31 int checkcpu (void)
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, int flag, int argc, char *argv[])
96 {
97         ulong msr, addr;
98
99         /* Interrupts and MMU off */
100         __asm__ ("mtspr    81, 0");
101
102         /* Interrupts and MMU off */
103         __asm__ __volatile__ ("mfmsr    %0":"=r" (msr):);
104
105         msr &= ~0x1030;
106         __asm__ __volatile__ ("mtmsr    %0"::"r" (msr));
107
108         /*
109          * Trying to execute the next instruction at a non-existing address
110          * should cause a machine check, resulting in reset
111          */
112 #ifdef CONFIG_SYS_RESET_ADDRESS
113         addr = CONFIG_SYS_RESET_ADDRESS;
114 #else
115         /*
116          * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
117          * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid
118          * address. Better pick an address known to be invalid on
119          * your system and assign it to CONFIG_SYS_RESET_ADDRESS.
120          * "(ulong)-1" used to be a good choice for many systems...
121          */
122         addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
123 #endif
124         ((void (*)(void)) addr) ();
125         return 1;
126
127 }
128
129 /* ------------------------------------------------------------------------- */
130
131 /*
132  * Get timebase clock frequency (like cpu_clk in Hz)
133  * This is the sys_logic_clk (memory bus) divided by 4
134  */
135 unsigned long get_tbclk (void)
136 {
137         return ((get_bus_freq (0) + 2L) / 4L);
138 }
139
140 /* ------------------------------------------------------------------------- */
141
142 /*
143  * The MPC824x has an integrated PCI controller known as the MPC107.
144  * The following are MPC107 Bridge Controller and PCI Support functions
145  *
146  */
147
148 /*
149  *  This procedure reads a 32-bit address MPC107 register, and returns
150  *  a 32 bit value.  It swaps the address to little endian before
151  *  writing it to config address, and swaps the value to big endian
152  *  before returning to the caller.
153  */
154 unsigned int mpc824x_mpc107_getreg (unsigned int regNum)
155 {
156         unsigned int temp;
157
158         /* swap the addr. to little endian */
159         *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
160         temp = *(volatile unsigned int *) CHRP_REG_DATA;
161         return PCISWAP (temp);          /* swap the data upon return */
162 }
163
164 /*
165  *  This procedure writes a 32-bit address MPC107 register.  It swaps
166  *  the address to little endian before writing it to config address.
167  */
168
169 void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal)
170 {
171         /* swap the addr. to little endian */
172         *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
173         *(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal);
174         return;
175 }
176
177
178 /*
179  *  Write a byte (8 bits) to a memory location.
180  */
181 void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data)
182 {
183         *(unsigned char *) addr = data;
184         __asm__ ("sync");
185 }
186
187 /*
188  *  Write a word (16 bits) to a memory location after the value
189  *  has been byte swapped (big to little endian or vice versa)
190  */
191
192 void mpc824x_mpc107_write16 (unsigned int address, unsigned short data)
193 {
194         *(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data);
195         __asm__ ("sync");
196 }
197
198 /*
199  *  Write a long word (32 bits) to a memory location after the value
200  *  has been byte swapped (big to little endian or vice versa)
201  */
202
203 void mpc824x_mpc107_write32 (unsigned int address, unsigned int data)
204 {
205         *(volatile unsigned int *) address = LONGSWAP (data);
206         __asm__ ("sync");
207 }
208
209 /*
210  *  Read a byte (8 bits) from a memory location.
211  */
212 unsigned char mpc824x_mpc107_read8 (unsigned int addr)
213 {
214         return *(volatile unsigned char *) addr;
215 }
216
217
218 /*
219  *  Read a word (16 bits) from a memory location, and byte swap the
220  *  value before returning to the caller.
221  */
222 unsigned short mpc824x_mpc107_read16 (unsigned int address)
223 {
224         unsigned short retVal;
225
226         retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address);
227         return retVal;
228 }
229
230
231 /*
232  *  Read a long word (32 bits) from a memory location, and byte
233  *  swap the value before returning to the caller.
234  */
235 unsigned int mpc824x_mpc107_read32 (unsigned int address)
236 {
237         unsigned int retVal;
238
239         retVal = LONGSWAP (*(unsigned int *) address);
240         return (retVal);
241 }
242
243
244 /*
245  *  Read a register in the Embedded Utilities Memory Block address
246  *  space.
247  *  Input: regNum - register number + utility base address.  Example,
248  *         the base address of EPIC is 0x40000, the register number
249  *         being passed is 0x40000+the address of the target register.
250  *         (See epic.h for register addresses).
251  *  Output:  The 32 bit little endian value of the register.
252  */
253
254 unsigned int mpc824x_eummbar_read (unsigned int regNum)
255 {
256         unsigned int temp;
257
258         temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum);
259         temp = PCISWAP (temp);
260         return temp;
261 }
262
263
264 /*
265  *  Write a value to a register in the Embedded Utilities Memory
266  *  Block address space.
267  *  Input: regNum - register number + utility base address.  Example,
268  *                  the base address of EPIC is 0x40000, the register
269  *                  number is 0x40000+the address of the target register.
270  *                  (See epic.h for register addresses).
271  *         regVal - value to be written to the register.
272  */
273
274 void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal)
275 {
276         *(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal);
277         return;
278 }
279
280 /* ------------------------------------------------------------------------- */