File indexing completed on 2025-05-11 08:23:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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
0026
0027 #define VME_ONE_BASE 0x30000000
0028 #define VME_TWO_BASE 0x31000000
0029
0030
0031
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
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
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
0097
0098
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
0146
0147
0148
0149 MCF5282_UART_UCR(CONSOLE_PORT) = MCF5282_UART_UCR_TX_ENABLED;
0150
0151
0152
0153
0154 for (i = 2 ; i < 256 ; i++)
0155 if (i != (32+2))
0156 *((void (**)(int))(i * 4)) = handler;
0157
0158
0159
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
0167
0168
0169
0170
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
0181
0182
0183 if ( 0 == *((void (**)(int))((32+2) * 4)) )
0184 *((void (**)(int))((32+2) * 4)) = bsp_fake_syscall;
0185
0186
0187
0188
0189
0190
0191
0192
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
0204
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
0226
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
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
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
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
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
0385 #define SysCode_program 5
0386 #define SysCode_gethwaddr 12
0387 #define SysCode_getbenv 14
0388 #define SysCode_setbenv 15
0389 #define SysCode_flash_erase_range 19
0390 #define SysCode_flash_write_range 20
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
0400
0401
0402
0403 #define __STR(x) #x
0404 #define __STRSTR(x) __STR(x)
0405 #define ERRVAL __STRSTR(EACCES)
0406
0407
0408 #define RCR "__IPSBAR + 0x110000"
0409
0410 __asm__ (
0411 "bsp_fake_syscall: \n"
0412 " cmpl #0, %d0 \n"
0413 " bne 1f \n"
0414 " moveb #0x80, %d0 \n"
0415 " moveb %d0, "RCR" \n"
0416
0417 "1: \n"
0418 " cmpl #12, %d0 \n"
0419 " beq 2f \n"
0420 " cmpl #14, %d0 \n"
0421 " beq 2f \n"
0422 " movel #-"ERRVAL", %d0 \n"
0423 " rte \n"
0424 "2: \n"
0425 " movel #0, %d0 \n"
0426 " rte \n"
0427 );
0428
0429
0430
0431
0432
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
0441
0442
0443
0444
0445
0446
0447
0448
0449 #define NVECTOR 256
0450 #define FPGA_VECTOR (64+1)
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
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
0535
0536
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
0579
0580 if (vector >= NVECTOR)
0581 return -1;
0582 handlerTab[vector].func = handler;
0583 handlerTab[vector].arg = usrArg;
0584
0585
0586
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
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;
0631 case VME_AM_STD_SUP_DATA: offset = 0x30000000; break;
0632 case VME_AM_EXT_SUP_DATA: offset = 0x31000000; break;
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 }