]>
git.ipfire.org Git - people/ms/u-boot.git/blob - arch/powerpc/cpu/mpc8xx/cpu.c
2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * SPDX-License-Identifier: GPL-2.0+
13 * written or collected and sometimes rewritten by
14 * Magnus Damm <damm@bitsmart.com>
16 * minor modifications by
17 * Wolfgang Denk <wd@denx.de>
26 #include <asm/cache.h>
27 #include <linux/compiler.h>
30 #if defined(CONFIG_OF_LIBFDT)
32 #include <fdt_support.h>
35 DECLARE_GLOBAL_DATA_PTR
;
37 static char *cpu_warning
= "\n " \
38 "*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***";
40 static int check_CPU (long clock
, uint pvr
, uint immr
)
44 volatile immap_t
*immap
= (immap_t
*) (immr
& 0xFFFF0000);
51 /* the highest 16 bits should be 0x0050 for a 860 */
53 if ((pvr
>> 16) != 0x0050)
57 immap
->im_cpm
.cp_dparam16
[PROFF_REVNUM
/ sizeof(u16
)];
62 * Some boards use sockets so different CPUs can be used.
63 * We have to check chip version in run time.
66 /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
67 case 0x08010004: /* Rev. A.0 */
70 case 0x08000003: /* Rev. 0.3 */
74 "PC866x"; /* Unknown chip from MPC866 family */
76 case 0x09000000: pre
= 'M'; mid
= suf
= ""; m
= 1;
78 id_str
= "PC885"; /* 870/875/880/885 */
81 default: suf
= NULL
; break;
85 id_str
= "PC86x"; /* Unknown 86x chip */
87 printf ("%c%s%sZPnn%s", pre
, id_str
, mid
, suf
);
89 printf ("unknown M%s (0x%08x)", id_str
, k
);
91 printf (" at %s MHz: ", strmhz (buf
, clock
));
93 print_size(checkicache(), " I-Cache ");
94 print_size(checkdcache(), " D-Cache");
96 /* do we have a FEC (860T/P or 852/859/866/885)? */
98 immap
->im_cpm
.cp_fec
.fec_addr_low
= 0x12345678;
99 if (immap
->im_cpm
.cp_fec
.fec_addr_low
== 0x12345678) {
100 printf (" FEC present");
112 /* ------------------------------------------------------------------------- */
116 ulong clock
= gd
->cpu_clk
;
117 uint immr
= get_immr (0); /* Return full IMMR contents */
118 uint pvr
= get_pvr ();
122 return check_CPU (clock
, pvr
, immr
);
125 /* ------------------------------------------------------------------------- */
128 int checkicache (void)
130 volatile immap_t
*immap
= (immap_t
*) CONFIG_SYS_IMMR
;
131 volatile memctl8xx_t
*memctl
= &immap
->im_memctl
;
132 u32 cacheon
= rd_ic_cst () & IDC_ENABLED
;
134 u32 k
= memctl
->memc_br0
& ~0x00007fff; /* probe in flash memoryarea */
138 wr_ic_cst (IDC_UNALL
);
139 wr_ic_cst (IDC_INVALL
);
140 wr_ic_cst (IDC_DISABLE
);
141 __asm__
volatile ("isync");
143 while (!((m
= rd_ic_cst ()) & IDC_CERR2
)) {
145 wr_ic_cst (IDC_LDLCK
);
146 __asm__
volatile ("isync");
149 k
+= 0x10; /* the number of bytes in a cacheline */
152 wr_ic_cst (IDC_UNALL
);
153 wr_ic_cst (IDC_INVALL
);
156 wr_ic_cst (IDC_ENABLE
);
158 wr_ic_cst (IDC_DISABLE
);
160 __asm__
volatile ("isync");
165 /* ------------------------------------------------------------------------- */
167 /* call with cache disabled */
169 int checkdcache (void)
171 volatile immap_t
*immap
= (immap_t
*) CONFIG_SYS_IMMR
;
172 volatile memctl8xx_t
*memctl
= &immap
->im_memctl
;
173 u32 cacheon
= rd_dc_cst () & IDC_ENABLED
;
175 u32 k
= memctl
->memc_br0
& ~0x00007fff; /* probe in flash memoryarea */
179 wr_dc_cst (IDC_UNALL
);
180 wr_dc_cst (IDC_INVALL
);
181 wr_dc_cst (IDC_DISABLE
);
183 while (!((m
= rd_dc_cst ()) & IDC_CERR2
)) {
185 wr_dc_cst (IDC_LDLCK
);
187 k
+= 0x10; /* the number of bytes in a cacheline */
190 wr_dc_cst (IDC_UNALL
);
191 wr_dc_cst (IDC_INVALL
);
194 wr_dc_cst (IDC_ENABLE
);
196 wr_dc_cst (IDC_DISABLE
);
201 /* ------------------------------------------------------------------------- */
203 void upmconfig (uint upm
, uint
* table
, uint size
)
207 volatile immap_t
*immap
= (immap_t
*) CONFIG_SYS_IMMR
;
208 volatile memctl8xx_t
*memctl
= &immap
->im_memctl
;
210 for (i
= 0; i
< size
; i
++) {
211 memctl
->memc_mdr
= table
[i
]; /* (16-15) */
212 memctl
->memc_mcr
= addr
| upm
; /* (16-16) */
217 /* ------------------------------------------------------------------------- */
219 int do_reset (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
223 volatile immap_t
*immap
= (immap_t
*) CONFIG_SYS_IMMR
;
225 immap
->im_clkrst
.car_plprcr
|= PLPRCR_CSR
; /* Checkstop Reset enable */
227 /* Interrupts and MMU off */
228 __asm__
volatile ("mtspr 81, 0");
229 __asm__
volatile ("mfmsr %0":"=r" (msr
));
232 __asm__
volatile ("mtmsr %0"::"r" (msr
));
235 * Trying to execute the next instruction at a non-existing address
236 * should cause a machine check, resulting in reset
238 #ifdef CONFIG_SYS_RESET_ADDRESS
239 addr
= CONFIG_SYS_RESET_ADDRESS
;
242 * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, CONFIG_SYS_MONITOR_BASE
243 * - sizeof (ulong) is usually a valid address. Better pick an address
244 * known to be invalid on your system and assign it to CONFIG_SYS_RESET_ADDRESS.
245 * "(ulong)-1" used to be a good choice for many systems...
247 addr
= CONFIG_SYS_MONITOR_BASE
- sizeof (ulong
);
249 ((void (*)(void)) addr
) ();
253 /* ------------------------------------------------------------------------- */
256 * Get timebase clock frequency (like cpu_clk in Hz)
258 * See sections 14.2 and 14.6 of the User's Manual
260 unsigned long get_tbclk (void)
262 uint immr
= get_immr (0); /* Return full IMMR contents */
263 volatile immap_t
*immap
= (volatile immap_t
*)(immr
& 0xFFFF0000);
264 ulong oscclk
, factor
, pll
;
266 if (immap
->im_clkrst
.car_sccr
& SCCR_TBS
) {
267 return (gd
->cpu_clk
/ 16);
270 pll
= immap
->im_clkrst
.car_plprcr
;
272 #define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
275 * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication
276 * factor is calculated as follows:
281 * factor = -----------------
285 factor
= (PLPRCR_val(MFI
) + PLPRCR_val(MFN
)/(PLPRCR_val(MFD
)+1))/
286 (PLPRCR_val(PDF
)+1) / (1<<PLPRCR_val(S
));
288 oscclk
= gd
->cpu_clk
/ factor
;
290 if ((immap
->im_clkrst
.car_sccr
& SCCR_RTSEL
) == 0 || factor
> 2) {
293 return (oscclk
/ 16);
296 /* ------------------------------------------------------------------------- */
298 #if defined(CONFIG_WATCHDOG)
299 void watchdog_reset (void)
301 int re_enable
= disable_interrupts ();
303 reset_8xx_watchdog ((immap_t
*) CONFIG_SYS_IMMR
);
305 enable_interrupts ();
307 #endif /* CONFIG_WATCHDOG */
309 #if defined(CONFIG_WATCHDOG)
311 void reset_8xx_watchdog (volatile immap_t
* immr
)
314 * All other boards use the MPC8xx Internal Watchdog
316 immr
->im_siu_conf
.sc_swsr
= 0x556c; /* write magic1 */
317 immr
->im_siu_conf
.sc_swsr
= 0xaa39; /* write magic2 */
319 #endif /* CONFIG_WATCHDOG */
322 * Initializes on-chip ethernet controllers.
323 * to override, implement board_eth_init()
325 int cpu_eth_init(bd_t
*bis
)
327 #if defined(FEC_ENET)