Back to home page

LXR

 
 

    


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

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 
0017 #include <string.h>
0018 
0019 #include <bsp.h>
0020 #include <bsp/bootcard.h>
0021 #include <rtems/bspIo.h>
0022 #include <rtems/counter.h>
0023 #include <rtems/sysinit.h>
0024 #include <bsp/consoleIo.h>
0025 #include <libcpu/spr.h>
0026 #include <bsp/residual.h>
0027 #include <bsp/pci.h>
0028 #include <bsp/openpic.h>
0029 #include <bsp/irq.h>
0030 #include <bsp/irq-generic.h>
0031 #include <libcpu/bat.h>
0032 #include <libcpu/pte121.h>
0033 #include <libcpu/cpuIdent.h>
0034 #include <bsp/vectors.h>
0035 #include <bsp/VME.h>
0036 #include <bsp/motorola.h>
0037 #include <rtems/powerpc/powerpc.h>
0038 
0039 extern void _return_to_ppcbug(void);
0040 extern unsigned long __rtems_end[];
0041 extern void L1_caches_enables(void);
0042 extern unsigned get_L2CR(void);
0043 extern void set_L2CR(unsigned);
0044 extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *);
0045 extern void         BSP_pgtbl_activate(Triv121PgTbl);
0046 
0047 #define PPC_MIN_BAT_SIZE (128 * 1024)
0048 static char cc_memory[PPC_MIN_BAT_SIZE] RTEMS_ALIGNED(PPC_MIN_BAT_SIZE);
0049 
0050 SPR_RW(SPRG1)
0051 
0052 #if defined(DEBUG_BATS)
0053 extern void ShowBATS(void);
0054 #endif
0055 
0056 /*
0057  *  Driver configuration parameters
0058  */
0059 uint32_t   bsp_clicks_per_usec;
0060 
0061 /*
0062  * Copy of residuals passed by firmware
0063  */
0064 RESIDUAL residualCopy;
0065 /*
0066  * Copy Additional boot param passed by boot loader
0067  */
0068 #define MAX_LOADER_ADD_PARM 80
0069 char loaderParam[MAX_LOADER_ADD_PARM];
0070 
0071 char *BSP_commandline_string = loaderParam;
0072 /*
0073  * Vital Board data Start using DATA RESIDUAL
0074  */
0075 /*
0076  * Total memory using RESIDUAL DATA
0077  */
0078 unsigned int BSP_mem_size;
0079 
0080 /*
0081  * PCI Bus Frequency
0082  */
0083 unsigned int BSP_bus_frequency;
0084 /*
0085  * processor clock frequency
0086  */
0087 unsigned int BSP_processor_frequency;
0088 /*
0089  * Time base divisior (how many tick for 1 second).
0090  */
0091 unsigned int BSP_time_base_divisor;
0092 
0093 /*
0094  *  Use the shared implementations of the following routines
0095  */
0096 
0097 char *save_boot_params(
0098   void *r3,
0099   void *r4,
0100   void *r5,
0101   char *cmdline_start,
0102   char *cmdline_end
0103 )
0104 {
0105 
0106   residualCopy = *(RESIDUAL *)r3;
0107   strncpy(loaderParam, cmdline_start, MAX_LOADER_ADD_PARM);
0108   loaderParam[MAX_LOADER_ADD_PARM - 1] ='\0';
0109   return loaderParam;
0110 }
0111 
0112 #if defined(mot_ppc_mvme2100)
0113 unsigned int EUMBBAR;
0114 
0115 /*
0116  * Return the current value of the Embedded Utilities Memory Block Base Address
0117  * Register (EUMBBAR) as read from the processor configuration register using
0118  * Processor Address Map B (CHRP).
0119  */
0120 static unsigned int get_eumbbar(void) {
0121   out_le32( (volatile uint32_t *)0xfec00000, 0x80000078 );
0122   return in_le32( (volatile uint32_t *)0xfee00000 );
0123 }
0124 #endif
0125 
0126 uint32_t _CPU_Counter_frequency(void)
0127 {
0128   return BSP_bus_frequency / (BSP_time_base_divisor / 1000);
0129 }
0130 
0131 static void bsp_early( void )
0132 {
0133 #if !defined(mot_ppc_mvme2100)
0134   unsigned l2cr;
0135 #endif
0136   prep_t boardManufacturer;
0137   motorolaBoard myBoard;
0138   Triv121PgTbl  pt=0;
0139 
0140   /*
0141    * Get CPU identification dynamically. Note that the get_ppc_cpu_type()
0142    * function store the result in global variables so that it can be used
0143    * later...
0144    */
0145   get_ppc_cpu_type();
0146   get_ppc_cpu_revision();
0147 
0148   /*
0149    * Init MMU block address translation to enable hardware access
0150    */
0151 
0152 #if !defined(mot_ppc_mvme2100)
0153   /*
0154    * PC legacy IO space used for inb/outb and all PC compatible hardware
0155    */
0156   setdbat(1, _IO_BASE, _IO_BASE, 0x10000000, IO_PAGE);
0157 #endif
0158 
0159   /*
0160    * PCI devices memory area. Needed to access OpenPIC features
0161    * provided by the Raven
0162    *
0163    * T. Straumann: give more PCI address space
0164    */
0165   setdbat(2, PCI_MEM_BASE+PCI_MEM_WIN0, PCI_MEM_BASE+PCI_MEM_WIN0, 0x10000000, IO_PAGE);
0166 
0167   /*
0168    * Must have acces to open pic PCI ACK registers provided by the RAVEN
0169    */
0170 #ifndef qemu
0171   setdbat(3, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
0172 #else
0173   setdbat(3, 0xb0000000, 0xb0000000, 0x10000000, IO_PAGE);
0174 #endif
0175 
0176 #if defined(mot_ppc_mvme2100)
0177   /* Need 0xfec00000 mapped for this */
0178   EUMBBAR = get_eumbbar();
0179 #endif
0180 
0181   /*
0182    * enables L1 Cache. Note that the L1_caches_enables() codes checks for
0183    * relevant CPU type so that the reason why there is no use of myCpu...
0184    */
0185   L1_caches_enables();
0186 
0187   select_console(CONSOLE_LOG);
0188 
0189   /*
0190    * We check that the keyboard is present and immediately
0191    * select the serial console if not.
0192    */
0193 #if defined(BSP_KBD_IOBASE)
0194   { int err;
0195     err = kbdreset();
0196     if (err) select_console(CONSOLE_SERIAL);
0197   }
0198 #else
0199   select_console(CONSOLE_SERIAL);
0200 #endif
0201 
0202 
0203 #if !defined(mot_ppc_mvme2100)
0204   /*
0205    * Enable L2 Cache. Note that the set_L2CR(L2CR) codes checks for
0206    * relevant CPU type (mpc750)...
0207    */
0208   l2cr = get_L2CR();
0209 #ifdef SHOW_LCR2_REGISTER
0210   printk("Initial L2CR value = %x\n", l2cr);
0211 #endif
0212   if ( (! (l2cr & 0x80000000)) && ((int) l2cr == -1))
0213     set_L2CR(0xb9A14000);
0214 #endif
0215 
0216   ppc_exc_initialize();
0217 
0218   boardManufacturer   =  checkPrepBoardType(&residualCopy);
0219   if (boardManufacturer != PREP_Motorola) {
0220     printk("Unsupported hardware vendor\n");
0221     while (1);
0222   }
0223   myBoard = getMotorolaBoard();
0224 
0225   printk("-----------------------------------------\n");
0226   printk("Welcome to %s on %s\n", rtems_get_version_string(),
0227                                     motorolaBoardToString(myBoard));
0228   printk("-----------------------------------------\n");
0229 #ifdef SHOW_MORE_INIT_SETTINGS
0230   printk("Residuals are located at %x\n", (unsigned) &residualCopy);
0231   printk("Additionnal boot options are %s\n", loaderParam);
0232   printk("-----------------------------------------\n");
0233 #endif
0234 
0235 #ifdef TEST_RETURN_TO_PPCBUG
0236   printk("Hit <Enter> to return to PPCBUG monitor\n");
0237   printk("When Finished hit GO. It should print <Back from monitor>\n");
0238   debug_getc();
0239   _return_to_ppcbug();
0240   printk("Back from monitor\n");
0241   _return_to_ppcbug();
0242 #endif /* TEST_RETURN_TO_PPCBUG  */
0243 
0244 #ifdef SHOW_MORE_INIT_SETTINGS
0245   printk("Going to start PCI buses scanning and initialization\n");
0246 #endif
0247 
0248   pci_initialize();
0249   {
0250     const struct _int_map *bspmap  = motorolaIntMap(currentBoard);
0251     if( bspmap ) {
0252        printk("pci : Configuring interrupt routing for '%s'\n",
0253           motorolaBoardToString(currentBoard));
0254        FixupPCI(bspmap, motorolaIntSwizzle(currentBoard));
0255     }
0256     else
0257        printk("pci : Interrupt routing not available for this bsp\n");
0258  }
0259 
0260 #ifdef SHOW_MORE_INIT_SETTINGS
0261   printk("Number of PCI buses found is : %d\n", pci_bus_count());
0262 #endif
0263 #ifdef TEST_RAW_EXCEPTION_CODE
0264   printk("Testing exception handling Part 1\n");
0265   /*
0266    * Cause a software exception
0267    */
0268   __asm__ __volatile ("sc");
0269   /*
0270    * Check we can still catch exceptions and return coorectly.
0271    */
0272   printk("Testing exception handling Part 2\n");
0273   __asm__ __volatile ("sc");
0274 
0275   /*
0276    * Somehow doing the above seems to clobber SPRG0 on the mvme2100.  The
0277    * interrupt disable mask is stored in SPRG0. Is this a problem?
0278    */
0279   ppc_interrupt_set_disable_mask( PPC_INTERRUPT_DISABLE_MASK_DEFAULT);
0280 
0281 #endif
0282 
0283 /* See above */
0284 
0285   BSP_mem_size            = residualCopy.TotalMemory;
0286   BSP_bus_frequency       = residualCopy.VitalProductData.ProcessorBusHz;
0287   BSP_processor_frequency = residualCopy.VitalProductData.ProcessorHz;
0288   BSP_time_base_divisor   = (residualCopy.VitalProductData.TimeBaseDivisor?
0289                     residualCopy.VitalProductData.TimeBaseDivisor : 4000);
0290 
0291   /* clear hostbridge errors but leave MCP disabled -
0292    * PCI config space scanning code will trip otherwise :-(
0293    */
0294   _BSP_clear_hostbridge_errors(0 /* enableMCP */, 0/*quiet*/);
0295 
0296   if (BSP_mem_size > 0x10000000)
0297   {
0298     /* Support cases of system memory size larger than 256Mb.
0299      *
0300      * We use BAT3 in order to obtain access to the top section of the RAM.
0301      * We also need to do this just before setting up the page table because
0302      * this is where the page table will be located.
0303      */
0304     const unsigned int mem256Count = (BSP_mem_size / 0x10000000);
0305     const unsigned int BAT3Addr    = ((BSP_mem_size % 0x10000000)  ?
0306                                        (mem256Count     * 0x10000000) :
0307                                       ((mem256Count-1) * 0x10000000));
0308     setdbat(3, BAT3Addr, BAT3Addr, 0x10000000, IO_PAGE);
0309 #ifdef SHOW_MORE_INIT_SETTINGS
0310     printk("Setting up BAT3 for large memory support. (BAT3 --> 0x%x)\n", BAT3Addr);
0311 #endif
0312   }
0313 
0314   /* Allocate and set up the page table mappings
0315    * This is only available on >604 CPUs.
0316    *
0317    * NOTE: This setup routine may modify the available memory
0318    *       size. It is essential to call it before
0319    *       calculating the workspace etc.
0320    */
0321   pt = BSP_pgtbl_setup(&BSP_mem_size);
0322 
0323   if (!pt || TRIV121_MAP_SUCCESS != triv121PgTblMap(
0324             pt, TRIV121_121_VSID,
0325 #ifndef qemu
0326             0xfeff0000,
0327 #else
0328             0xbffff000,
0329 #endif
0330             1,
0331             TRIV121_ATTR_IO_PAGE, TRIV121_PP_RW_PAGE)) {
0332     printk("WARNING: unable to setup page tables VME "
0333                "bridge must share PCI space\n");
0334   }
0335 
0336   /*
0337    *  initialize the device driver parameters
0338    */
0339   bsp_clicks_per_usec    = BSP_bus_frequency/(BSP_time_base_divisor * 1000);
0340 
0341   /* Initialize interrupt support */
0342   bsp_interrupt_initialize();
0343 
0344   /* Activate the page table mappings only after
0345    * initializing interrupts because the irq_mng_init()
0346    * routine needs to modify the text
0347    */
0348   if (pt) {
0349 #ifdef  SHOW_MORE_INIT_SETTINGS
0350     printk("Page table setup finished; will activate it NOW...\n");
0351 #endif
0352     BSP_pgtbl_activate(pt);
0353     /* finally, switch off DBAT3 */
0354     setdbat(3, 0, 0, 0, 0);
0355   }
0356 
0357   setdbat(3, (intptr_t) &cc_memory[0], (intptr_t) &cc_memory[0], PPC_MIN_BAT_SIZE, IO_PAGE);
0358   rtems_cache_coherent_add_area(&cc_memory[0], PPC_MIN_BAT_SIZE);
0359 
0360 #if defined(DEBUG_BATS)
0361   ShowBATS();
0362 #endif
0363 
0364 #ifdef SHOW_MORE_INIT_SETTINGS
0365   printk("Exit from bspstart\n");
0366 #endif
0367 }
0368 
0369 RTEMS_SYSINIT_ITEM(
0370   bsp_early,
0371   RTEMS_SYSINIT_BSP_EARLY,
0372   RTEMS_SYSINIT_ORDER_MIDDLE
0373 );
0374 
0375 void bsp_start( void )
0376 {
0377   /* Initialization was done by bsp_early() */
0378 }
0379 
0380 RTEMS_SYSINIT_ITEM(
0381   BSP_vme_config,
0382   RTEMS_SYSINIT_BSP_PRE_DRIVERS,
0383   RTEMS_SYSINIT_ORDER_MIDDLE
0384 );