source: rtems/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c @ 7be6ad9

4.104.114.84.95
Last change on this file since 7be6ad9 was 7be6ad9, checked in by Eric Norum <WENorum@…>, on 10/20/04 at 15:21:05

Add MVME550 BSP

  • Property mode set to 100644
File size: 18.0 KB
Line 
1/*
2 *  This routine starts the application.  It includes application,
3 *  board, and monitor specific initialization and configuration.
4 *  The generic CPU dependent initialization has been performed
5 *  before this routine is invoked.
6 *
7 *  COPYRIGHT (c) 1989-1998.
8 *  On-Line Applications Research Corporation (OAR).
9 *
10 *  The license and distribution terms for this file may be
11 *  found in the file LICENSE in this distribution or at
12 *  http://www.OARcorp.com/rtems/license.html.
13 *
14 *  Modified to support the MCP750.
15 *  Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
16 *
17 *  Modified to support the Synergy VGM & Motorola PowerPC boards.
18 *  Many thanks to Till Straumann for providing assistance to port the
19 *  BSP_pgtbl_xxx().
20 *  (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004
21 *
22 *  Modified to support the MVME5500 board
23 *  (C) by S. Kate Feng <feng1@bnl.gov>, 2003, 2004
24 *
25 */
26#include <string.h>
27#include <stdlib.h>
28#include <ctype.h>
29
30#include <rtems/system.h>
31#include <rtems/libio.h>
32#include <rtems/libcsupport.h>
33/*#include <bsp/consoleIo.h>*/
34#include <libcpu/spr.h>   /* registers.h is included here */
35#include <bsp.h>
36#include <bsp/uart.h>
37#include <bsp/pci.h>
38#include <libcpu/bat.h>
39#include <libcpu/pte121.h>
40#include <libcpu/cpuIdent.h>
41#include <bsp/vectors.h>
42#include <bsp/bspException.h>
43
44/* for RTEMS_VERSION :-( I dont like the preassembled string */
45#include <rtems/sptables.h>
46
47#ifdef __RTEMS_APPLICATION__
48#undef __RTEMS_APPLICATION__
49#endif
50
51/*
52#define SHOW_MORE_INIT_SETTINGS
53#define SHOW_LCR1_REGISTER
54#define SHOW_LCR2_REGISTER
55#define SHOW_LCR3_REGISTER
56#define CONF_VPD
57*/
58
59/* there is no public Workspace_Free() variant :-( */
60#include <rtems/score/wkspace.h>
61
62rtems_unsigned32
63_bsp_sbrk_init(rtems_unsigned32 heap_start, rtems_unsigned32 *heap_size_p);
64
65/* provide access to the command line parameters */
66char *BSP_commandline_string = 0;
67
68BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial;
69
70extern char *BSP_build_date;
71extern void _return_to_ppcbug();
72extern unsigned long __rtems_end[];
73extern void L1_caches_enables();
74extern unsigned get_L1CR(), get_L2CR(), get_L3CR();
75extern unsigned set_L2CR(unsigned);
76extern void bsp_cleanup(void);
77extern Triv121PgTbl BSP_pgtbl_setup();
78extern void BSP_pgtbl_activate();
79extern int I2Cread_eeprom();
80extern void BSP_vme_config(void);
81
82SPR_RW(SPRG0)
83SPR_RW(SPRG1)
84
85typedef struct CmdLineRec_ {
86                unsigned long   size;
87                char            buf[0];
88} CmdLineRec, *CmdLine;
89
90
91#define mtspr(reg, val) \
92        __asm __volatile("mtspr %0,%1" : : "K"(reg), "r"(val))
93
94
95#define mfspr(reg) \
96        ( { unsigned val; \
97          __asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg)); \
98          val; } )
99
100/*
101 * Copy Additional boot param passed by boot loader
102 */
103#define MAX_LOADER_ADD_PARM 80
104char loaderParam[MAX_LOADER_ADD_PARM];
105
106/*
107 * Total memory using RESIDUAL DATA
108 */
109unsigned int BSP_mem_size;
110/*
111 * PCI Bus Frequency
112 */
113unsigned int BSP_bus_frequency;
114/*
115 * processor clock frequency
116 */
117unsigned int BSP_processor_frequency;
118/*
119 * Time base divisior (how many tick for 1 second).
120 */
121unsigned int BSP_time_base_divisor;
122unsigned char ConfVPD_buff[200];
123
124/*
125 * system init stack and soft ir stack size
126 */
127#define INIT_STACK_SIZE 0x1000
128#define INTR_STACK_SIZE CONFIGURE_INTERRUPT_STACK_MEMORY
129
130/* calculate the heap start */
131static unsigned long
132heapStart(void)
133{
134unsigned long rval;
135    rval = ((rtems_unsigned32) __rtems_end) +INIT_STACK_SIZE + INTR_STACK_SIZE;
136    if (rval & (CPU_ALIGNMENT-1))
137        rval = (rval + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1);
138        return rval;
139}
140
141void BSP_panic(char *s)
142{
143  printk("%s PANIC %s\n",_RTEMS_version, s);
144  __asm__ __volatile ("sc");
145}
146
147void _BSP_Fatal_error(unsigned int v)
148{
149  printk("%s PANIC ERROR %x\n",_RTEMS_version, v);
150  __asm__ __volatile ("sc");
151}
152 
153/*
154 *  The original table from the application and our copy of it with
155 *  some changes.
156 */
157
158extern rtems_configuration_table Configuration;
159
160rtems_configuration_table  BSP_Configuration;
161
162rtems_cpu_table Cpu_table;
163
164char *rtems_progname;
165
166/*
167 *  Use the shared implementations of the following routines
168 */
169 
170extern void bsp_postdriver_hook(void); /* see c/src/lib/libbsp/shared/bsppost.c */
171
172extern void bsp_libc_init( void *, unsigned32, int );
173
174/*
175 *  Function:   bsp_pretasking_hook
176 *  Created:    95/03/10
177 *
178 *  Description:
179 *      BSP pretasking hook.  Called just before drivers are initialized.
180 *      Used to setup libc and install any BSP extensions.
181 *
182 *  NOTES:
183 *      Must not use libc (to do io) from here, since drivers are
184 *      not yet initialized.
185 *
186 */
187
188void bsp_pretasking_hook(void)
189{
190    rtems_unsigned32        heap_start=heapStart();   
191    rtems_unsigned32        heap_size,heap_sbrk_spared;
192    char                    *buf;
193    extern rtems_unsigned32 _bsp_sbrk_init(rtems_unsigned32, rtems_unsigned32*);
194
195    heap_size = (BSP_mem_size - heap_start) - BSP_Configuration.work_space_size;
196
197    heap_sbrk_spared=_bsp_sbrk_init(heap_start, &heap_size);
198
199#ifdef SHOW_MORE_INIT_SETTINGS
200        printk(" HEAP start %x  size %x (%x bytes spared for sbrk)\n", heap_start, heap_size, heap_sbrk_spared);
201#endif   
202
203    bsp_libc_init((void *) 0, heap_size, heap_sbrk_spared);
204
205#ifdef RTEMS_DEBUG
206    rtems_debug_enable( RTEMS_DEBUG_ALL_MASK );
207#endif
208}
209
210void zero_bss()
211{
212  /* prevent these from being accessed in the short data areas */
213  extern unsigned long __bss_start[], __sbss_start[], __sbss_end[];
214  extern unsigned long __sbss2_start[], __sbss2_end[];
215  memset(__sbss_start, 0, ((unsigned) __sbss_end) - ((unsigned)__sbss_start));
216  memset(__sbss2_start, 0, ((unsigned) __sbss2_end) - ((unsigned)__sbss2_start));
217  memset(__bss_start, 0, ((unsigned) __rtems_end) - ((unsigned)__bss_start));
218}
219
220/* NOTE: we cannot simply malloc the commandline string;
221 * save_boot_params() is called during a very early stage when
222 * libc/malloc etc. are not yet initialized!
223 *
224 * Here's what we do:
225 *
226 * initial layout setup by the loader (preload.S):
227 *
228 * 0..RTEMS...__rtems_end | cmdline ....... TOP
229 *
230 * After the save_boot_params() routine returns, the stack area will be
231 * set up (start.S):
232 *
233 * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ..... TOP
234 *
235 * initialize_executive_early() [called from boot_card()]
236 * will initialize the workspace:
237 *
238 * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ...... | workspace | TOP
239 *
240 * and later calls our pretasking_hook() which ends up initializing
241 * libc which in turn initializes the heap
242 *
243 * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | heap | workspace | TOP
244 *
245 * The idea here is to first move the commandline to the future 'heap' area
246 * from where it will be picked up by our pretasking_hook().
247 * pretasking_hook() then moves it either to INIT_STACK or the workspace
248 * area using proper allocation, initializes libc and finally moves
249 * the data to the environment / malloced areas...
250 */
251
252/* this routine is called early at shared/start/start.S
253 * and must be safe with a not properly aligned stack
254 */
255void
256save_boot_params(void *r3, void *r4, void* r5, char *cmdline_start, char *cmdline_end)
257{
258int             i=cmdline_end-cmdline_start;
259CmdLine future_heap=(CmdLine)heapStart();
260
261        /* get the string out of the stack area into the future heap region;
262         * assume there's enough memory...
263         */
264        memmove(future_heap->buf,cmdline_start,i);
265        /* make sure there's an end of string marker */
266        future_heap->buf[i++]=0;
267        future_heap->size=i;
268}
269
270
271/* Configure and enable the L3CR */
272void config_enable_L3CR(unsigned l3cr)
273{
274        unsigned x;
275
276        /* By The Book (numbered steps from section 3.7.3.1 of MPC7450UM) */                           
277        /*
278         * 1: Set all L3CR bits for final config except L3E, L3I, L3PE, and
279         *    L3CLKEN.  (also mask off reserved bits in case they were included
280         *    in L3CR_CONFIG)
281         */
282        l3cr &= ~(L3CR_L3E|L3CR_L3I|L3CR_LOCK_745x|L3CR_L3PE|L3CR_L3CLKEN|L3CR_RESERVED);
283        mtspr(L3CR, l3cr);
284
285        /* 2: Set L3CR[5] (otherwise reserved bit) to 1 */
286        l3cr |= 0x04000000;
287        mtspr(L3CR, l3cr);
288
289        /* 3: Set L3CLKEN to 1*/
290        l3cr |= L3CR_L3CLKEN;
291        mtspr(L3CR, l3cr);
292
293        /* 4/5: Perform a global cache invalidate (ref section 3.7.3.6) */
294        __asm __volatile("dssall;sync");
295        /* L3 cache is already disabled, no need to clear L3E */
296        mtspr(L3CR, l3cr|L3CR_L3I);
297
298        do {
299               x = mfspr(L3CR);
300        } while (x & L3CR_L3I);
301       
302        /* 6: Clear L3CLKEN to 0 */
303        l3cr &= ~L3CR_L3CLKEN;
304        mtspr(L3CR, l3cr);
305
306        /* 7: Perform a 'sync' and wait at least 100 CPU cycles */
307        __asm __volatile("sync");
308        rtems_bsp_delay_in_bus_cycles(100);
309
310        /* 8: Set L3E and L3CLKEN */
311        l3cr |= (L3CR_L3E|L3CR_L3CLKEN);
312        mtspr(L3CR, l3cr);
313
314        /* 9: Perform a 'sync' and wait at least 100 CPU cycles */
315        __asm __volatile("sync");
316
317        rtems_bsp_delay_in_bus_cycles(100);
318}
319
320/*
321 *  bsp_start
322 *
323 *  This routine does the bulk of the system initialization.
324 */
325
326void bsp_start( void )
327{
328  int i;
329  unsigned char *stack;
330  unsigned long  *r1sp;
331  unsigned l1cr, l2cr, l3cr;
332  register unsigned char* intrStack;
333  register unsigned int intrNestingLevel = 0;
334  unsigned char *work_space_start;
335  ppc_cpu_id_t myCpu;
336  ppc_cpu_revision_t myCpuRevision;
337  Triv121PgTbl  pt=0;
338  /*
339   * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
340   * store the result in global variables so that it can be used latter...
341   */
342  myCpu         = get_ppc_cpu_type();
343  myCpuRevision = get_ppc_cpu_revision();
344
345  /*
346   * enables L1 Cache. Note that the L1_caches_enables() codes checks for
347   * relevant CPU type so that the reason why there is no use of myCpu...
348   *
349   * MOTLoad default is good. Otherwise, one would have to disable L2, L3
350   * first before settting L1.  Then L1->L2->L3.
351   *
352   L1_caches_enables();*/
353 
354#ifdef SHOW_LCR1_REGISTER
355  l1cr = get_L1CR();
356  printk("Initial L1CR value = %x\n", l1cr);
357#endif
358
359  /*
360   * the initial stack  has aready been set to this value in start.S
361   * so there is no need to set it in r1 again... It is just for info
362   * so that it can be printed without accessing R1.
363   */
364  stack = ((unsigned char*) __rtems_end) + INIT_STACK_SIZE - CPU_MINIMUM_STACK_FRAME_SIZE;
365
366 /* tag the bottom (T. Straumann 6/36/2001 <strauman@slac.stanford.edu>) */
367  *((unsigned32 *)stack) = 0;
368
369  /* fill stack with pattern for debugging */
370  __asm__ __volatile__("mr %0, %%r1":"=r"(r1sp));
371  while (--r1sp >= (unsigned long*)__rtems_end)
372          *r1sp=0xeeeeeeee;
373
374  /*
375   * Initialize the interrupt related settings
376   * SPRG0 = interrupt nesting level count
377   * SPRG1 = software managed IRQ stack
378   *
379   * This could be done latter (e.g in IRQ_INIT) but it helps to understand
380   * some settings below...
381   */
382  intrStack = ((unsigned char*) __rtems_end) + INIT_STACK_SIZE + INTR_STACK_SIZE - CPU_MINIMUM_STACK_FRAME_SIZE;
383
384  /* make sure it's properly aligned */
385  (unsigned32)intrStack &= ~(CPU_STACK_ALIGNMENT-1);
386
387  /* tag the bottom (T. Straumann 6/36/2001 <strauman@slac.stanford.edu>) */
388  *((unsigned32 *)intrStack) = 0;
389
390  _write_SPRG1((unsigned int)intrStack);
391  _write_SPRG0(PPC_BSP_HAS_FIXED_PR288);
392
393  /*
394   * Initialize default raw exception hanlders. See vectors/vectors_init.c
395   */
396  initialize_exceptions();
397  /*
398   * Init MMU block address translation to enable hardware
399   * access
400   * More PCI1 memory mapping to be done after BSP_pgtbl_activate.
401   */
402  /*
403   * PCI 0 domain memory space, want to leave room for the VME window
404   */
405  setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE);
406
407  /* map the PCI 0, 1 Domain I/O space, GT64260B registers
408   * and the reserved area so that the size is the power of 2.
409   */
410  setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x2000000, IO_PAGE);
411
412  printk("-----------------------------------------\n");
413  printk("Welcome to %s on MVME5500-0163\n", _RTEMS_version );
414  printk("Build Date: %s\n",BSP_build_date);
415  printk("-----------------------------------------\n");
416
417#ifdef TEST_RETURN_TO_PPCBUG 
418  printk("Hit <Enter> to return to PPCBUG monitor\n");
419  printk("When Finished hit GO. It should print <Back from monitor>\n");
420  debug_getc();
421  _return_to_ppcbug();
422  printk("Back from monitor\n");
423  _return_to_ppcbug();
424#endif /* TEST_RETURN_TO_PPCBUG  */
425
426#ifdef TEST_RAW_EXCEPTION_CODE 
427  printk("Testing exception handling Part 1\n");
428  /*
429   * Cause a software exception
430   */
431  __asm__ __volatile ("sc");
432  /*
433   * Check we can still catch exceptions and returned coorectly.
434   */
435  printk("Testing exception handling Part 2\n");
436  __asm__ __volatile ("sc");
437#endif 
438
439  BSP_mem_size                          =  _512M;
440  /* TODO: calculate the BSP_bus_frequency using the REF_CLK bit of System Status  register */
441  /* rtems_bsp_delay_in_bus_cycles are defined in registers.h */
442  BSP_bus_frequency                     = 133333333;
443  BSP_processor_frequency               = 1000000000;
444  BSP_time_base_divisor                 = 4000;/* P94 : 7455 clocks the TB/DECR at 1/4 of the system bus clock frequency */
445
446
447  /* Maybe not setup yet becuase of the warning message */
448  /* Allocate and set up the page table mappings
449   * This is only available on >604 CPUs.
450   *
451   * NOTE: This setup routine may modify the available memory
452   *       size. It is essential to call it before
453   *       calculating the workspace etc.
454   */
455  pt = BSP_pgtbl_setup(&BSP_mem_size);
456  if (!pt)
457     printk("WARNING: unable to setup page tables.\n");
458
459  printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size);
460
461  /*
462   * Set up our hooks
463   * Make sure libc_init is done before drivers initialized so that
464   * they can use atexit()
465   */
466
467  Cpu_table.pretasking_hook      = bsp_pretasking_hook;    /* init libc, etc. */
468  Cpu_table.postdriver_hook      = bsp_postdriver_hook;
469  Cpu_table.do_zero_of_workspace = TRUE;
470  Cpu_table.interrupt_stack_size = CONFIGURE_INTERRUPT_STACK_MEMORY;
471  /* P94 : 7455 TB/DECR is clocked by the system bus clock frequency */
472  Cpu_table.clicks_per_usec      = BSP_bus_frequency/(BSP_time_base_divisor * 1000);
473  Cpu_table.exceptions_in_RAM    = TRUE;
474  _CPU_Table                     = Cpu_table;/* <skf> for rtems_bsp_delay() */
475
476  printk("BSP_Configuration.work_space_size = %x\n", BSP_Configuration.work_space_size);
477  work_space_start =
478    (unsigned char *)BSP_mem_size - BSP_Configuration.work_space_size;
479
480  if ( work_space_start <= ((unsigned char *)__rtems_end) + INIT_STACK_SIZE + INTR_STACK_SIZE) {
481    printk( "bspstart: Not enough RAM!!!\n" );
482    bsp_cleanup();
483  }
484
485  BSP_Configuration.work_space_start = work_space_start;
486
487  /*
488   * Initalize RTEMS IRQ system
489   */
490   BSP_rtems_irq_mng_init(0);
491
492  /*
493   * Enable L2 Cache. Note that the set_L2CR(L2CR) codes checks for
494   * relevant CPU type (mpc750)...
495   *
496   * It also takes care of flushing the cache under certain conditions:
497   *   current    going to (E==enable, I==invalidate)
498   *     E           E | I      -> __NOT_FLUSHED_, invalidated, stays E
499   *     E               I      -> flush & disable, invalidate
500   *     E           E          -> nothing, stays E
501   *     0           E | I      -> not flushed, invalidated, enabled
502   *     0             | I      -> not flushed, invalidated, stays off
503   *     0           E      -> not flushed, _NO_INVALIDATE, enabled
504   *
505   * The first and the last combinations are potentially dangerous!
506   *
507   * NOTE: we assume the essential cache parameters (speed, size etc.)
508   *       have been set correctly by the firmware!
509   *
510   */
511#ifdef SHOW_LCR2_REGISTER
512  l2cr = get_L2CR();
513  printk("Initial L2CR value = %x\n", l2cr);
514#endif 
515#if 0
516  /* Again, MOTload setup seems to be fine. Otherwise, one would
517   * have to disable the L3 cahce, then R2 ->R3
518   */
519  if ( -1 != (int)l2cr ) {
520        /* -1 would mean that this machine doesn't support L2 */
521
522        l2cr &= ~( L2CR_LOCK_745x); /* clear 'data only' and 'instruction only' */
523        l2cr |= L2CR_L3OH0;    /* L3 output hold 0 should be set */
524        if ( ! (l2cr & L2CR_L2E) ) {
525            /* we are going to enable the L2 - hence we
526             * MUST invalidate it first; however, if
527             * it was enabled already, we MUST NOT
528             * invalidate it!!
529             */
530             l2cr |= L2CR_L2E | L2CR_L2I;
531             l2cr=set_L2CR(l2cr);
532        }
533        l2cr=set_L2CR(l2cr);
534  }
535#endif
536
537#ifdef SHOW_LCR3_REGISTER
538  /* L3CR needs DEC int. handler installed for bsp_delay()*/
539  l3cr = get_L3CR();
540  printk("Initial L3CR value = %x\n", l3cr);
541#endif 
542
543#if 0
544  /* Again, use the MOTLoad default for L3CR again */
545  if ( -1 != (int)l3cr ) {
546        /* -1 would mean that this machine doesn't support L3 */
547        /* BSD : %2 , SDRAM late wirte
548           l3cr |= L3SIZ_2M|L3CLK_20|L3RT_PIPELINE_LATE; */
549        /* MOTLOad :0xDF826000-> %5, 4 clocks sample point,3 p-clocks SP */
550        l3cr |= L3CR_L3PE| L3SIZ_2M|L3CLK_50|L3CKSP_4|L3PSP_3;
551
552        /* TOCHECK MOTload had L2 cache enabled, try to set nothing first */
553        if ( !(l3cr & L3CR_L3E)) {
554           l3cr |= L3CR_L3E | L3CR_L3I;
555           config_enable_L3CR(l3cr);
556        }
557  }
558#endif
559
560  /* Activate the page table mappings only after
561   * initializing interrupts because the irq_mng_init()
562   * routine needs to modify the text
563   */           
564  if (pt) {
565#ifdef SHOW_MORE_INIT_SETTINGS
566    printk("Page table setup finished; will activate it NOW...\n");
567#endif
568    BSP_pgtbl_activate(pt);
569  }
570
571  /*
572   * PCI 1 domain memory space
573   */
574  setdbat(1, PCI1_MEM_BASE, PCI1_MEM_BASE, 0x10000000, IO_PAGE);
575 
576
577#ifdef SHOW_MORE_INIT_SETTINGS
578  printk("Going to start PCI buses scanning and initialization\n");
579#endif 
580  InitializePCI();
581#ifdef SHOW_MORE_INIT_SETTINGS
582  printk("Number of PCI buses found is : %d\n", BusCountPCI());
583#endif
584
585  /* Install our own exception handler (needs PCI) */
586  globalExceptHdl = BSP_exceptionHandler;
587
588  /* clear hostbridge errors. MCP signal is not used on the MVME5500
589   * PCI config space scanning code will trip otherwise :-(
590   */
591  _BSP_clear_hostbridge_errors(0, 1 /*quiet*/);
592
593  /*
594   * Initialize VME bridge - needs working PCI
595   * and IRQ subsystems...
596   */
597#ifdef SHOW_MORE_INIT_SETTINGS
598  printk("Going to initialize VME bridge\n");
599#endif
600  /* VME initialization is in a separate file so apps which don't use
601   * VME or want a different configuration may link against a customized
602   * routine.
603   */
604  BSP_vme_config();
605
606  /* Read Configuration Vital Product Data (VPD) */
607  if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150))
608     printk("I2Cread_eeprom() error \n");
609  else {
610#ifdef CONF_VPD
611    printk("\n");
612    for (i=0; i<150; i++) {
613      printk("%2x ", ConfVPD_buff[i]); 
614      if ((i % 20)==0 ) printk("\n");
615    }
616    printk("\n");
617#endif
618  }
619
620#ifdef SHOW_MORE_INIT_SETTINGS
621  printk("MSR %x \n", _read_MSR());
622  printk("Exit from bspstart\n");
623#endif
624
625}
Note: See TracBrowser for help on using the repository browser.