source: rtems/bsps/m68k/uC5282/start/bspstart.c @ c9625a21

Last change on this file since c9625a21 was 9964895, checked in by Sebastian Huber <sebastian.huber@…>, on 04/20/18 at 08:35:35

bsps: Move startup files to bsps

Adjust build support files to new directory layout.

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 21.8 KB
Line 
1/*
2 *  This routine does the bulk of the system initialisation.
3 */
4
5/*
6 *  Author: W. Eric Norum <norume@aps.anl.gov>
7 *
8 *  COPYRIGHT (c) 2005.
9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.org/license/LICENSE.
14 */
15
16#include <bsp.h>
17#include <bsp/bootcard.h>
18#include <rtems/error.h>
19#include <errno.h>
20#include <stdio.h>
21#include <inttypes.h>
22#include <mcf5282/mcf5282.h>
23
24/*
25 * Location of 'VME' access
26 */
27#define VME_ONE_BASE    0x30000000
28#define VME_TWO_BASE    0x31000000
29
30/*
31 * Linker Script Defined Variables
32 */
33extern char RamSize[];
34extern char RamBase[];
35extern char _CPUClockSpeed[];
36extern char _PLLRefClockSpeed[];
37
38uint32_t BSP_sys_clk_speed = (uint32_t)_CPUClockSpeed;
39uint32_t BSP_pll_ref_clock = (uint32_t)_PLLRefClockSpeed;
40
41/*
42 * CPU-space access
43 * The NOP after writing the CACR is there to address the following issue as
44 * described in "Device Errata MCF5282DE", Rev. 1.7, 09/2004:
45 *
46 * 6 Possible Cache Corruption after Setting  CACR[CINV]
47 * 6.1 Description
48 * The cache on the MCF5282 was enhanced to function as a unified data and
49 * instruction cache, an instruction cache, or an operand cache.  The cache
50 * function and organization is controlled by the cache control register (CACR).
51 * The CINV (Bit 24 = cache invalidate) bit in the CACR causes a cache clear.
52 * If the cache is configured as a unified cache and the CINV bit is set, the
53 * scope of the cache clear is controlled by two other bits in the CACR,
54 * INVI (BIT 21 = CINV instruction cache only) and INVD (BIT 20 = CINV data
55 * cache only).  These bits allow the entire cache, just the instruction
56 * portion of the cache, or just the data portion of the cache to be cleared.
57 * If a write to the CACR is performed to clear the cache (CINV = BIT 24 set)
58 * and only a partial clear will be done (INVI = BIT 21 or INVD = BIT 20 set),
59 * then cache corruption may  occur.
60 *
61 * 6.2 Workaround
62 * All loads of the CACR that perform a cache clear operation (CINV = BIT 24)
63 * should be followed immediately by a NOP instruction.  This avoids the cache
64 * corruption problem.
65 * DATECODES AFFECTED: All
66 *
67 *
68 * Buffered writes must be disabled as described in "MCF5282 Chip Errata",
69 * MCF5282DE, Rev. 6, 5/2009:
70 *   SECF124: Buffered Write May Be Executed Twice
71 *   Errata type: Silicon
72 *   Affected component: Cache
73 *   Description: If buffered writes are enabled using the CACR or ACR
74 *                registers, the imprecise write transaction generated
75 *                by a buffered write may be executed twice.
76 *   Workaround: Do not enable buffered writes in the CACR or ACR registers:
77 *               CACR[8] = DBWE (default buffered write enable) must be 0
78 *               ACRn[5] = BUFW (buffered write enable) must be 0
79 *   Fix plan: Currently, there are no plans to fix this.
80 */
81#define m68k_set_cacr_nop(_cacr) \
82  __asm__ volatile ("movec %0,%%cacr\n\tnop" : : "d" (_cacr))
83#define m68k_set_cacr(_cacr) \
84  __asm__ volatile ("movec %0,%%cacr" : : "d" (_cacr))
85#define m68k_set_acr0(_acr0) \
86  __asm__ volatile ("movec %0,%%acr0" : : "d" (_acr0))
87#define m68k_set_acr1(_acr1) \
88  __asm__ volatile ("movec %0,%%acr1" : : "d" (_acr1))
89
90uint32_t mcf5282_acr0_mode = 0;
91uint32_t mcf5282_acr1_mode = 0;
92
93extern void bsp_fake_syscall(int);
94
95/*
96 * The Arcturus boot ROM prints exception information improperly
97 * so use this default exception handler instead.  This one also
98 * prints a call backtrace
99 */
100static void handler(int pc)
101{
102    int level;
103    static volatile int reent;
104
105    rtems_interrupt_disable(level);
106    if (reent++) bsp_sysReset(0);
107    {
108    int *p = &pc;
109    int info = p[-1];
110    int pc = p[0];
111    int format = (info >> 28) & 0xF;
112    int faultStatus = ((info >> 24) & 0xC) | ((info >> 16) & 0x3);
113    int vector = (info >> 18) & 0xFF;
114    int statusRegister = info & 0xFFFF;
115    int *fp;
116
117    printk("\n\nPC:%x  SR:%x  VEC:%x  FORMAT:%x  STATUS:%x\n", pc,
118                                                               statusRegister,
119                                                               vector,
120                                                               format,
121                                                               faultStatus);
122    fp = &p[-2];
123    for(;;) {
124        int *nfp = (int *)*fp;
125        if ((nfp <= fp)
126         || ((char *)nfp >= RamSize)
127         || ((char *)(nfp[1]) >= RamSize))
128            break;
129        printk("FP:%p -> %p    PC:%x\n", fp, nfp, nfp[1]);
130        fp = nfp;
131    }
132    }
133    rtems_task_suspend(0);
134    rtems_panic("done");
135}
136
137void bsp_start( void )
138{
139  int   i;
140  const char *clk_speed_str;
141  uint32_t clk_speed, mfd, rfd;
142  uint8_t  byte;
143
144  /*
145   * Make sure UART TX is running - necessary for
146   * early printk to work. The firmware monitor
147   * usually enables this anyways but qemu doesn't!
148   */
149  MCF5282_UART_UCR(CONSOLE_PORT) = MCF5282_UART_UCR_TX_ENABLED;
150
151  /*
152   * Set up default exception handler
153   */
154  for (i = 2 ; i < 256 ; i++)
155      if (i != (32+2)) /* Catch all but bootrom system calls */
156          *((void (**)(int))(i * 4)) = handler;
157
158  /*
159   * Invalidate the cache and disable it
160   */
161  m68k_set_acr0(mcf5282_acr0_mode);
162  m68k_set_acr1(mcf5282_acr1_mode);
163  m68k_set_cacr_nop(MCF5XXX_CACR_CINV);
164
165  /*
166   * Cache SDRAM
167   * Enable buffered writes
168   * As Device Errata SECF124 notes this may cause double writes,
169   * but that's not really a big problem and benchmarking tests have
170   * shown that buffered writes do gain some performance.
171   */
172  mcf5282_acr0_mode = MCF5XXX_ACR_AB((uint32_t)RamBase)     |
173                      MCF5XXX_ACR_AM((uint32_t)RamSize-1)   |
174                      MCF5XXX_ACR_EN                        |
175                      MCF5XXX_ACR_SM_IGNORE                 |
176                      MCF5XXX_ACR_BWE;
177  m68k_set_acr0(mcf5282_acr0_mode);
178
179  /*
180   * Qemu has no trap handler; install our fake syscall
181   * implementation if there is no existing handler.
182   */
183  if ( 0 == *((void (**)(int))((32+2) * 4)) )
184    *((void (**)(int))((32+2) * 4)) = bsp_fake_syscall;
185
186  /*
187   * Read/write copy of cache registers
188   *   Split instruction/data or instruction-only
189   *   Allow CPUSHL to invalidate a cache line
190   *   Disable buffered writes
191   *   No burst transfers on non-cacheable accesses
192   *   Default cache mode is *disabled* (cache only ACRx areas)
193   */
194  mcf5xxx_initialize_cacr(
195     MCF5XXX_CACR_CENB |
196     #ifndef RTEMS_MCF5282_BSP_ENABLE_DATA_CACHE
197       MCF5XXX_CACR_DISD |
198     #endif
199     MCF5XXX_CACR_DCM
200  );
201
202  /*
203   * Set up CS* space (fake 'VME')
204   *   Two A24/D16 spaces, supervisor data acces
205   */
206  MCF5282_CS1_CSAR = MCF5282_CS_CSAR_BA(VME_ONE_BASE);
207  MCF5282_CS1_CSMR = MCF5282_CS_CSMR_BAM_16M |
208                     MCF5282_CS_CSMR_CI |
209                     MCF5282_CS_CSMR_SC |
210                     MCF5282_CS_CSMR_UC |
211                     MCF5282_CS_CSMR_UD |
212                     MCF5282_CS_CSMR_V;
213  MCF5282_CS1_CSCR = MCF5282_CS_CSCR_PS_16;
214  MCF5282_CS2_CSAR = MCF5282_CS_CSAR_BA(VME_TWO_BASE);
215  MCF5282_CS2_CSMR = MCF5282_CS_CSMR_BAM_16M |
216                     MCF5282_CS_CSMR_CI |
217                     MCF5282_CS_CSMR_SC |
218                     MCF5282_CS_CSMR_UC |
219                     MCF5282_CS_CSMR_UD |
220                     MCF5282_CS_CSMR_V;
221  MCF5282_CS2_CSCR = MCF5282_CS_CSCR_PS_16;
222  MCF5282_GPIO_PJPAR |= 0x06;
223
224  /*
225   * Hopefully, the UART clock is still correctly set up
226   * so they can see the printk() output...
227   */
228  clk_speed = 0;
229  printk("Trying to figure out the system clock\n");
230  printk("Checking ENV variable SYS_CLOCK_SPEED:\n");
231  if ( (clk_speed_str = bsp_getbenv("SYS_CLOCK_SPEED")) ) {
232    printk("Found: %s\n", clk_speed_str);
233        for ( clk_speed = 0, i=0;
234              clk_speed_str[i] >= '0' && clk_speed_str[i] <= '9';
235              i++ ) {
236                clk_speed = 10*clk_speed + clk_speed_str[i] - '0';
237        }
238        if ( 0 != clk_speed_str[i] ) {
239                printk("Not a decimal number; I'm not using this setting\n");
240                clk_speed = 0;
241        }
242  } else {
243    printk("Not set.\n");
244  }
245
246  if ( 0 == clk_speed )
247        clk_speed = BSP_sys_clk_speed;
248
249  if ( 0 == clk_speed ) {
250        printk("Using some heuristics to determine clock speed...\n");
251        byte = MCF5282_CLOCK_SYNSR;
252        if ( 0 == byte ) {
253                printk("SYNSR == 0; assuming QEMU at 66MHz\n");
254                BSP_pll_ref_clock = 8250000;
255                mfd = ( 0 << 8 ) | ( 2 << 12 );
256        } else {
257                if ( 0xf8 != byte ) {
258                        printk("FATAL ERROR: Unexpected SYNSR contents (0x%02x), can't proceed\n", byte);
259                        bsp_sysReset(0);
260                }
261                mfd = MCF5282_CLOCK_SYNCR;
262        }
263        printk("Assuming %" PRIu32 "Hz PLL ref. clock\n", BSP_pll_ref_clock);
264        rfd = (mfd >>  8) & 7;
265        mfd = (mfd >> 12) & 7;
266        /* Check against 'known' cases */
267        if ( 0 != rfd || (2 != mfd && 3 != mfd) ) {
268          printk("WARNING: Pll divisor/multiplier has unknown value; \n");
269          printk("         either your board is not 64MHz or 80Mhz or\n");
270          printk("         it uses a PLL reference other than 8MHz.\n");
271          printk("         I'll proceed anyways but you might have to\n");
272          printk("         reset the board and set uCbootloader ENV\n");
273          printk("         variable \"SYS_CLOCK_SPEED\".\n");
274        }
275        mfd = 2 * (mfd + 2);
276        /* sysclk = pll_ref * 2 * (MFD + 2) / 2^(rfd) */
277        printk(
278          "PLL multiplier: %" PRIu32", output divisor: %" PRIu32 "\n",
279          mfd,
280          rfd
281        );
282        clk_speed = (BSP_pll_ref_clock * mfd) >> rfd;
283  }
284
285  if ( 0 == clk_speed ) {
286        printk("FATAL ERROR: Unable to determine system clock speed\n");
287        bsp_sysReset(0);
288  } else {
289        BSP_sys_clk_speed = clk_speed;
290        printk(
291          "System clock speed: %" PRIu32 "Hz\n", bsp_get_CPU_clock_speed());
292  }
293}
294
295uint32_t bsp_get_CPU_clock_speed(void)
296{
297  return( BSP_sys_clk_speed );
298}
299
300/*
301 * Interrupt controller allocation
302 */
303rtems_status_code
304bsp_allocate_interrupt(int level, int priority)
305{
306  static char used[7];
307  rtems_interrupt_level l;
308  rtems_status_code ret = RTEMS_RESOURCE_IN_USE;
309
310  if ((level < 1) || (level > 7) || (priority < 0) || (priority > 7))
311    return RTEMS_INVALID_NUMBER;
312  rtems_interrupt_disable(l);
313  if ((used[level-1] & (1 << priority)) == 0) {
314    used[level-1] |= (1 << priority);
315    ret = RTEMS_SUCCESSFUL;
316  }
317  rtems_interrupt_enable(l);
318  return ret;
319}
320
321/*
322 * Arcturus bootloader system calls
323 */
324#define syscall_return(type, ret)                      \
325do {                                                   \
326   if ((unsigned long)(ret) >= (unsigned long)(-64)) { \
327      errno = -(ret);                                  \
328      ret = -1;                                        \
329   }                                                   \
330   return (type)(ret);                                 \
331} while (0)
332
333#define syscall_1(type,name,d1type,d1)                      \
334type bsp_##name(d1type d1);                                 \
335type bsp_##name(d1type d1)                                  \
336{                                                           \
337   long ret;                                                \
338   register long __d1 __asm__ ("%d1") = (long)d1;           \
339   __asm__ __volatile__ ("move.l %1,%%d0\n\t"               \
340                         "trap #2\n\t"                      \
341                         "move.l %%d0,%0"                   \
342                         : "=g" (ret)                       \
343                         : "i" (SysCode_##name), "d" (__d1) \
344                         : "d0" );                          \
345   syscall_return(type,ret);                                \
346}
347
348#define syscall_2(type,name,d1type,d1,d2type,d2)            \
349type bsp_##name(d1type d1, d2type d2);                      \
350type bsp_##name(d1type d1, d2type d2)                       \
351{                                                           \
352   long ret;                                                \
353   register long __d1 __asm__ ("%d1") = (long)d1;           \
354   register long __d2 __asm__ ("%d2") = (long)d2;           \
355   __asm__ __volatile__ ("move.l %1,%%d0\n\t"               \
356                         "trap #2\n\t"                      \
357                         "move.l %%d0,%0"                   \
358                         : "=g" (ret)                       \
359                         : "i" (SysCode_##name), "d" (__d1),\
360                                                 "d" (__d2) \
361                         : "d0" );                          \
362   syscall_return(type,ret);                                \
363}
364
365#define syscall_3(type,name,d1type,d1,d2type,d2,d3type,d3)  \
366type bsp_##name(d1type d1, d2type d2, d3type d3);           \
367type bsp_##name(d1type d1, d2type d2, d3type d3)            \
368{                                                           \
369   long ret;                                                \
370   register long __d1 __asm__ ("%d1") = (long)d1;           \
371   register long __d2 __asm__ ("%d2") = (long)d2;           \
372   register long __d3 __asm__ ("%d3") = (long)d3;           \
373   __asm__ __volatile__ ("move.l %1,%%d0\n\t"               \
374                         "trap #2\n\t"                      \
375                         "move.l %%d0,%0"                   \
376                         : "=g" (ret)                       \
377                         : "i" (SysCode_##name), "d" (__d1),\
378                                                 "d" (__d2),\
379                                                 "d" (__d3) \
380                         : "d0" );                          \
381   syscall_return(type,ret);                                \
382}
383
384#define SysCode_sysReset           0 /* system reset */
385#define SysCode_program            5 /* program flash memory */
386#define SysCode_gethwaddr         12 /* get hardware address */
387#define SysCode_getbenv           14 /* get bootloader environment variable */
388#define SysCode_setbenv           15 /* set bootloader environment variable */
389#define SysCode_flash_erase_range 19 /* erase a section of flash */
390#define SysCode_flash_write_range 20 /* write a section of flash */
391syscall_1(int, sysReset, int, flags)
392syscall_1(unsigned const char *, gethwaddr, int, a)
393syscall_1(const char *, getbenv, const char *, a)
394syscall_1(int, setbenv, const char *, a)
395syscall_2(int, program, bsp_mnode_t *, chain, int, flags)
396syscall_3(int, flash_erase_range, volatile unsigned short *, flashptr, int, start, int, end);
397syscall_3(int, flash_write_range, volatile unsigned short *, flashptr, bsp_mnode_t *, chain, int, offset);
398
399/* Provide a dummy-implementation of these syscalls
400 * for qemu (which lacks the firmware).
401 */
402
403#define __STR(x)    #x
404#define __STRSTR(x) __STR(x)
405#define ERRVAL      __STRSTR(EACCES)
406
407/* reset-control register */
408#define RCR "__IPSBAR + 0x110000"
409
410__asm__ (
411    "bsp_fake_syscall:         \n"
412    "   cmpl  #0,  %d0         \n" /* sysreset    */
413    "   bne   1f               \n"
414    "   moveb #0x80, %d0       \n"
415    "   moveb %d0, "RCR"       \n" /* reset-controller */
416        /* should never get here - but we'd return -EACCESS if we do */
417    "1:                        \n"
418    "   cmpl  #12, %d0         \n" /* gethwaddr   */
419    "   beq   2f               \n"
420    "   cmpl  #14, %d0         \n" /* getbenv     */
421    "   beq   2f               \n"
422    "   movel #-"ERRVAL", %d0  \n" /* return -EACCESS */
423    "   rte                    \n"
424    "2:                        \n"
425    "   movel #0,  %d0         \n" /* return NULL */
426    "   rte                    \n"
427);
428
429
430/*
431 * 'Extended BSP' routines
432 * Should move to cpukit/score/cpu/m68k/cpu.c someday.
433 */
434
435rtems_status_code bspExtInit(void) { return RTEMS_SUCCESSFUL; }
436int BSP_enableVME_int_lvl(unsigned int level) { return 0; }
437int BSP_disableVME_int_lvl(unsigned int level) { return 0; }
438
439/*
440 * 'VME' interrupt support
441 * Interrupt vectors 192-255 are set aside for use by external logic which
442 * drives IRQ1*.  The actual interrupt source is read from the external
443 * logic at FPGA_IRQ_INFO.  The most-significant bit of the least-significant
444 * byte read from this location is set as long as the external logic has
445 * interrupts to be serviced.  The least-significant six bits indicate the
446 * interrupt source within the external logic and are used to select the
447 * specified interupt handler.
448 */
449#define NVECTOR 256
450#define FPGA_VECTOR (64+1)  /* IRQ1* pin connected to external FPGA */
451#define FPGA_IRQ_INFO    *((vuint16 *)(0x31000000 + 0xfffffe))
452
453static struct handlerTab {
454  BSP_VME_ISR_t func;
455  void         *arg;
456} handlerTab[NVECTOR];
457
458BSP_VME_ISR_t
459BSP_getVME_isr(unsigned long vector, void **pusrArg)
460{
461  if (vector >= NVECTOR)
462    return (BSP_VME_ISR_t)NULL;
463  if (pusrArg)
464    *pusrArg = handlerTab[vector].arg;
465  return handlerTab[vector].func;
466}
467
468static rtems_isr
469fpga_trampoline (rtems_vector_number v)
470{
471  /*
472   * Handle FPGA interrupts until all have been consumed
473   */
474  int loopcount = 0;
475  while (((v = FPGA_IRQ_INFO) & 0x80) != 0) {
476    v = 192 + (v & 0x3f);
477    if (++loopcount >= 50) {
478      rtems_interrupt_level level;
479      rtems_interrupt_disable(level);
480      printk(
481        "\nTOO MANY FPGA INTERRUPTS (LAST WAS 0x%lx) -- "
482        "DISABLING ALL FPGA INTERRUPTS.\n",
483        v & 0x3f
484      );
485      MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1;
486      rtems_interrupt_enable(level);
487      return;
488    }
489    if (handlerTab[v].func)  {
490      (*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v);
491    }
492    else {
493      rtems_interrupt_level level;
494      rtems_vector_number nv;
495      rtems_interrupt_disable(level);
496      printk("\nSPURIOUS FPGA INTERRUPT (0x%lx).\n", v & 0x3f);
497      if ((((nv = FPGA_IRQ_INFO) & 0x80) != 0)
498          && ((nv & 0x3f) == (v & 0x3f))) {
499        printk("DISABLING ALL FPGA INTERRUPTS.\n");
500        MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1;
501      }
502      rtems_interrupt_enable(level);
503      return;
504    }
505  }
506}
507
508static rtems_isr
509trampoline (rtems_vector_number v)
510{
511    if (handlerTab[v].func)
512        (*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v);
513}
514
515static void
516enable_irq(unsigned source)
517{
518rtems_interrupt_level level;
519  rtems_interrupt_disable(level);
520  if (source >= 32)
521    MCF5282_INTC0_IMRH &= ~(1 << (source - 32));
522  else
523    MCF5282_INTC0_IMRL &= ~((1 << source) |
524        MCF5282_INTC_IMRL_MASKALL);
525  rtems_interrupt_enable(level);
526}
527
528static int
529init_intc0_bit(unsigned long vector)
530{
531rtems_interrupt_level level;
532
533    /*
534     * Find an unused level/priority if this is an on-chip (INTC0)
535     * source and this is the first time the source is being used.
536     * Interrupt sources 1 through 7 are fixed level/priority
537     */
538
539    if ((vector >= 65) && (vector <= 127)) {
540        int l, p;
541        int source = vector - 64;
542        static unsigned char installed[8];
543
544        rtems_interrupt_disable(level);
545        if (installed[source/8] & (1 << (source % 8))) {
546            rtems_interrupt_enable(level);
547            return 0;
548        }
549        installed[source/8] |= (1 << (source % 8));
550        rtems_interrupt_enable(level);
551        for (l = 1 ; l < 7 ; l++) {
552            for (p = 0 ; p < 8 ; p++) {
553                if ((source < 8)
554                 || (bsp_allocate_interrupt(l,p) == RTEMS_SUCCESSFUL)) {
555                    if (source < 8)
556                        MCF5282_EPORT_EPIER |= 1 << source;
557                    else
558                        *(&MCF5282_INTC0_ICR1 + (source - 1)) =
559                                                       MCF5282_INTC_ICR_IL(l) |
560                                                       MCF5282_INTC_ICR_IP(p);
561          enable_irq(source);
562                    return 0;
563                }
564            }
565        }
566        return -1;
567    }
568  return 0;
569}
570
571int
572BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg)
573{
574  rtems_isr_entry old_handler;
575  rtems_interrupt_level level;
576
577  /*
578   * Register the handler information
579   */
580  if (vector >= NVECTOR)
581    return -1;
582  handlerTab[vector].func = handler;
583  handlerTab[vector].arg = usrArg;
584
585  /*
586   * If this is an external FPGA ('VME') vector set up the real IRQ.
587   */
588  if ((vector >= 192) && (vector <= 255)) {
589    int i;
590    static volatile int setupDone;
591    rtems_interrupt_disable(level);
592    if (setupDone) {
593      rtems_interrupt_enable(level);
594      return 0;
595    }
596    setupDone = 1;
597    rtems_interrupt_catch(fpga_trampoline, FPGA_VECTOR, &old_handler);
598    i = init_intc0_bit(FPGA_VECTOR);
599    rtems_interrupt_enable(level);
600    return i;
601  }
602
603  /*
604   * Make the connection between the interrupt and the local handler
605   */
606  rtems_interrupt_catch(trampoline, vector, &old_handler);
607
608  return init_intc0_bit(vector);
609}
610
611int
612BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg)
613{
614  if (vector >= NVECTOR)
615    return -1;
616  if ((handlerTab[vector].func != handler)
617     || (handlerTab[vector].arg != usrArg))
618    return -1;
619  handlerTab[vector].func = (BSP_VME_ISR_t)NULL;
620  return 0;
621}
622
623int
624BSP_vme2local_adrs(unsigned am, unsigned long vmeaddr, unsigned long *plocaladdr)
625{
626  unsigned long offset;
627
628  switch (am) {
629    default:    return -1;
630    case VME_AM_SUP_SHORT_IO: offset = 0x31FF0000; break; /* A16/D16 */
631    case VME_AM_STD_SUP_DATA: offset = 0x30000000; break; /* A24/D16 */
632    case VME_AM_EXT_SUP_DATA: offset = 0x31000000; break; /* A32/D32 */
633  }
634  *plocaladdr = vmeaddr + offset;
635  return 0;
636}
637
638void
639bsp_reset_cause(char *buf, size_t capacity)
640{
641  int bit, rsr;
642  size_t i;
643  const char *cp;
644
645  if (buf == NULL)
646    return;
647  if (capacity)
648    buf[0] = '\0';
649  rsr = MCF5282_RESET_RSR;
650  for (i = 0, bit = 0x80 ; bit != 0 ; bit >>= 1) {
651    if (rsr & bit) {
652      switch (bit) {
653        case MCF5282_RESET_RSR_LVD:  cp = "Low voltage";        break;
654        case MCF5282_RESET_RSR_SOFT: cp = "Software reset";     break;
655        case MCF5282_RESET_RSR_WDR:  cp = "Watchdog reset";     break;
656        case MCF5282_RESET_RSR_POR:  cp = "Power-on reset";     break;
657        case MCF5282_RESET_RSR_EXT:  cp = "External reset";     break;
658        case MCF5282_RESET_RSR_LOC:  cp = "Loss of clock";      break;
659        case MCF5282_RESET_RSR_LOL:  cp = "Loss of lock";       break;
660        default:                     cp = "??";                 break;
661      }
662      i += snprintf(buf+i, capacity-i, cp);
663      if (i >= capacity)
664        break;
665      rsr &= ~bit;
666      if (rsr == 0)
667        break;
668      i += snprintf(buf+i, capacity-i, ", ");
669      if (i >= capacity)
670        break;
671    }
672  }
673}
Note: See TracBrowser for help on using the repository browser.