source: rtems/c/src/lib/libbsp/m68k/uC5282/startup/bspstart.c @ c7e77ee

4.115
Last change on this file since c7e77ee was c7e77ee, checked in by Joel Sherrill <joel.sherrill@…>, on 10/14/14 at 17:39:57

mcf5282: Move cache to libcpu and update av5282 and uC5282 BSPs

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