Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:57

0001 /*
0002  *  This routine does the bulk of the system initialization.
0003  */
0004 
0005 /*
0006  *  COPYRIGHT (c) 1989-2007.
0007  *  On-Line Applications Research Corporation (OAR).
0008  *
0009  *  The license and distribution terms for this file may be
0010  *  found in the file LICENSE in this distribution or at
0011  *  http://www.rtems.org/license/LICENSE.
0012  *
0013  *  Modified to support the MCP750.
0014  *  Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
0015  *
0016  *  Modified to support the Synergy VGM & Motorola PowerPC boards
0017  *  (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004, 2005
0018  *
0019  *  Modified to support the MVME5500 board.
0020  *  Also, the settings of L1, L2, and L3 caches is not necessary here.
0021  *  (C) by Brookhaven National Lab., S. Kate Feng <feng1@bnl.gov>, 2003-2009
0022  */
0023 
0024 #include <string.h>
0025 #include <stdlib.h>
0026 #include <ctype.h>
0027 
0028 #include <rtems/sysinit.h>
0029 #include <rtems/powerpc/powerpc.h>
0030 
0031 #include <libcpu/spr.h>   /* registers.h is included here */
0032 #include <bsp.h>
0033 #include <bsp/bootcard.h>
0034 #include <bsp/uart.h>
0035 #include <bsp/pci.h>
0036 #include <libcpu/bat.h>
0037 #include <libcpu/pte121.h>
0038 #include <libcpu/cpuIdent.h>
0039 #include <bsp/vectors.h>
0040 #include <bsp/VME.h>
0041 #include <bsp/bspException.h>
0042 
0043 #include <rtems/bspIo.h>
0044 #include <rtems/counter.h>
0045 
0046 /*
0047 #define SHOW_MORE_INIT_SETTINGS
0048 #define SHOW_LCR1_REGISTER
0049 #define SHOW_LCR2_REGISTER
0050 #define SHOW_LCR3_REGISTER
0051 #define CONF_VPD
0052 */
0053 
0054 extern uint32_t probeMemoryEnd(void); /* from shared/startup/probeMemoryEnd.c */
0055 
0056 BSP_output_char_function_type     BSP_output_char = BSP_output_char_via_serial;
0057 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0058 
0059 extern void _return_to_ppcbug(void);
0060 extern unsigned long __rtems_end[];
0061 extern unsigned get_L1CR(void), get_L2CR(void), get_L3CR(void);
0062 extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *);
0063 extern void BSP_pgtbl_activate(Triv121PgTbl);
0064 extern int I2Cread_eeprom(unsigned char I2cBusAddr, uint32_t devA2A1A0, uint32_t AddrBytes, unsigned char *pBuff, uint32_t numBytes);
0065 extern void BSP_vme_config(void);
0066 
0067 extern unsigned char ReadConfVPD_buff(int offset);
0068 
0069 uint32_t bsp_clicks_per_usec;
0070 
0071 typedef struct CmdLineRec_ {
0072     unsigned long  size;
0073     char           buf[0];
0074 } CmdLineRec, *CmdLine;
0075 
0076 
0077 #define mtspr(reg, val)  \
0078   __asm __volatile("mtspr %0,%1" : : "K"(reg), "r"(val))
0079 
0080 
0081 #define mfspr(reg) \
0082   ( { unsigned val; \
0083     __asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg)); \
0084     val; } )
0085 
0086 /*
0087  * Copy Additional boot param passed by boot loader
0088  */
0089 #define MAX_LOADER_ADD_PARM 80
0090 char loaderParam[MAX_LOADER_ADD_PARM];
0091 
0092 /*
0093  * Total memory using RESIDUAL DATA
0094  */
0095 unsigned int BSP_mem_size;
0096 /*
0097  * PCI Bus Frequency
0098  */
0099 unsigned int BSP_bus_frequency;
0100 /*
0101  * processor clock frequency
0102  */
0103 unsigned int BSP_processor_frequency;
0104 /*
0105  * Time base divisior (how many tick for 1 second).
0106  */
0107 unsigned int BSP_time_base_divisor;
0108 static unsigned char ConfVPD_buff[200];
0109 
0110 #define CMDLINE_BUF_SIZE  2048
0111 
0112 static char cmdline_buf[CMDLINE_BUF_SIZE];
0113 char *BSP_commandline_string = cmdline_buf;
0114 
0115 /* NOTE: we cannot simply malloc the commandline string;
0116  * save_boot_params() is called during a very early stage when
0117  * libc/malloc etc. are not yet initialized!
0118  *
0119  * Here's what we do:
0120  *
0121  * initial layout setup by the loader (preload.S):
0122  *
0123  * 0..RTEMS...__rtems_end | cmdline ....... TOP
0124  *
0125  * After the save_boot_params() routine returns, the stack area will be
0126  * set up (start.S):
0127  *
0128  * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ..... TOP
0129  *
0130  * initialize_executive_early() [called from boot_card()]
0131  * will initialize the workspace:
0132  *
0133  * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ...... | workspace | TOP
0134  *
0135  * and later calls our bsp_predriver_hook() which ends up initializing
0136  * libc which in turn initializes the heap
0137  *
0138  * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | heap | workspace | TOP
0139  *
0140  * The idea here is to first move the commandline to the future 'heap' area
0141  * from where it will be picked up by our bsp_predriver_hook().
0142  * bsp_predriver_hook() then moves it either to INIT_STACK or the workspace
0143  * area using proper allocation, initializes libc and finally moves
0144  * the data to the environment / malloced areas...
0145  */
0146 
0147 /* this routine is called early at shared/start/start.S
0148  * and must be safe with a not properly aligned stack
0149  */
0150 char *
0151 save_boot_params(
0152   void *r3,
0153   void *r4,
0154   void* r5,
0155   char *cmdline_start,
0156   char *cmdline_end
0157 )
0158 {
0159   int i=cmdline_end-cmdline_start;
0160 
0161   if ( i >= CMDLINE_BUF_SIZE )
0162     i = CMDLINE_BUF_SIZE-1;
0163   else if ( i < 0 )
0164     i = 0;
0165 
0166   memmove(cmdline_buf, cmdline_start, i);
0167   cmdline_buf[i]=0;
0168   return cmdline_buf;
0169 }
0170 
0171 uint32_t _CPU_Counter_frequency(void)
0172 {
0173   return BSP_bus_frequency / (BSP_time_base_divisor / 1000);
0174 }
0175 
0176 static void bsp_early( void )
0177 {
0178 #ifdef CONF_VPD
0179   int i;
0180 #endif
0181 #ifdef SHOW_LCR1_REGISTER
0182   unsigned l1cr;
0183 #endif
0184 #ifdef SHOW_LCR2_REGISTER
0185   unsigned l2cr;
0186 #endif
0187 #ifdef SHOW_LCR3_REGISTER
0188   unsigned l3cr;
0189 #endif
0190   Triv121PgTbl  pt=0;
0191 
0192   /* Till Straumann: 4/2005
0193    * Need to map the system registers early, so we can printk...
0194    * (otherwise we silently die)
0195    */
0196   /*
0197    * Kate Feng : PCI 0 domain memory space, want to leave room for the VME window
0198    */
0199   setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE);
0200 
0201   /* Till Straumann: 2004
0202    * map the PCI 0, 1 Domain I/O space, GT64260B registers
0203    * and the reserved area so that the size is the power of 2.
0204    * 2009 : map the entire 256 M space
0205    *
0206    */
0207   setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x10000000, IO_PAGE);
0208 
0209 
0210   /*
0211    * Get CPU identification dynamically. Note that the get_ppc_cpu_type()
0212    * function store the result in global variables so that it can be used later.
0213    */
0214   get_ppc_cpu_type();
0215   get_ppc_cpu_revision();
0216 
0217 #ifdef SHOW_LCR1_REGISTER
0218   l1cr = get_L1CR();
0219   printk("Initial L1CR value = %x\n", l1cr);
0220 #endif
0221 
0222   ppc_exc_initialize();
0223 
0224   /*
0225    * Init MMU block address translation to enable hardware
0226    * access
0227    * More PCI1 memory mapping to be done after BSP_pgtbl_activate.
0228    */
0229   printk("-----------------------------------------\n");
0230   printk("Welcome to %s on MVME5500-0163\n", rtems_get_version_string() );
0231   printk("-----------------------------------------\n");
0232 
0233   BSP_mem_size         =  probeMemoryEnd();
0234 
0235   /* TODO: calculate the BSP_bus_frequency using the REF_CLK bit
0236    *       of System Status  register
0237    */
0238   /* rtems_bsp_delay_in_bus_cycles are defined in registers.h */
0239   BSP_bus_frequency      = 133333333;
0240   BSP_processor_frequency    = 1000000000;
0241   /* P94 : 7455 clocks the TB/DECR at 1/4 of the system bus clock frequency */
0242   BSP_time_base_divisor      = 4000;
0243 
0244   /* Maybe not setup yet becuase of the warning message */
0245   /* Allocate and set up the page table mappings
0246    * This is only available on >604 CPUs.
0247    *
0248    * NOTE: This setup routine may modify the available memory
0249    *       size. It is essential to call it before
0250    *       calculating the workspace etc.
0251    */
0252   pt = BSP_pgtbl_setup(&BSP_mem_size);
0253   if (!pt)
0254      printk("WARNING: unable to setup page tables.\n");
0255 
0256   printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size);
0257 
0258   /* P94 : 7455 TB/DECR is clocked by the system bus clock frequency */
0259 
0260   bsp_clicks_per_usec    = BSP_bus_frequency/(BSP_time_base_divisor * 1000);
0261 
0262   /*
0263    * Initalize RTEMS IRQ system
0264    */
0265    BSP_rtems_irq_mng_init(0);
0266 
0267 #ifdef SHOW_LCR2_REGISTER
0268   l2cr = get_L2CR();
0269   printk("Initial L2CR value = %x\n", l2cr);
0270 #endif
0271 
0272 #ifdef SHOW_LCR3_REGISTER
0273   /* L3CR needs DEC int. handler installed for bsp_delay()*/
0274   l3cr = get_L3CR();
0275   printk("Initial L3CR value = %x\n", l3cr);
0276 #endif
0277 
0278 
0279   /* Activate the page table mappings only after
0280    * initializing interrupts because the irq_mng_init()
0281    * routine needs to modify the text
0282    */
0283   if (pt) {
0284 #ifdef SHOW_MORE_INIT_SETTINGS
0285     printk("Page table setup finished; will activate it NOW...\n");
0286 #endif
0287     BSP_pgtbl_activate(pt);
0288   }
0289   /* Read Configuration Vital Product Data (VPD) */
0290   if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150))
0291      printk("I2Cread_eeprom() error \n");
0292   else {
0293 #ifdef CONF_VPD
0294     printk("\n");
0295     for (i=0; i<150; i++) {
0296       printk("%2x ", ConfVPD_buff[i]);
0297       if ((i % 20)==0 ) printk("\n");
0298     }
0299     printk("\n");
0300 #endif
0301   }
0302 
0303   /*
0304    * PCI 1 domain memory space
0305    */
0306   setdbat(1, PCI1_MEM_BASE, PCI1_MEM_BASE, 0x10000000, IO_PAGE);
0307 
0308 
0309 #ifdef SHOW_MORE_INIT_SETTINGS
0310   printk("Going to start PCI buses scanning and initialization\n");
0311 #endif
0312   pci_initialize();
0313 #ifdef SHOW_MORE_INIT_SETTINGS
0314   printk("Number of PCI buses found is : %d\n", pci_bus_count());
0315 #endif
0316 
0317   /* Install our own exception handler (needs PCI) */
0318   globalExceptHdl = BSP_exceptionHandler;
0319 
0320   /* clear hostbridge errors. MCP signal is not used on the MVME5500
0321    * PCI config space scanning code will trip otherwise :-(
0322    */
0323   _BSP_clear_hostbridge_errors(0, 1 /*quiet*/);
0324 
0325 #ifdef SHOW_MORE_INIT_SETTINGS
0326   printk("MSR %x \n", _read_MSR());
0327   printk("Exit from bspstart\n");
0328 #endif
0329 
0330 }
0331 
0332 RTEMS_SYSINIT_ITEM(
0333   bsp_early,
0334   RTEMS_SYSINIT_BSP_EARLY,
0335   RTEMS_SYSINIT_ORDER_MIDDLE
0336 );
0337 
0338 void bsp_start( void )
0339 {
0340   /* Initialization was done by bsp_early() */
0341 }
0342 
0343 unsigned char ReadConfVPD_buff(int offset)
0344 {
0345   return(ConfVPD_buff[offset]);
0346 }
0347 
0348 RTEMS_SYSINIT_ITEM(
0349   BSP_vme_config,
0350   RTEMS_SYSINIT_BSP_PRE_DRIVERS,
0351   RTEMS_SYSINIT_ORDER_MIDDLE
0352 );