Back to home page

LXR

 
 

    


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

0001 /*
0002  *  This routine does the bulk of the system initialisation.
0003  */
0004 
0005 /*
0006  * Copyright (c) 2005 Eric Norum <eric@norum.ca>
0007  *
0008  * COPYRIGHT (c) 2005.
0009  * On-Line Applications Research Corporation (OAR).
0010  *
0011  * The license and distribution terms for this file may be
0012  * found in the file LICENSE in this distribution or at
0013  * http://www.rtems.org/license/LICENSE.
0014  */
0015 
0016 #include <bsp.h>
0017 #include <bsp/bootcard.h>
0018 #include <rtems/error.h>
0019 #include <errno.h>
0020 #include <stdio.h>
0021 #include <inttypes.h>
0022 #include <mcf5282/mcf5282.h>
0023 
0024 /*
0025  * Location of 'VME' access
0026  */
0027 #define VME_ONE_BASE    0x30000000
0028 #define VME_TWO_BASE    0x31000000
0029 
0030 /*
0031  * Linker Script Defined Variables
0032  */
0033 extern char RamSize[];
0034 extern char RamBase[];
0035 extern char _CPUClockSpeed[];
0036 extern char _PLLRefClockSpeed[];
0037 
0038 uint32_t BSP_sys_clk_speed = (uint32_t)_CPUClockSpeed;
0039 uint32_t BSP_pll_ref_clock = (uint32_t)_PLLRefClockSpeed;
0040 
0041 /*
0042  * CPU-space access
0043  * The NOP after writing the CACR is there to address the following issue as
0044  * described in "Device Errata MCF5282DE", Rev. 1.7, 09/2004:
0045  *
0046  * 6 Possible Cache Corruption after Setting  CACR[CINV]
0047  * 6.1 Description
0048  * The cache on the MCF5282 was enhanced to function as a unified data and
0049  * instruction cache, an instruction cache, or an operand cache.  The cache
0050  * function and organization is controlled by the cache control register (CACR).
0051  * The CINV (Bit 24 = cache invalidate) bit in the CACR causes a cache clear.
0052  * If the cache is configured as a unified cache and the CINV bit is set, the
0053  * scope of the cache clear is controlled by two other bits in the CACR,
0054  * INVI (BIT 21 = CINV instruction cache only) and INVD (BIT 20 = CINV data
0055  * cache only).  These bits allow the entire cache, just the instruction
0056  * portion of the cache, or just the data portion of the cache to be cleared.
0057  * If a write to the CACR is performed to clear the cache (CINV = BIT 24 set)
0058  * and only a partial clear will be done (INVI = BIT 21 or INVD = BIT 20 set),
0059  * then cache corruption may  occur.
0060  *
0061  * 6.2 Workaround
0062  * All loads of the CACR that perform a cache clear operation (CINV = BIT 24)
0063  * should be followed immediately by a NOP instruction.  This avoids the cache
0064  * corruption problem.
0065  * DATECODES AFFECTED: All
0066  *
0067  *
0068  * Buffered writes must be disabled as described in "MCF5282 Chip Errata",
0069  * MCF5282DE, Rev. 6, 5/2009:
0070  *   SECF124: Buffered Write May Be Executed Twice
0071  *   Errata type: Silicon
0072  *   Affected component: Cache
0073  *   Description: If buffered writes are enabled using the CACR or ACR
0074  *                registers, the imprecise write transaction generated
0075  *                by a buffered write may be executed twice.
0076  *   Workaround: Do not enable buffered writes in the CACR or ACR registers:
0077  *               CACR[8] = DBWE (default buffered write enable) must be 0
0078  *               ACRn[5] = BUFW (buffered write enable) must be 0
0079  *   Fix plan: Currently, there are no plans to fix this.
0080  */
0081 #define m68k_set_cacr_nop(_cacr) \
0082   __asm__ volatile ("movec %0,%%cacr\n\tnop" : : "d" (_cacr))
0083 #define m68k_set_cacr(_cacr) \
0084   __asm__ volatile ("movec %0,%%cacr" : : "d" (_cacr))
0085 #define m68k_set_acr0(_acr0) \
0086   __asm__ volatile ("movec %0,%%acr0" : : "d" (_acr0))
0087 #define m68k_set_acr1(_acr1) \
0088   __asm__ volatile ("movec %0,%%acr1" : : "d" (_acr1))
0089 
0090 uint32_t mcf5282_acr0_mode = 0;
0091 uint32_t mcf5282_acr1_mode = 0;
0092 
0093 extern void bsp_fake_syscall(int);
0094 
0095 /*
0096  * The Arcturus boot ROM prints exception information improperly
0097  * so use this default exception handler instead.  This one also
0098  * prints a call backtrace
0099  */
0100 static void handler(int pc)
0101 {
0102     int level;
0103     static volatile int reent;
0104 
0105     rtems_interrupt_disable(level);
0106     if (reent++) bsp_sysReset(0);
0107     {
0108     int *p = &pc;
0109     int info = p[-1];
0110     int pc = p[0];
0111     int format = (info >> 28) & 0xF;
0112     int faultStatus = ((info >> 24) & 0xC) | ((info >> 16) & 0x3);
0113     int vector = (info >> 18) & 0xFF;
0114     int statusRegister = info & 0xFFFF;
0115     int *fp;
0116 
0117     printk("\n\nPC:%x  SR:%x  VEC:%x  FORMAT:%x  STATUS:%x\n", pc,
0118                                                                statusRegister,
0119                                                                vector,
0120                                                                format,
0121                                                                faultStatus);
0122     fp = &p[-2];
0123     for(;;) {
0124         int *nfp = (int *)*fp;
0125         if ((nfp <= fp)
0126          || ((char *)nfp >= RamSize)
0127          || ((char *)(nfp[1]) >= RamSize))
0128             break;
0129         printk("FP:%p -> %p    PC:%x\n", fp, nfp, nfp[1]);
0130         fp = nfp;
0131     }
0132     }
0133     rtems_task_suspend(0);
0134     rtems_panic("done");
0135 }
0136 
0137 void bsp_start( void )
0138 {
0139   int   i;
0140   const char *clk_speed_str;
0141   uint32_t clk_speed, mfd, rfd;
0142   uint8_t  byte;
0143 
0144   /*
0145    * Make sure UART TX is running - necessary for
0146    * early printk to work. The firmware monitor
0147    * usually enables this anyways but qemu doesn't!
0148    */
0149   MCF5282_UART_UCR(CONSOLE_PORT) = MCF5282_UART_UCR_TX_ENABLED;
0150 
0151   /*
0152    * Set up default exception handler
0153    */
0154   for (i = 2 ; i < 256 ; i++)
0155       if (i != (32+2)) /* Catch all but bootrom system calls */
0156           *((void (**)(int))(i * 4)) = handler;
0157 
0158   /*
0159    * Invalidate the cache and disable it
0160    */
0161   m68k_set_acr0(mcf5282_acr0_mode);
0162   m68k_set_acr1(mcf5282_acr1_mode);
0163   m68k_set_cacr_nop(MCF5XXX_CACR_CINV);
0164 
0165   /*
0166    * Cache SDRAM
0167    * Enable buffered writes
0168    * As Device Errata SECF124 notes this may cause double writes,
0169    * but that's not really a big problem and benchmarking tests have
0170    * shown that buffered writes do gain some performance.
0171    */
0172   mcf5282_acr0_mode = MCF5XXX_ACR_AB((uint32_t)RamBase)     |
0173                       MCF5XXX_ACR_AM((uint32_t)RamSize-1)   |
0174                       MCF5XXX_ACR_EN                        |
0175                       MCF5XXX_ACR_SM_IGNORE                 |
0176                       MCF5XXX_ACR_BWE;
0177   m68k_set_acr0(mcf5282_acr0_mode);
0178 
0179   /*
0180    * Qemu has no trap handler; install our fake syscall
0181    * implementation if there is no existing handler.
0182    */
0183   if ( 0 == *((void (**)(int))((32+2) * 4)) )
0184     *((void (**)(int))((32+2) * 4)) = bsp_fake_syscall;
0185 
0186   /*
0187    * Read/write copy of cache registers
0188    *   Split instruction/data or instruction-only
0189    *   Allow CPUSHL to invalidate a cache line
0190    *   Disable buffered writes
0191    *   No burst transfers on non-cacheable accesses
0192    *   Default cache mode is *disabled* (cache only ACRx areas)
0193    */
0194   mcf5xxx_initialize_cacr(
0195      MCF5XXX_CACR_CENB |
0196      #ifndef RTEMS_MCF5282_BSP_ENABLE_DATA_CACHE
0197        MCF5XXX_CACR_DISD |
0198      #endif
0199      MCF5XXX_CACR_DCM
0200   );
0201 
0202   /*
0203    * Set up CS* space (fake 'VME')
0204    *   Two A24/D16 spaces, supervisor data acces
0205    */
0206   MCF5282_CS1_CSAR = MCF5282_CS_CSAR_BA(VME_ONE_BASE);
0207   MCF5282_CS1_CSMR = MCF5282_CS_CSMR_BAM_16M |
0208                      MCF5282_CS_CSMR_CI |
0209                      MCF5282_CS_CSMR_SC |
0210                      MCF5282_CS_CSMR_UC |
0211                      MCF5282_CS_CSMR_UD |
0212                      MCF5282_CS_CSMR_V;
0213   MCF5282_CS1_CSCR = MCF5282_CS_CSCR_PS_16;
0214   MCF5282_CS2_CSAR = MCF5282_CS_CSAR_BA(VME_TWO_BASE);
0215   MCF5282_CS2_CSMR = MCF5282_CS_CSMR_BAM_16M |
0216                      MCF5282_CS_CSMR_CI |
0217                      MCF5282_CS_CSMR_SC |
0218                      MCF5282_CS_CSMR_UC |
0219                      MCF5282_CS_CSMR_UD |
0220                      MCF5282_CS_CSMR_V;
0221   MCF5282_CS2_CSCR = MCF5282_CS_CSCR_PS_16;
0222   MCF5282_GPIO_PJPAR |= 0x06;
0223 
0224   /*
0225    * Hopefully, the UART clock is still correctly set up
0226    * so they can see the printk() output...
0227    */
0228   clk_speed = 0;
0229   printk("Trying to figure out the system clock\n");
0230   printk("Checking ENV variable SYS_CLOCK_SPEED:\n");
0231   if ( (clk_speed_str = bsp_getbenv("SYS_CLOCK_SPEED")) ) {
0232     printk("Found: %s\n", clk_speed_str);
0233     for ( clk_speed = 0, i=0;
0234           clk_speed_str[i] >= '0' && clk_speed_str[i] <= '9';
0235           i++ ) {
0236         clk_speed = 10*clk_speed + clk_speed_str[i] - '0';
0237     }
0238     if ( 0 != clk_speed_str[i] ) {
0239         printk("Not a decimal number; I'm not using this setting\n");
0240         clk_speed = 0;
0241     }
0242   } else {
0243     printk("Not set.\n");
0244   }
0245 
0246   if ( 0 == clk_speed )
0247     clk_speed = BSP_sys_clk_speed;
0248 
0249   if ( 0 == clk_speed ) {
0250     printk("Using some heuristics to determine clock speed...\n");
0251     byte = MCF5282_CLOCK_SYNSR;
0252     if ( 0 == byte ) {
0253         printk("SYNSR == 0; assuming QEMU at 66MHz\n");
0254         BSP_pll_ref_clock = 8250000;
0255         mfd = ( 0 << 8 ) | ( 2 << 12 );
0256     } else {
0257         if ( 0xf8 != byte ) {
0258             printk("FATAL ERROR: Unexpected SYNSR contents (0x%02x), can't proceed\n", byte);
0259             bsp_sysReset(0);
0260         }
0261         mfd = MCF5282_CLOCK_SYNCR;
0262     }
0263     printk("Assuming %" PRIu32 "Hz PLL ref. clock\n", BSP_pll_ref_clock);
0264     rfd = (mfd >>  8) & 7;
0265     mfd = (mfd >> 12) & 7;
0266     /* Check against 'known' cases */
0267     if ( 0 != rfd || (2 != mfd && 3 != mfd) ) {
0268       printk("WARNING: Pll divisor/multiplier has unknown value; \n");
0269       printk("         either your board is not 64MHz or 80Mhz or\n");
0270       printk("         it uses a PLL reference other than 8MHz.\n");
0271       printk("         I'll proceed anyways but you might have to\n");
0272       printk("         reset the board and set uCbootloader ENV\n");
0273       printk("         variable \"SYS_CLOCK_SPEED\".\n");
0274     }
0275     mfd = 2 * (mfd + 2);
0276     /* sysclk = pll_ref * 2 * (MFD + 2) / 2^(rfd) */
0277     printk(
0278           "PLL multiplier: %" PRIu32", output divisor: %" PRIu32 "\n",
0279           mfd,
0280           rfd
0281         );
0282     clk_speed = (BSP_pll_ref_clock * mfd) >> rfd;
0283   }
0284 
0285   if ( 0 == clk_speed ) {
0286     printk("FATAL ERROR: Unable to determine system clock speed\n");
0287     bsp_sysReset(0);
0288   } else {
0289     BSP_sys_clk_speed = clk_speed;
0290     printk(
0291           "System clock speed: %" PRIu32 "Hz\n", bsp_get_CPU_clock_speed());
0292   }
0293 }
0294 
0295 uint32_t bsp_get_CPU_clock_speed(void)
0296 {
0297   return( BSP_sys_clk_speed );
0298 }
0299 
0300 /*
0301  * Interrupt controller allocation
0302  */
0303 rtems_status_code
0304 bsp_allocate_interrupt(int level, int priority)
0305 {
0306   static char used[7];
0307   rtems_interrupt_level l;
0308   rtems_status_code ret = RTEMS_RESOURCE_IN_USE;
0309 
0310   if ((level < 1) || (level > 7) || (priority < 0) || (priority > 7))
0311     return RTEMS_INVALID_NUMBER;
0312   rtems_interrupt_disable(l);
0313   if ((used[level-1] & (1 << priority)) == 0) {
0314     used[level-1] |= (1 << priority);
0315     ret = RTEMS_SUCCESSFUL;
0316   }
0317   rtems_interrupt_enable(l);
0318   return ret;
0319 }
0320 
0321 /*
0322  * Arcturus bootloader system calls
0323  */
0324 #define syscall_return(type, ret)                      \
0325 do {                                                   \
0326    if ((unsigned long)(ret) >= (unsigned long)(-64)) { \
0327       errno = -(ret);                                  \
0328       ret = -1;                                        \
0329    }                                                   \
0330    return (type)(ret);                                 \
0331 } while (0)
0332 
0333 #define syscall_1(type,name,d1type,d1)                      \
0334 type bsp_##name(d1type d1);                                 \
0335 type bsp_##name(d1type d1)                                  \
0336 {                                                           \
0337    long ret;                                                \
0338    register long __d1 __asm__ ("%d1") = (long)d1;           \
0339    __asm__ __volatile__ ("move.l %1,%%d0\n\t"               \
0340                          "trap #2\n\t"                      \
0341                          "move.l %%d0,%0"                   \
0342                          : "=g" (ret)                       \
0343                          : "i" (SysCode_##name), "d" (__d1) \
0344                          : "d0" );                          \
0345    syscall_return(type,ret);                                \
0346 }
0347 
0348 #define syscall_2(type,name,d1type,d1,d2type,d2)            \
0349 type bsp_##name(d1type d1, d2type d2);                      \
0350 type bsp_##name(d1type d1, d2type d2)                       \
0351 {                                                           \
0352    long ret;                                                \
0353    register long __d1 __asm__ ("%d1") = (long)d1;           \
0354    register long __d2 __asm__ ("%d2") = (long)d2;           \
0355    __asm__ __volatile__ ("move.l %1,%%d0\n\t"               \
0356                          "trap #2\n\t"                      \
0357                          "move.l %%d0,%0"                   \
0358                          : "=g" (ret)                       \
0359                          : "i" (SysCode_##name), "d" (__d1),\
0360                                                  "d" (__d2) \
0361                          : "d0" );                          \
0362    syscall_return(type,ret);                                \
0363 }
0364 
0365 #define syscall_3(type,name,d1type,d1,d2type,d2,d3type,d3)  \
0366 type bsp_##name(d1type d1, d2type d2, d3type d3);           \
0367 type bsp_##name(d1type d1, d2type d2, d3type d3)            \
0368 {                                                           \
0369    long ret;                                                \
0370    register long __d1 __asm__ ("%d1") = (long)d1;           \
0371    register long __d2 __asm__ ("%d2") = (long)d2;           \
0372    register long __d3 __asm__ ("%d3") = (long)d3;           \
0373    __asm__ __volatile__ ("move.l %1,%%d0\n\t"               \
0374                          "trap #2\n\t"                      \
0375                          "move.l %%d0,%0"                   \
0376                          : "=g" (ret)                       \
0377                          : "i" (SysCode_##name), "d" (__d1),\
0378                                                  "d" (__d2),\
0379                                                  "d" (__d3) \
0380                          : "d0" );                          \
0381    syscall_return(type,ret);                                \
0382 }
0383 
0384 #define SysCode_sysReset           0 /* system reset */
0385 #define SysCode_program            5 /* program flash memory */
0386 #define SysCode_gethwaddr         12 /* get hardware address */
0387 #define SysCode_getbenv           14 /* get bootloader environment variable */
0388 #define SysCode_setbenv           15 /* set bootloader environment variable */
0389 #define SysCode_flash_erase_range 19 /* erase a section of flash */
0390 #define SysCode_flash_write_range 20 /* write a section of flash */
0391 syscall_1(int, sysReset, int, flags)
0392 syscall_1(unsigned const char *, gethwaddr, int, a)
0393 syscall_1(const char *, getbenv, const char *, a)
0394 syscall_1(int, setbenv, const char *, a)
0395 syscall_2(int, program, bsp_mnode_t *, chain, int, flags)
0396 syscall_3(int, flash_erase_range, volatile unsigned short *, flashptr, int, start, int, end);
0397 syscall_3(int, flash_write_range, volatile unsigned short *, flashptr, bsp_mnode_t *, chain, int, offset);
0398 
0399 /* Provide a dummy-implementation of these syscalls
0400  * for qemu (which lacks the firmware).
0401  */
0402 
0403 #define __STR(x)    #x
0404 #define __STRSTR(x) __STR(x)
0405 #define ERRVAL      __STRSTR(EACCES)
0406 
0407 /* reset-control register */
0408 #define RCR "__IPSBAR + 0x110000"
0409 
0410 __asm__ (
0411     "bsp_fake_syscall:         \n"
0412     "   cmpl  #0,  %d0         \n" /* sysreset    */
0413     "   bne   1f               \n"
0414     "   moveb #0x80, %d0       \n"
0415     "   moveb %d0, "RCR"       \n" /* reset-controller */
0416         /* should never get here - but we'd return -EACCESS if we do */
0417     "1:                        \n"
0418     "   cmpl  #12, %d0         \n" /* gethwaddr   */
0419     "   beq   2f               \n"
0420     "   cmpl  #14, %d0         \n" /* getbenv     */
0421     "   beq   2f               \n"
0422     "   movel #-"ERRVAL", %d0  \n" /* return -EACCESS */
0423     "   rte                    \n"
0424     "2:                        \n"
0425     "   movel #0,  %d0         \n" /* return NULL */
0426     "   rte                    \n"
0427 );
0428 
0429 
0430 /*
0431  * 'Extended BSP' routines
0432  * Should move to cpukit/score/cpu/m68k/cpu.c someday.
0433  */
0434 
0435 rtems_status_code bspExtInit(void) { return RTEMS_SUCCESSFUL; }
0436 int BSP_enableVME_int_lvl(unsigned int level) { return 0; }
0437 int BSP_disableVME_int_lvl(unsigned int level) { return 0; }
0438 
0439 /*
0440  * 'VME' interrupt support
0441  * Interrupt vectors 192-255 are set aside for use by external logic which
0442  * drives IRQ1*.  The actual interrupt source is read from the external
0443  * logic at FPGA_IRQ_INFO.  The most-significant bit of the least-significant
0444  * byte read from this location is set as long as the external logic has
0445  * interrupts to be serviced.  The least-significant six bits indicate the
0446  * interrupt source within the external logic and are used to select the
0447  * specified interupt handler.
0448  */
0449 #define NVECTOR 256
0450 #define FPGA_VECTOR (64+1)  /* IRQ1* pin connected to external FPGA */
0451 #define FPGA_IRQ_INFO    *((vuint16 *)(0x31000000 + 0xfffffe))
0452 
0453 static struct handlerTab {
0454   BSP_VME_ISR_t func;
0455   void         *arg;
0456 } handlerTab[NVECTOR];
0457 
0458 BSP_VME_ISR_t
0459 BSP_getVME_isr(unsigned long vector, void **pusrArg)
0460 {
0461   if (vector >= NVECTOR)
0462     return (BSP_VME_ISR_t)NULL;
0463   if (pusrArg)
0464     *pusrArg = handlerTab[vector].arg;
0465   return handlerTab[vector].func;
0466 }
0467 
0468 static rtems_isr
0469 fpga_trampoline (rtems_vector_number v)
0470 {
0471   /*
0472    * Handle FPGA interrupts until all have been consumed
0473    */
0474   int loopcount = 0;
0475   while (((v = FPGA_IRQ_INFO) & 0x80) != 0) {
0476     v = 192 + (v & 0x3f);
0477     if (++loopcount >= 50) {
0478       rtems_interrupt_level level;
0479       rtems_interrupt_disable(level);
0480       printk(
0481         "\nTOO MANY FPGA INTERRUPTS (LAST WAS 0x%lx) -- "
0482         "DISABLING ALL FPGA INTERRUPTS.\n",
0483         v & 0x3f
0484       );
0485       MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1;
0486       rtems_interrupt_enable(level);
0487       return;
0488     }
0489     if (handlerTab[v].func)  {
0490       (*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v);
0491     }
0492     else {
0493       rtems_interrupt_level level;
0494       rtems_vector_number nv;
0495       rtems_interrupt_disable(level);
0496       printk("\nSPURIOUS FPGA INTERRUPT (0x%lx).\n", v & 0x3f);
0497       if ((((nv = FPGA_IRQ_INFO) & 0x80) != 0)
0498           && ((nv & 0x3f) == (v & 0x3f))) {
0499         printk("DISABLING ALL FPGA INTERRUPTS.\n");
0500         MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1;
0501       }
0502       rtems_interrupt_enable(level);
0503       return;
0504     }
0505   }
0506 }
0507 
0508 static rtems_isr
0509 trampoline (rtems_vector_number v)
0510 {
0511     if (handlerTab[v].func)
0512         (*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v);
0513 }
0514 
0515 static void
0516 enable_irq(unsigned source)
0517 {
0518 rtems_interrupt_level level;
0519   rtems_interrupt_disable(level);
0520   if (source >= 32)
0521     MCF5282_INTC0_IMRH &= ~(1 << (source - 32));
0522   else
0523     MCF5282_INTC0_IMRL &= ~((1 << source) |
0524         MCF5282_INTC_IMRL_MASKALL);
0525   rtems_interrupt_enable(level);
0526 }
0527 
0528 static int
0529 init_intc0_bit(unsigned long vector)
0530 {
0531 rtems_interrupt_level level;
0532 
0533     /*
0534      * Find an unused level/priority if this is an on-chip (INTC0)
0535      * source and this is the first time the source is being used.
0536      * Interrupt sources 1 through 7 are fixed level/priority
0537      */
0538 
0539     if ((vector >= 65) && (vector <= 127)) {
0540         int l, p;
0541         int source = vector - 64;
0542         static unsigned char installed[8];
0543 
0544         rtems_interrupt_disable(level);
0545         if (installed[source/8] & (1 << (source % 8))) {
0546             rtems_interrupt_enable(level);
0547             return 0;
0548         }
0549         installed[source/8] |= (1 << (source % 8));
0550         rtems_interrupt_enable(level);
0551         for (l = 1 ; l < 7 ; l++) {
0552             for (p = 0 ; p < 8 ; p++) {
0553                 if ((source < 8)
0554                  || (bsp_allocate_interrupt(l,p) == RTEMS_SUCCESSFUL)) {
0555                     if (source < 8)
0556                         MCF5282_EPORT_EPIER |= 1 << source;
0557                     else
0558                         *(&MCF5282_INTC0_ICR1 + (source - 1)) =
0559                                                        MCF5282_INTC_ICR_IL(l) |
0560                                                        MCF5282_INTC_ICR_IP(p);
0561           enable_irq(source);
0562                     return 0;
0563                 }
0564             }
0565         }
0566         return -1;
0567     }
0568   return 0;
0569 }
0570 
0571 int
0572 BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg)
0573 {
0574   rtems_isr_entry old_handler;
0575   rtems_interrupt_level level;
0576 
0577   /*
0578    * Register the handler information
0579    */
0580   if (vector >= NVECTOR)
0581     return -1;
0582   handlerTab[vector].func = handler;
0583   handlerTab[vector].arg = usrArg;
0584 
0585   /*
0586    * If this is an external FPGA ('VME') vector set up the real IRQ.
0587    */
0588   if ((vector >= 192) && (vector <= 255)) {
0589     int i;
0590     static volatile int setupDone;
0591     rtems_interrupt_disable(level);
0592     if (setupDone) {
0593       rtems_interrupt_enable(level);
0594       return 0;
0595     }
0596     setupDone = 1;
0597     rtems_interrupt_catch(fpga_trampoline, FPGA_VECTOR, &old_handler);
0598     i = init_intc0_bit(FPGA_VECTOR);
0599     rtems_interrupt_enable(level);
0600     return i;
0601   }
0602 
0603   /*
0604    * Make the connection between the interrupt and the local handler
0605    */
0606   rtems_interrupt_catch(trampoline, vector, &old_handler);
0607 
0608   return init_intc0_bit(vector);
0609 }
0610 
0611 int
0612 BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg)
0613 {
0614   if (vector >= NVECTOR)
0615     return -1;
0616   if ((handlerTab[vector].func != handler)
0617      || (handlerTab[vector].arg != usrArg))
0618     return -1;
0619   handlerTab[vector].func = (BSP_VME_ISR_t)NULL;
0620   return 0;
0621 }
0622 
0623 int
0624 BSP_vme2local_adrs(unsigned am, unsigned long vmeaddr, unsigned long *plocaladdr)
0625 {
0626   unsigned long offset;
0627 
0628   switch (am) {
0629     default:    return -1;
0630     case VME_AM_SUP_SHORT_IO: offset = 0x31FF0000; break; /* A16/D16 */
0631     case VME_AM_STD_SUP_DATA: offset = 0x30000000; break; /* A24/D16 */
0632     case VME_AM_EXT_SUP_DATA: offset = 0x31000000; break; /* A32/D32 */
0633   }
0634   *plocaladdr = vmeaddr + offset;
0635   return 0;
0636 }
0637 
0638 void
0639 bsp_reset_cause(char *buf, size_t capacity)
0640 {
0641   int bit, rsr;
0642   size_t i;
0643   const char *cp;
0644 
0645   if (buf == NULL)
0646     return;
0647   if (capacity)
0648     buf[0] = '\0';
0649   rsr = MCF5282_RESET_RSR;
0650   for (i = 0, bit = 0x80 ; bit != 0 ; bit >>= 1) {
0651     if (rsr & bit) {
0652       switch (bit) {
0653         case MCF5282_RESET_RSR_LVD:  cp = "Low voltage";        break;
0654         case MCF5282_RESET_RSR_SOFT: cp = "Software reset";     break;
0655         case MCF5282_RESET_RSR_WDR:  cp = "Watchdog reset";     break;
0656         case MCF5282_RESET_RSR_POR:  cp = "Power-on reset";     break;
0657         case MCF5282_RESET_RSR_EXT:  cp = "External reset";     break;
0658         case MCF5282_RESET_RSR_LOC:  cp = "Loss of clock";      break;
0659         case MCF5282_RESET_RSR_LOL:  cp = "Loss of lock";       break;
0660         default:                     cp = "??";                 break;
0661       }
0662       i += snprintf(buf+i, capacity-i, cp);
0663       if (i >= capacity)
0664         break;
0665       rsr &= ~bit;
0666       if (rsr == 0)
0667         break;
0668       i += snprintf(buf+i, capacity-i, ", ");
0669       if (i >= capacity)
0670         break;
0671     }
0672   }
0673 }