[b7a6d23a] | 1 | /* |
---|
[dbd8b307] | 2 | * This routine does the bulk of the system initialization. |
---|
| 3 | */ |
---|
| 4 | |
---|
| 5 | /* |
---|
[b7a6d23a] | 6 | * COPYRIGHT (c) 1989-1998. |
---|
| 7 | * On-Line Applications Research Corporation (OAR). |
---|
| 8 | * |
---|
| 9 | * The license and distribution terms for this file may be |
---|
| 10 | * found in the file LICENSE in this distribution or at |
---|
| 11 | * http://www.OARcorp.com/rtems/license.html. |
---|
| 12 | * |
---|
| 13 | * Modified to support the MCP750. |
---|
| 14 | * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr |
---|
| 15 | * |
---|
| 16 | * Modified to support the Synergy VGM & Motorola PowerPC boards. |
---|
| 17 | * (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004, 2005 |
---|
| 18 | * |
---|
| 19 | * Modified to support the mvme5500 BSP |
---|
| 20 | * (C) by Kate Feng <feng1@bnl.gov>, 2003, 2004 |
---|
| 21 | * under the contract DE-AC02-98CH10886 with the Deaprtment of Energy |
---|
| 22 | * |
---|
| 23 | * T. Straumann: 2005-2007; stolen again for 'beatnik'... |
---|
| 24 | */ |
---|
| 25 | #include <string.h> |
---|
| 26 | #include <stdlib.h> |
---|
| 27 | #include <ctype.h> |
---|
| 28 | |
---|
| 29 | #include <rtems/system.h> |
---|
| 30 | #include <rtems/libio.h> |
---|
| 31 | #include <rtems/libcsupport.h> |
---|
| 32 | #include <rtems/bspIo.h> |
---|
[24bf11e] | 33 | #include <rtems/counter.h> |
---|
[b7a6d23a] | 34 | #include <rtems/powerpc/powerpc.h> |
---|
| 35 | /*#include <bsp/consoleIo.h>*/ |
---|
| 36 | #include <libcpu/spr.h> /* registers.h is included here */ |
---|
| 37 | #include <bsp.h> |
---|
[dbd8b307] | 38 | #include <bsp/bootcard.h> |
---|
[b7a6d23a] | 39 | #include <bsp/uart.h> |
---|
| 40 | #include <bsp/pci.h> |
---|
| 41 | #include <bsp/gtreg.h> |
---|
| 42 | #include <bsp/gt_timer.h> |
---|
| 43 | #include <libcpu/bat.h> |
---|
| 44 | #include <libcpu/pte121.h> |
---|
| 45 | #include <libcpu/cpuIdent.h> |
---|
| 46 | #include <bsp/vectors.h> |
---|
| 47 | #include <bsp/vpd.h> |
---|
| 48 | |
---|
| 49 | /* for RTEMS_VERSION :-( I dont like the preassembled string */ |
---|
| 50 | #include <rtems/sptables.h> |
---|
| 51 | |
---|
| 52 | #define SHOW_MORE_INIT_SETTINGS |
---|
| 53 | |
---|
[5650235] | 54 | BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial; |
---|
| 55 | BSP_polling_getchar_function_type BSP_poll_char = NULL; |
---|
[b7a6d23a] | 56 | |
---|
| 57 | extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *); |
---|
| 58 | extern void BSP_pgtbl_activate(Triv121PgTbl); |
---|
| 59 | extern void BSP_motload_pci_fixup(void); |
---|
| 60 | |
---|
| 61 | extern unsigned long __rtems_end[]; |
---|
| 62 | |
---|
| 63 | /* We really shouldn't use these since MMUoff also sets IP; |
---|
| 64 | * nevertheless, during early init I don't care for now |
---|
| 65 | */ |
---|
| 66 | extern void MMUoff(void); |
---|
| 67 | extern void MMUon(void); |
---|
| 68 | |
---|
| 69 | extern uint32_t probeMemoryEnd(void); |
---|
| 70 | |
---|
| 71 | SPR_RW(SPRG0) |
---|
| 72 | SPR_RW(SPRG1) |
---|
| 73 | SPR_RO(HID1) |
---|
| 74 | |
---|
| 75 | /* Table of PLL multipliers for 7455/7457: |
---|
| 76 | 01000 2 00010 7.5 00000 11.5 00001 17 |
---|
| 77 | 10000 3 11000 8 10111 12 00101 18 |
---|
| 78 | 10100 4 01100 8.5 11111 12.5 00111 20 |
---|
| 79 | 10110 5 01111 9 01011 13 01001 21 |
---|
| 80 | 10010 5.5 01110 9.5 11100 13.5 01101 24 |
---|
| 81 | 11010 6 10101 10 11001 14 11101 28 |
---|
| 82 | 01010 6.5 10001 10.5 00011 15 00110 bypass |
---|
| 83 | 00100 7 10011 11 11011 16 11110 off |
---|
| 84 | */ |
---|
| 85 | |
---|
| 86 | /* Sorted according to CFG bits and multiplied by 2 it looks |
---|
| 87 | * like this (note that this is in sequential order, not |
---|
| 88 | * tabulated as above) |
---|
| 89 | */ |
---|
| 90 | signed char mpc7450PllMultByTwo[32] = { |
---|
| 91 | 23, 34, 15, 30, |
---|
| 92 | 14, 36, 2/*bypass*/, 40, |
---|
| 93 | 4, 42, 13, 26, |
---|
| 94 | 17, 48, 19, 18, |
---|
| 95 | 6, 21, 11, 22, |
---|
| 96 | 8, 20, 10, 24, |
---|
| 97 | 16, 28, 12, 32, |
---|
| 98 | 27, 56, 0/*off*/, 25, |
---|
| 99 | }; |
---|
| 100 | |
---|
| 101 | uint32_t bsp_clicks_per_usec = 0; |
---|
| 102 | |
---|
| 103 | /* |
---|
| 104 | * Total memory using probing. |
---|
| 105 | */ |
---|
| 106 | unsigned int BSP_mem_size; |
---|
| 107 | |
---|
| 108 | /* |
---|
| 109 | * PCI Bus Frequency |
---|
| 110 | */ |
---|
| 111 | unsigned int BSP_bus_frequency = 0xdeadbeef; |
---|
| 112 | /* |
---|
| 113 | * processor clock frequency |
---|
| 114 | */ |
---|
| 115 | unsigned int BSP_processor_frequency = 0xdeadbeef; |
---|
| 116 | |
---|
| 117 | /* |
---|
| 118 | * Time base divisior (bus freq / TB clock) |
---|
| 119 | */ |
---|
| 120 | unsigned int BSP_time_base_divisor = 4000; /* most 604+ CPUs seem to use this */ |
---|
| 121 | |
---|
| 122 | /* Board identification string */ |
---|
| 123 | char BSP_productIdent[20] = {0}; |
---|
| 124 | char BSP_serialNumber[20] = {0}; |
---|
| 125 | |
---|
| 126 | /* VPD appends an extra char -- what for ? */ |
---|
| 127 | char BSP_enetAddr0[7] = {0}; |
---|
| 128 | char BSP_enetAddr1[7] = {0}; |
---|
| 129 | |
---|
| 130 | char *rtems_progname; |
---|
| 131 | |
---|
| 132 | #define CMDLINE_BUF_SIZE 2048 |
---|
| 133 | |
---|
| 134 | static char cmdline_buf[CMDLINE_BUF_SIZE]; |
---|
| 135 | char *BSP_commandline_string = cmdline_buf; |
---|
| 136 | |
---|
| 137 | /* this routine is called early and must be safe with a not properly |
---|
| 138 | * aligned stack |
---|
| 139 | */ |
---|
[2cb449d] | 140 | char *save_boot_params( |
---|
| 141 | void *r3, |
---|
| 142 | void *r4, |
---|
| 143 | void *r5, |
---|
| 144 | char *cmdline_start, |
---|
| 145 | char *cmdline_end |
---|
| 146 | ) |
---|
[b7a6d23a] | 147 | { |
---|
| 148 | int i=cmdline_end-cmdline_start; |
---|
| 149 | if ( i >= CMDLINE_BUF_SIZE ) |
---|
| 150 | i = CMDLINE_BUF_SIZE-1; |
---|
| 151 | else if ( i < 0 ) |
---|
| 152 | i = 0; |
---|
| 153 | memmove(cmdline_buf, cmdline_start, i); |
---|
| 154 | cmdline_buf[i]=0; |
---|
| 155 | return cmdline_buf; |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | static BSP_BoardType board_type = Unknown; |
---|
| 159 | |
---|
| 160 | BSP_BoardType |
---|
| 161 | BSP_getBoardType( void ) |
---|
| 162 | { |
---|
| 163 | return board_type; |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | /* |
---|
| 167 | * bsp_start |
---|
| 168 | * |
---|
| 169 | * This routine does the bulk of the system initialization. |
---|
| 170 | */ |
---|
| 171 | |
---|
| 172 | void bsp_start( void ) |
---|
| 173 | { |
---|
| 174 | unsigned char *stack; |
---|
| 175 | char *chpt; |
---|
| 176 | uint32_t intrStackStart; |
---|
| 177 | uint32_t intrStackSize; |
---|
| 178 | |
---|
| 179 | Triv121PgTbl pt=0; |
---|
| 180 | |
---|
| 181 | VpdBufRec vpdData [] = { |
---|
| 182 | { key: ProductIdent, instance: 0, buf: BSP_productIdent, buflen: sizeof(BSP_productIdent) - 1 }, |
---|
| 183 | { key: SerialNumber, instance: 0, buf: BSP_serialNumber, buflen: sizeof(BSP_serialNumber) - 1 }, |
---|
| 184 | { key: CpuClockHz, instance: 0, buf: &BSP_processor_frequency, buflen: sizeof(BSP_processor_frequency) }, |
---|
| 185 | { key: BusClockHz, instance: 0, buf: &BSP_bus_frequency, buflen: sizeof(BSP_bus_frequency) }, |
---|
| 186 | { key: EthernetAddr, instance: 0, buf: BSP_enetAddr0, buflen: sizeof(BSP_enetAddr0) }, |
---|
| 187 | { key: EthernetAddr, instance: 1, buf: BSP_enetAddr1, buflen: sizeof(BSP_enetAddr1) }, |
---|
| 188 | VPD_END |
---|
| 189 | }; |
---|
| 190 | |
---|
| 191 | /* T. Straumann: 4/2005 |
---|
| 192 | * |
---|
| 193 | * Need to map the system registers early, so we can printk... |
---|
| 194 | * (otherwise we silently die) |
---|
| 195 | */ |
---|
| 196 | /* map the PCI 0, 1 Domain I/O space, GT64260B registers |
---|
| 197 | * and the reserved area so that the size is the power of 2. |
---|
| 198 | */ |
---|
| 199 | setdbat(7, BSP_DEV_AND_PCI_IO_BASE, BSP_DEV_AND_PCI_IO_BASE, BSP_DEV_AND_PCI_IO_SIZE, IO_PAGE); |
---|
| 200 | |
---|
| 201 | /* Intersperse messages with actions to help locate problems */ |
---|
| 202 | printk("-----------------------------------------\n"); |
---|
| 203 | |
---|
| 204 | /* |
---|
| 205 | * Get CPU identification dynamically. Note that the get_ppc_cpu_type() & friends functions |
---|
| 206 | * store the result in global variables so that it can be used latter... |
---|
| 207 | * This also verifies that we run on a known CPU. |
---|
| 208 | */ |
---|
| 209 | get_ppc_cpu_type(); |
---|
| 210 | get_ppc_cpu_revision(); |
---|
| 211 | |
---|
| 212 | /* Make sure we detect a known host bridge */ |
---|
| 213 | BSP_getDiscoveryVersion(/* assert detection */ 1); |
---|
| 214 | |
---|
[f17a8e01] | 215 | printk("Welcome to RTEMS %s\n", _RTEMS_version ); |
---|
[b7a6d23a] | 216 | |
---|
| 217 | /* Leave all caches as MotLoad left them. Seems to be fine */ |
---|
| 218 | |
---|
| 219 | /* |
---|
| 220 | * the initial stack has aready been set to this value in start.S |
---|
| 221 | * so there is no need to set it in r1 again... It is just for info |
---|
| 222 | * so that it can be printed without accessing R1. |
---|
| 223 | */ |
---|
[90b6801] | 224 | __asm__ volatile("mr %0, 1":"=r"(stack)); |
---|
[b7a6d23a] | 225 | |
---|
| 226 | /* tag the bottom (T. Straumann 6/36/2001 <strauman@slac.stanford.edu>) */ |
---|
| 227 | |
---|
| 228 | *((uint32_t *)stack) = 0; |
---|
| 229 | |
---|
| 230 | /* |
---|
| 231 | * Initialize the interrupt related settings |
---|
| 232 | * SPRG0 = interrupt nesting level count |
---|
| 233 | * SPRG1 = software managed IRQ stack |
---|
| 234 | * |
---|
| 235 | * This could be done latter (e.g in IRQ_INIT) but it helps to understand |
---|
| 236 | * some settings below... |
---|
| 237 | */ |
---|
| 238 | intrStackStart = (uint32_t)__rtems_end; |
---|
| 239 | intrStackSize = rtems_configuration_get_interrupt_stack_size(); |
---|
| 240 | |
---|
| 241 | /* |
---|
| 242 | * Initialize default raw exception handlers. See vectors/vectors_init.c |
---|
| 243 | */ |
---|
[801b5d8] | 244 | ppc_exc_initialize(intrStackStart, intrStackSize); |
---|
[b7a6d23a] | 245 | |
---|
| 246 | printk("CPU: %s\n", get_ppc_cpu_type_name(current_ppc_cpu)); |
---|
| 247 | |
---|
| 248 | /* |
---|
| 249 | * Initialize RTEMS IRQ system |
---|
| 250 | */ |
---|
| 251 | BSP_rtems_irq_mng_init(0); |
---|
| 252 | |
---|
| 253 | BSP_vpdRetrieveFields(vpdData); |
---|
| 254 | |
---|
| 255 | if ( !strncmp(BSP_productIdent,"MVME5500",8) ) |
---|
| 256 | board_type = MVME5500; |
---|
| 257 | else if ( !strncmp(BSP_productIdent,"MVME6100",8) ) |
---|
| 258 | board_type = MVME6100; |
---|
| 259 | |
---|
| 260 | printk("Board Type: %s (S/N %s)\n", |
---|
| 261 | BSP_productIdent[0] ? BSP_productIdent : "n/a", |
---|
| 262 | BSP_serialNumber[0] ? BSP_serialNumber : "n/a"); |
---|
| 263 | |
---|
| 264 | if ( 0xdeadbeef == BSP_bus_frequency ) { |
---|
| 265 | BSP_bus_frequency = 133333333; |
---|
| 266 | printk("Bus Clock Freq NOT FOUND in VPD; using %10u Hz\n", |
---|
| 267 | BSP_bus_frequency); |
---|
| 268 | } else { |
---|
| 269 | printk("Bus Clock Freq: %10u Hz\n", |
---|
| 270 | BSP_bus_frequency); |
---|
| 271 | } |
---|
| 272 | |
---|
| 273 | if ( 0xdeadbeef == BSP_processor_frequency ) { |
---|
| 274 | BSP_processor_frequency = BSP_bus_frequency/2; |
---|
| 275 | BSP_processor_frequency *= mpc7450PllMultByTwo[ (_read_HID1() >> (31-19)) & 31 ]; |
---|
| 276 | } |
---|
| 277 | printk("CPU Clock Freq: %10u Hz\n", BSP_processor_frequency); |
---|
| 278 | |
---|
| 279 | /* probe real memory size; if it's more than 256M we can't currently access it |
---|
| 280 | * since at this point only BAT-0 maps 0..256M |
---|
| 281 | */ |
---|
| 282 | BSP_mem_size = probeMemoryEnd(); |
---|
| 283 | |
---|
| 284 | if ( (chpt = strstr(BSP_commandline_string,"MEMSZ=")) ) { |
---|
| 285 | char *endp; |
---|
| 286 | uint32_t sz; |
---|
| 287 | chpt+=6 /* strlen("MEMSZ=") */; |
---|
| 288 | sz = strtoul(chpt, &endp, 0); |
---|
| 289 | if ( endp != chpt ) |
---|
| 290 | BSP_mem_size = sz; |
---|
| 291 | } |
---|
| 292 | |
---|
| 293 | printk("Memory: %10u bytes\n", BSP_mem_size); |
---|
| 294 | |
---|
| 295 | if ( BSP_mem_size > 0x10000000 ) { |
---|
| 296 | uint32_t s; |
---|
| 297 | if ( BSP_mem_size > 0x80000000 ) { |
---|
| 298 | BSP_mem_size = 0x80000000; |
---|
| 299 | printk("Memory clipped to 0x%08x for now, sorry\n", BSP_mem_size); |
---|
| 300 | } |
---|
| 301 | for ( s = 0x20000000; s < BSP_mem_size ; s<<=1) |
---|
| 302 | ; |
---|
| 303 | MMUoff(); |
---|
| 304 | /* since it's currently in use we must first surrender it */ |
---|
| 305 | setdbat(0, 0, 0, 0, 0); |
---|
| 306 | setdbat(0, 0, 0, s, _PAGE_RW); |
---|
| 307 | MMUon(); |
---|
| 308 | } |
---|
| 309 | |
---|
| 310 | printk("-----------------------------------------\n"); |
---|
| 311 | |
---|
| 312 | /* Maybe not setup yet because of the warning message */ |
---|
| 313 | |
---|
| 314 | /* Allocate and set up the page table mappings |
---|
| 315 | * This is only available on >604 CPUs. |
---|
| 316 | * |
---|
| 317 | * NOTE: This setup routine may modify the available memory |
---|
| 318 | * size. It is essential to call it before |
---|
| 319 | * calculating the workspace etc. |
---|
| 320 | */ |
---|
| 321 | pt = BSP_pgtbl_setup(&BSP_mem_size); |
---|
| 322 | if (!pt) |
---|
| 323 | printk("WARNING: unable to setup page tables.\n"); |
---|
| 324 | |
---|
| 325 | #ifdef SHOW_MORE_INIT_SETTINGS |
---|
| 326 | printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size); |
---|
| 327 | #endif |
---|
| 328 | |
---|
| 329 | /* |
---|
| 330 | * Set up our hooks |
---|
| 331 | */ |
---|
| 332 | |
---|
[fd8dca5] | 333 | bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); |
---|
[24bf11e] | 334 | rtems_counter_initialize_converter( |
---|
| 335 | BSP_bus_frequency / (BSP_time_base_divisor / 1000) |
---|
| 336 | ); |
---|
[b7a6d23a] | 337 | |
---|
| 338 | #ifdef SHOW_MORE_INIT_SETTINGS |
---|
[c479497] | 339 | printk( |
---|
| 340 | "Configuration.work_space_size = %x\n", |
---|
| 341 | rtems_configuration_get_work_space_size() |
---|
| 342 | ); |
---|
[b7a6d23a] | 343 | #endif |
---|
| 344 | |
---|
| 345 | /* Activate the page table mappings only after |
---|
| 346 | * initializing interrupts because the irq_mng_init() |
---|
| 347 | * routine needs to modify the text |
---|
| 348 | */ |
---|
| 349 | if ( pt ) { |
---|
| 350 | #ifdef SHOW_MORE_INIT_SETTINGS |
---|
| 351 | printk("Page table setup finished; will activate it NOW...\n"); |
---|
| 352 | #endif |
---|
| 353 | BSP_pgtbl_activate(pt); |
---|
| 354 | } |
---|
| 355 | |
---|
| 356 | #ifdef SHOW_MORE_INIT_SETTINGS |
---|
| 357 | printk("Going to start PCI buses scanning and initialization\n"); |
---|
| 358 | #endif |
---|
| 359 | BSP_pci_initialize(); |
---|
| 360 | |
---|
| 361 | /* need to tweak the motload setup */ |
---|
| 362 | BSP_motload_pci_fixup(); |
---|
| 363 | |
---|
| 364 | /* map 512M, 256 for PCI 256 for VME */ |
---|
| 365 | setdbat(5,BSP_PCI_HOSE0_MEM_BASE, BSP_PCI_HOSE0_MEM_BASE, BSP_PCI_HOSE0_MEM_SIZE, IO_PAGE); |
---|
| 366 | setdbat(6,BSP_PCI_HOSE1_MEM_BASE, BSP_PCI_HOSE1_MEM_BASE, 0x10000000, IO_PAGE); |
---|
| 367 | |
---|
| 368 | #ifdef SHOW_MORE_INIT_SETTINGS |
---|
| 369 | printk("Number of PCI buses found is : %d\n", pci_bus_count()); |
---|
| 370 | #endif |
---|
| 371 | |
---|
| 372 | /* |
---|
| 373 | * Initialize hardware timer facility (not used by BSP itself) |
---|
| 374 | * Needs PCI to identify discovery version... |
---|
| 375 | */ |
---|
| 376 | BSP_timers_initialize(); |
---|
| 377 | |
---|
| 378 | #ifdef SHOW_MORE_INIT_SETTINGS |
---|
| 379 | printk("MSR %x \n", _read_MSR()); |
---|
| 380 | printk("Exit from bspstart\n"); |
---|
| 381 | #endif |
---|
| 382 | } |
---|