1 /* 2 * (C) Copyright 2000-2002 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 /* 9 * m8xx.c 10 * 11 * CPU specific code 12 * 13 * written or collected and sometimes rewritten by 14 * Magnus Damm <damm@bitsmart.com> 15 * 16 * minor modifications by 17 * Wolfgang Denk <wd@denx.de> 18 */ 19 20 #include <common.h> 21 #include <watchdog.h> 22 #include <command.h> 23 #include <mpc8xx.h> 24 #include <commproc.h> 25 #include <netdev.h> 26 #include <asm/cache.h> 27 #include <linux/compiler.h> 28 #include <asm/io.h> 29 30 #if defined(CONFIG_OF_LIBFDT) 31 #include <libfdt.h> 32 #include <fdt_support.h> 33 #endif 34 35 DECLARE_GLOBAL_DATA_PTR; 36 37 static char *cpu_warning = "\n " \ 38 "*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***"; 39 40 static int check_CPU (long clock, uint pvr, uint immr) 41 { 42 char *id_str = 43 NULL; 44 immap_t __iomem *immap = (immap_t __iomem *)(immr & 0xFFFF0000); 45 uint k, m; 46 char buf[32]; 47 char pre = 'X'; 48 char *mid = "xx"; 49 char *suf; 50 51 /* the highest 16 bits should be 0x0050 for a 860 */ 52 53 if ((pvr >> 16) != 0x0050) 54 return -1; 55 56 k = (immr << 16) | 57 in_be16(&immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]); 58 m = 0; 59 suf = ""; 60 61 /* 62 * Some boards use sockets so different CPUs can be used. 63 * We have to check chip version in run time. 64 */ 65 switch (k) { 66 /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */ 67 case 0x08010004: /* Rev. A.0 */ 68 suf = "A"; 69 /* fall through */ 70 case 0x08000003: /* Rev. 0.3 */ 71 pre = 'M'; m = 1; 72 if (id_str == NULL) 73 id_str = 74 "PC866x"; /* Unknown chip from MPC866 family */ 75 break; 76 case 0x09000000: pre = 'M'; mid = suf = ""; m = 1; 77 if (id_str == NULL) 78 id_str = "PC885"; /* 870/875/880/885 */ 79 break; 80 81 default: suf = NULL; break; 82 } 83 84 if (id_str == NULL) 85 id_str = "PC86x"; /* Unknown 86x chip */ 86 if (suf) 87 printf ("%c%s%sZPnn%s", pre, id_str, mid, suf); 88 else 89 printf ("unknown M%s (0x%08x)", id_str, k); 90 91 printf (" at %s MHz: ", strmhz (buf, clock)); 92 93 print_size(checkicache(), " I-Cache "); 94 print_size(checkdcache(), " D-Cache"); 95 96 /* do we have a FEC (860T/P or 852/859/866/885)? */ 97 98 out_be32(&immap->im_cpm.cp_fec.fec_addr_low, 0x12345678); 99 if (in_be32(&immap->im_cpm.cp_fec.fec_addr_low) == 0x12345678) 100 printf (" FEC present"); 101 102 if (!m) { 103 puts (cpu_warning); 104 } 105 106 putc ('\n'); 107 108 return 0; 109 } 110 111 /* ------------------------------------------------------------------------- */ 112 113 int checkcpu (void) 114 { 115 ulong clock = gd->cpu_clk; 116 uint immr = get_immr (0); /* Return full IMMR contents */ 117 uint pvr = get_pvr (); 118 119 puts ("CPU: "); 120 121 return check_CPU (clock, pvr, immr); 122 } 123 124 /* ------------------------------------------------------------------------- */ 125 /* L1 i-cache */ 126 127 int checkicache (void) 128 { 129 immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; 130 memctl8xx_t __iomem *memctl = &immap->im_memctl; 131 u32 cacheon = rd_ic_cst () & IDC_ENABLED; 132 /* probe in flash memoryarea */ 133 u32 k = in_be32(&memctl->memc_br0) & ~0x00007fff; 134 u32 m; 135 u32 lines = -1; 136 137 wr_ic_cst (IDC_UNALL); 138 wr_ic_cst (IDC_INVALL); 139 wr_ic_cst (IDC_DISABLE); 140 __asm__ volatile ("isync"); 141 142 while (!((m = rd_ic_cst ()) & IDC_CERR2)) { 143 wr_ic_adr (k); 144 wr_ic_cst (IDC_LDLCK); 145 __asm__ volatile ("isync"); 146 147 lines++; 148 k += 0x10; /* the number of bytes in a cacheline */ 149 } 150 151 wr_ic_cst (IDC_UNALL); 152 wr_ic_cst (IDC_INVALL); 153 154 if (cacheon) 155 wr_ic_cst (IDC_ENABLE); 156 else 157 wr_ic_cst (IDC_DISABLE); 158 159 __asm__ volatile ("isync"); 160 161 return lines << 4; 162 }; 163 164 /* ------------------------------------------------------------------------- */ 165 /* L1 d-cache */ 166 /* call with cache disabled */ 167 168 int checkdcache (void) 169 { 170 immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; 171 memctl8xx_t __iomem *memctl = &immap->im_memctl; 172 u32 cacheon = rd_dc_cst () & IDC_ENABLED; 173 /* probe in flash memoryarea */ 174 u32 k = in_be32(&memctl->memc_br0) & ~0x00007fff; 175 u32 m; 176 u32 lines = -1; 177 178 wr_dc_cst (IDC_UNALL); 179 wr_dc_cst (IDC_INVALL); 180 wr_dc_cst (IDC_DISABLE); 181 182 while (!((m = rd_dc_cst ()) & IDC_CERR2)) { 183 wr_dc_adr (k); 184 wr_dc_cst (IDC_LDLCK); 185 lines++; 186 k += 0x10; /* the number of bytes in a cacheline */ 187 } 188 189 wr_dc_cst (IDC_UNALL); 190 wr_dc_cst (IDC_INVALL); 191 192 if (cacheon) 193 wr_dc_cst (IDC_ENABLE); 194 else 195 wr_dc_cst (IDC_DISABLE); 196 197 return lines << 4; 198 }; 199 200 /* ------------------------------------------------------------------------- */ 201 202 void upmconfig (uint upm, uint * table, uint size) 203 { 204 uint i; 205 uint addr = 0; 206 immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; 207 memctl8xx_t __iomem *memctl = &immap->im_memctl; 208 209 for (i = 0; i < size; i++) { 210 out_be32(&memctl->memc_mdr, table[i]); /* (16-15) */ 211 out_be32(&memctl->memc_mcr, addr | upm); /* (16-16) */ 212 addr++; 213 } 214 } 215 216 /* ------------------------------------------------------------------------- */ 217 218 int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 219 { 220 ulong msr, addr; 221 222 immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR; 223 224 /* Checkstop Reset enable */ 225 setbits_be32(&immap->im_clkrst.car_plprcr, PLPRCR_CSR); 226 227 /* Interrupts and MMU off */ 228 __asm__ volatile ("mtspr 81, 0"); 229 __asm__ volatile ("mfmsr %0":"=r" (msr)); 230 231 msr &= ~0x1030; 232 __asm__ volatile ("mtmsr %0"::"r" (msr)); 233 234 /* 235 * Trying to execute the next instruction at a non-existing address 236 * should cause a machine check, resulting in reset 237 */ 238 #ifdef CONFIG_SYS_RESET_ADDRESS 239 addr = CONFIG_SYS_RESET_ADDRESS; 240 #else 241 /* 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... 246 */ 247 addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong); 248 #endif 249 ((void (*)(void)) addr) (); 250 return 1; 251 } 252 253 /* ------------------------------------------------------------------------- */ 254 255 /* 256 * Get timebase clock frequency (like cpu_clk in Hz) 257 * 258 * See sections 14.2 and 14.6 of the User's Manual 259 */ 260 unsigned long get_tbclk (void) 261 { 262 uint immr = get_immr (0); /* Return full IMMR contents */ 263 immap_t __iomem *immap = (immap_t __iomem *)(immr & 0xFFFF0000); 264 ulong oscclk, factor, pll; 265 266 if (in_be32(&immap->im_clkrst.car_sccr) & SCCR_TBS) 267 return (gd->cpu_clk / 16); 268 269 pll = in_be32(&immap->im_clkrst.car_plprcr); 270 271 #define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT) 272 273 /* 274 * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication 275 * factor is calculated as follows: 276 * 277 * MFN 278 * MFI + ------- 279 * MFD + 1 280 * factor = ----------------- 281 * (PDF + 1) * 2^S 282 * 283 */ 284 factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN)/(PLPRCR_val(MFD)+1))/ 285 (PLPRCR_val(PDF)+1) / (1<<PLPRCR_val(S)); 286 287 oscclk = gd->cpu_clk / factor; 288 289 if ((in_be32(&immap->im_clkrst.car_sccr) & SCCR_RTSEL) == 0 || 290 factor > 2) 291 return (oscclk / 4); 292 293 return (oscclk / 16); 294 } 295 296 /* ------------------------------------------------------------------------- */ 297 298 #if defined(CONFIG_WATCHDOG) 299 void watchdog_reset (void) 300 { 301 int re_enable = disable_interrupts (); 302 303 reset_8xx_watchdog((immap_t __iomem *)CONFIG_SYS_IMMR); 304 if (re_enable) 305 enable_interrupts (); 306 } 307 #endif /* CONFIG_WATCHDOG */ 308 309 #if defined(CONFIG_WATCHDOG) 310 311 void reset_8xx_watchdog(immap_t __iomem *immr) 312 { 313 /* 314 * All other boards use the MPC8xx Internal Watchdog 315 */ 316 out_be16(&immr->im_siu_conf.sc_swsr, 0x556c); /* write magic1 */ 317 out_be16(&immr->im_siu_conf.sc_swsr, 0xaa39); /* write magic2 */ 318 } 319 #endif /* CONFIG_WATCHDOG */ 320 321 /* 322 * Initializes on-chip ethernet controllers. 323 * to override, implement board_eth_init() 324 */ 325 int cpu_eth_init(bd_t *bis) 326 { 327 #if defined(FEC_ENET) 328 fec_initialize(bis); 329 #endif 330 return 0; 331 } 332