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

4.104.114.84.95
Last change on this file since ef9e015 was ef9e015, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/03/05 at 14:55:33

2005-11-03 Ralf Corsepius <ralf.corsepius@…>

PR 844/bsps

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