diff options
Diffstat (limited to 'c/src/lib/libbsp/m68k/uC5282/startup/bspstart.c')
-rw-r--r-- | c/src/lib/libbsp/m68k/uC5282/startup/bspstart.c | 673 |
1 files changed, 0 insertions, 673 deletions
diff --git a/c/src/lib/libbsp/m68k/uC5282/startup/bspstart.c b/c/src/lib/libbsp/m68k/uC5282/startup/bspstart.c deleted file mode 100644 index 33ce737ceb..0000000000 --- a/c/src/lib/libbsp/m68k/uC5282/startup/bspstart.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * This routine does the bulk of the system initialisation. - */ - -/* - * Author: W. Eric Norum <norume@aps.anl.gov> - * - * COPYRIGHT (c) 2005. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <bsp.h> -#include <bsp/bootcard.h> -#include <rtems/error.h> -#include <errno.h> -#include <stdio.h> -#include <inttypes.h> -#include <mcf5282/mcf5282.h> - -/* - * Location of 'VME' access - */ -#define VME_ONE_BASE 0x30000000 -#define VME_TWO_BASE 0x31000000 - -/* - * Linker Script Defined Variables - */ -extern char RamSize[]; -extern char RamBase[]; -extern char _CPUClockSpeed[]; -extern char _PLLRefClockSpeed[]; - -uint32_t BSP_sys_clk_speed = (uint32_t)_CPUClockSpeed; -uint32_t BSP_pll_ref_clock = (uint32_t)_PLLRefClockSpeed; - -/* - * CPU-space access - * The NOP after writing the CACR is there to address the following issue as - * described in "Device Errata MCF5282DE", Rev. 1.7, 09/2004: - * - * 6 Possible Cache Corruption after Setting CACR[CINV] - * 6.1 Description - * The cache on the MCF5282 was enhanced to function as a unified data and - * instruction cache, an instruction cache, or an operand cache. The cache - * function and organization is controlled by the cache control register (CACR). - * The CINV (Bit 24 = cache invalidate) bit in the CACR causes a cache clear. - * If the cache is configured as a unified cache and the CINV bit is set, the - * scope of the cache clear is controlled by two other bits in the CACR, - * INVI (BIT 21 = CINV instruction cache only) and INVD (BIT 20 = CINV data - * cache only). These bits allow the entire cache, just the instruction - * portion of the cache, or just the data portion of the cache to be cleared. - * If a write to the CACR is performed to clear the cache (CINV = BIT 24 set) - * and only a partial clear will be done (INVI = BIT 21 or INVD = BIT 20 set), - * then cache corruption may occur. - * - * 6.2 Workaround - * All loads of the CACR that perform a cache clear operation (CINV = BIT 24) - * should be followed immediately by a NOP instruction. This avoids the cache - * corruption problem. - * DATECODES AFFECTED: All - * - * - * Buffered writes must be disabled as described in "MCF5282 Chip Errata", - * MCF5282DE, Rev. 6, 5/2009: - * SECF124: Buffered Write May Be Executed Twice - * Errata type: Silicon - * Affected component: Cache - * Description: If buffered writes are enabled using the CACR or ACR - * registers, the imprecise write transaction generated - * by a buffered write may be executed twice. - * Workaround: Do not enable buffered writes in the CACR or ACR registers: - * CACR[8] = DBWE (default buffered write enable) must be 0 - * ACRn[5] = BUFW (buffered write enable) must be 0 - * Fix plan: Currently, there are no plans to fix this. - */ -#define m68k_set_cacr_nop(_cacr) \ - __asm__ volatile ("movec %0,%%cacr\n\tnop" : : "d" (_cacr)) -#define m68k_set_cacr(_cacr) \ - __asm__ volatile ("movec %0,%%cacr" : : "d" (_cacr)) -#define m68k_set_acr0(_acr0) \ - __asm__ volatile ("movec %0,%%acr0" : : "d" (_acr0)) -#define m68k_set_acr1(_acr1) \ - __asm__ volatile ("movec %0,%%acr1" : : "d" (_acr1)) - -uint32_t mcf5282_acr0_mode = 0; -uint32_t mcf5282_acr1_mode = 0; - -extern void bsp_fake_syscall(int); - -/* - * The Arcturus boot ROM prints exception information improperly - * so use this default exception handler instead. This one also - * prints a call backtrace - */ -static void handler(int pc) -{ - int level; - static volatile int reent; - - rtems_interrupt_disable(level); - if (reent++) bsp_sysReset(0); - { - int *p = &pc; - int info = p[-1]; - int pc = p[0]; - int format = (info >> 28) & 0xF; - int faultStatus = ((info >> 24) & 0xC) | ((info >> 16) & 0x3); - int vector = (info >> 18) & 0xFF; - int statusRegister = info & 0xFFFF; - int *fp; - - printk("\n\nPC:%x SR:%x VEC:%x FORMAT:%x STATUS:%x\n", pc, - statusRegister, - vector, - format, - faultStatus); - fp = &p[-2]; - for(;;) { - int *nfp = (int *)*fp; - if ((nfp <= fp) - || ((char *)nfp >= RamSize) - || ((char *)(nfp[1]) >= RamSize)) - break; - printk("FP:%p -> %p PC:%x\n", fp, nfp, nfp[1]); - fp = nfp; - } - } - rtems_task_suspend(0); - rtems_panic("done"); -} - -void bsp_start( void ) -{ - int i; - const char *clk_speed_str; - uint32_t clk_speed, mfd, rfd; - uint8_t byte; - - /* - * Make sure UART TX is running - necessary for - * early printk to work. The firmware monitor - * usually enables this anyways but qemu doesn't! - */ - MCF5282_UART_UCR(CONSOLE_PORT) = MCF5282_UART_UCR_TX_ENABLED; - - /* - * Set up default exception handler - */ - for (i = 2 ; i < 256 ; i++) - if (i != (32+2)) /* Catch all but bootrom system calls */ - *((void (**)(int))(i * 4)) = handler; - - /* - * Invalidate the cache and disable it - */ - m68k_set_acr0(mcf5282_acr0_mode); - m68k_set_acr1(mcf5282_acr1_mode); - m68k_set_cacr_nop(MCF5XXX_CACR_CINV); - - /* - * Cache SDRAM - * Enable buffered writes - * As Device Errata SECF124 notes this may cause double writes, - * but that's not really a big problem and benchmarking tests have - * shown that buffered writes do gain some performance. - */ - mcf5282_acr0_mode = MCF5XXX_ACR_AB((uint32_t)RamBase) | - MCF5XXX_ACR_AM((uint32_t)RamSize-1) | - MCF5XXX_ACR_EN | - MCF5XXX_ACR_SM_IGNORE | - MCF5XXX_ACR_BWE; - m68k_set_acr0(mcf5282_acr0_mode); - - /* - * Qemu has no trap handler; install our fake syscall - * implementation if there is no existing handler. - */ - if ( 0 == *((void (**)(int))((32+2) * 4)) ) - *((void (**)(int))((32+2) * 4)) = bsp_fake_syscall; - - /* - * Read/write copy of cache registers - * Split instruction/data or instruction-only - * Allow CPUSHL to invalidate a cache line - * Disable buffered writes - * No burst transfers on non-cacheable accesses - * Default cache mode is *disabled* (cache only ACRx areas) - */ - mcf5xxx_initialize_cacr( - MCF5XXX_CACR_CENB | - #ifndef RTEMS_MCF5282_BSP_ENABLE_DATA_CACHE - MCF5XXX_CACR_DISD | - #endif - MCF5XXX_CACR_DCM - ); - - /* - * Set up CS* space (fake 'VME') - * Two A24/D16 spaces, supervisor data acces - */ - MCF5282_CS1_CSAR = MCF5282_CS_CSAR_BA(VME_ONE_BASE); - MCF5282_CS1_CSMR = MCF5282_CS_CSMR_BAM_16M | - MCF5282_CS_CSMR_CI | - MCF5282_CS_CSMR_SC | - MCF5282_CS_CSMR_UC | - MCF5282_CS_CSMR_UD | - MCF5282_CS_CSMR_V; - MCF5282_CS1_CSCR = MCF5282_CS_CSCR_PS_16; - MCF5282_CS2_CSAR = MCF5282_CS_CSAR_BA(VME_TWO_BASE); - MCF5282_CS2_CSMR = MCF5282_CS_CSMR_BAM_16M | - MCF5282_CS_CSMR_CI | - MCF5282_CS_CSMR_SC | - MCF5282_CS_CSMR_UC | - MCF5282_CS_CSMR_UD | - MCF5282_CS_CSMR_V; - MCF5282_CS2_CSCR = MCF5282_CS_CSCR_PS_16; - MCF5282_GPIO_PJPAR |= 0x06; - - /* - * Hopefully, the UART clock is still correctly set up - * so they can see the printk() output... - */ - clk_speed = 0; - printk("Trying to figure out the system clock\n"); - printk("Checking ENV variable SYS_CLOCK_SPEED:\n"); - if ( (clk_speed_str = bsp_getbenv("SYS_CLOCK_SPEED")) ) { - printk("Found: %s\n", clk_speed_str); - for ( clk_speed = 0, i=0; - clk_speed_str[i] >= '0' && clk_speed_str[i] <= '9'; - i++ ) { - clk_speed = 10*clk_speed + clk_speed_str[i] - '0'; - } - if ( 0 != clk_speed_str[i] ) { - printk("Not a decimal number; I'm not using this setting\n"); - clk_speed = 0; - } - } else { - printk("Not set.\n"); - } - - if ( 0 == clk_speed ) - clk_speed = BSP_sys_clk_speed; - - if ( 0 == clk_speed ) { - printk("Using some heuristics to determine clock speed...\n"); - byte = MCF5282_CLOCK_SYNSR; - if ( 0 == byte ) { - printk("SYNSR == 0; assuming QEMU at 66MHz\n"); - BSP_pll_ref_clock = 8250000; - mfd = ( 0 << 8 ) | ( 2 << 12 ); - } else { - if ( 0xf8 != byte ) { - printk("FATAL ERROR: Unexpected SYNSR contents (0x%02x), can't proceed\n", byte); - bsp_sysReset(0); - } - mfd = MCF5282_CLOCK_SYNCR; - } - printk("Assuming %" PRIu32 "Hz PLL ref. clock\n", BSP_pll_ref_clock); - rfd = (mfd >> 8) & 7; - mfd = (mfd >> 12) & 7; - /* Check against 'known' cases */ - if ( 0 != rfd || (2 != mfd && 3 != mfd) ) { - printk("WARNING: Pll divisor/multiplier has unknown value; \n"); - printk(" either your board is not 64MHz or 80Mhz or\n"); - printk(" it uses a PLL reference other than 8MHz.\n"); - printk(" I'll proceed anyways but you might have to\n"); - printk(" reset the board and set uCbootloader ENV\n"); - printk(" variable \"SYS_CLOCK_SPEED\".\n"); - } - mfd = 2 * (mfd + 2); - /* sysclk = pll_ref * 2 * (MFD + 2) / 2^(rfd) */ - printk( - "PLL multiplier: %" PRIu32", output divisor: %" PRIu32 "\n", - mfd, - rfd - ); - clk_speed = (BSP_pll_ref_clock * mfd) >> rfd; - } - - if ( 0 == clk_speed ) { - printk("FATAL ERROR: Unable to determine system clock speed\n"); - bsp_sysReset(0); - } else { - BSP_sys_clk_speed = clk_speed; - printk( - "System clock speed: %" PRIu32 "Hz\n", bsp_get_CPU_clock_speed()); - } -} - -uint32_t bsp_get_CPU_clock_speed(void) -{ - return( BSP_sys_clk_speed ); -} - -/* - * Interrupt controller allocation - */ -rtems_status_code -bsp_allocate_interrupt(int level, int priority) -{ - static char used[7]; - rtems_interrupt_level l; - rtems_status_code ret = RTEMS_RESOURCE_IN_USE; - - if ((level < 1) || (level > 7) || (priority < 0) || (priority > 7)) - return RTEMS_INVALID_NUMBER; - rtems_interrupt_disable(l); - if ((used[level-1] & (1 << priority)) == 0) { - used[level-1] |= (1 << priority); - ret = RTEMS_SUCCESSFUL; - } - rtems_interrupt_enable(l); - return ret; -} - -/* - * Arcturus bootloader system calls - */ -#define syscall_return(type, ret) \ -do { \ - if ((unsigned long)(ret) >= (unsigned long)(-64)) { \ - errno = -(ret); \ - ret = -1; \ - } \ - return (type)(ret); \ -} while (0) - -#define syscall_1(type,name,d1type,d1) \ -type bsp_##name(d1type d1); \ -type bsp_##name(d1type d1) \ -{ \ - long ret; \ - register long __d1 __asm__ ("%d1") = (long)d1; \ - __asm__ __volatile__ ("move.l %1,%%d0\n\t" \ - "trap #2\n\t" \ - "move.l %%d0,%0" \ - : "=g" (ret) \ - : "i" (SysCode_##name), "d" (__d1) \ - : "d0" ); \ - syscall_return(type,ret); \ -} - -#define syscall_2(type,name,d1type,d1,d2type,d2) \ -type bsp_##name(d1type d1, d2type d2); \ -type bsp_##name(d1type d1, d2type d2) \ -{ \ - long ret; \ - register long __d1 __asm__ ("%d1") = (long)d1; \ - register long __d2 __asm__ ("%d2") = (long)d2; \ - __asm__ __volatile__ ("move.l %1,%%d0\n\t" \ - "trap #2\n\t" \ - "move.l %%d0,%0" \ - : "=g" (ret) \ - : "i" (SysCode_##name), "d" (__d1),\ - "d" (__d2) \ - : "d0" ); \ - syscall_return(type,ret); \ -} - -#define syscall_3(type,name,d1type,d1,d2type,d2,d3type,d3) \ -type bsp_##name(d1type d1, d2type d2, d3type d3); \ -type bsp_##name(d1type d1, d2type d2, d3type d3) \ -{ \ - long ret; \ - register long __d1 __asm__ ("%d1") = (long)d1; \ - register long __d2 __asm__ ("%d2") = (long)d2; \ - register long __d3 __asm__ ("%d3") = (long)d3; \ - __asm__ __volatile__ ("move.l %1,%%d0\n\t" \ - "trap #2\n\t" \ - "move.l %%d0,%0" \ - : "=g" (ret) \ - : "i" (SysCode_##name), "d" (__d1),\ - "d" (__d2),\ - "d" (__d3) \ - : "d0" ); \ - syscall_return(type,ret); \ -} - -#define SysCode_sysReset 0 /* system reset */ -#define SysCode_program 5 /* program flash memory */ -#define SysCode_gethwaddr 12 /* get hardware address */ -#define SysCode_getbenv 14 /* get bootloader environment variable */ -#define SysCode_setbenv 15 /* set bootloader environment variable */ -#define SysCode_flash_erase_range 19 /* erase a section of flash */ -#define SysCode_flash_write_range 20 /* write a section of flash */ -syscall_1(int, sysReset, int, flags) -syscall_1(unsigned const char *, gethwaddr, int, a) -syscall_1(const char *, getbenv, const char *, a) -syscall_1(int, setbenv, const char *, a) -syscall_2(int, program, bsp_mnode_t *, chain, int, flags) -syscall_3(int, flash_erase_range, volatile unsigned short *, flashptr, int, start, int, end); -syscall_3(int, flash_write_range, volatile unsigned short *, flashptr, bsp_mnode_t *, chain, int, offset); - -/* Provide a dummy-implementation of these syscalls - * for qemu (which lacks the firmware). - */ - -#define __STR(x) #x -#define __STRSTR(x) __STR(x) -#define ERRVAL __STRSTR(EACCES) - -/* reset-control register */ -#define RCR "__IPSBAR + 0x110000" - -__asm__ ( - "bsp_fake_syscall: \n" - " cmpl #0, %d0 \n" /* sysreset */ - " bne 1f \n" - " moveb #0x80, %d0 \n" - " moveb %d0, "RCR" \n" /* reset-controller */ - /* should never get here - but we'd return -EACCESS if we do */ - "1: \n" - " cmpl #12, %d0 \n" /* gethwaddr */ - " beq 2f \n" - " cmpl #14, %d0 \n" /* getbenv */ - " beq 2f \n" - " movel #-"ERRVAL", %d0 \n" /* return -EACCESS */ - " rte \n" - "2: \n" - " movel #0, %d0 \n" /* return NULL */ - " rte \n" -); - - -/* - * 'Extended BSP' routines - * Should move to cpukit/score/cpu/m68k/cpu.c someday. - */ - -rtems_status_code bspExtInit(void) { return RTEMS_SUCCESSFUL; } -int BSP_enableVME_int_lvl(unsigned int level) { return 0; } -int BSP_disableVME_int_lvl(unsigned int level) { return 0; } - -/* - * 'VME' interrupt support - * Interrupt vectors 192-255 are set aside for use by external logic which - * drives IRQ1*. The actual interrupt source is read from the external - * logic at FPGA_IRQ_INFO. The most-significant bit of the least-significant - * byte read from this location is set as long as the external logic has - * interrupts to be serviced. The least-significant six bits indicate the - * interrupt source within the external logic and are used to select the - * specified interupt handler. - */ -#define NVECTOR 256 -#define FPGA_VECTOR (64+1) /* IRQ1* pin connected to external FPGA */ -#define FPGA_IRQ_INFO *((vuint16 *)(0x31000000 + 0xfffffe)) - -static struct handlerTab { - BSP_VME_ISR_t func; - void *arg; -} handlerTab[NVECTOR]; - -BSP_VME_ISR_t -BSP_getVME_isr(unsigned long vector, void **pusrArg) -{ - if (vector >= NVECTOR) - return (BSP_VME_ISR_t)NULL; - if (pusrArg) - *pusrArg = handlerTab[vector].arg; - return handlerTab[vector].func; -} - -static rtems_isr -fpga_trampoline (rtems_vector_number v) -{ - /* - * Handle FPGA interrupts until all have been consumed - */ - int loopcount = 0; - while (((v = FPGA_IRQ_INFO) & 0x80) != 0) { - v = 192 + (v & 0x3f); - if (++loopcount >= 50) { - rtems_interrupt_level level; - rtems_interrupt_disable(level); - printk( - "\nTOO MANY FPGA INTERRUPTS (LAST WAS 0x%lx) -- " - "DISABLING ALL FPGA INTERRUPTS.\n", - v & 0x3f - ); - MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1; - rtems_interrupt_enable(level); - return; - } - if (handlerTab[v].func) { - (*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v); - } - else { - rtems_interrupt_level level; - rtems_vector_number nv; - rtems_interrupt_disable(level); - printk("\nSPURIOUS FPGA INTERRUPT (0x%lx).\n", v & 0x3f); - if ((((nv = FPGA_IRQ_INFO) & 0x80) != 0) - && ((nv & 0x3f) == (v & 0x3f))) { - printk("DISABLING ALL FPGA INTERRUPTS.\n"); - MCF5282_INTC0_IMRL |= MCF5282_INTC_IMRL_INT1; - } - rtems_interrupt_enable(level); - return; - } - } -} - -static rtems_isr -trampoline (rtems_vector_number v) -{ - if (handlerTab[v].func) - (*handlerTab[v].func)(handlerTab[v].arg, (unsigned long)v); -} - -static void -enable_irq(unsigned source) -{ -rtems_interrupt_level level; - rtems_interrupt_disable(level); - if (source >= 32) - MCF5282_INTC0_IMRH &= ~(1 << (source - 32)); - else - MCF5282_INTC0_IMRL &= ~((1 << source) | - MCF5282_INTC_IMRL_MASKALL); - rtems_interrupt_enable(level); -} - -static int -init_intc0_bit(unsigned long vector) -{ -rtems_interrupt_level level; - - /* - * Find an unused level/priority if this is an on-chip (INTC0) - * source and this is the first time the source is being used. - * Interrupt sources 1 through 7 are fixed level/priority - */ - - if ((vector >= 65) && (vector <= 127)) { - int l, p; - int source = vector - 64; - static unsigned char installed[8]; - - rtems_interrupt_disable(level); - if (installed[source/8] & (1 << (source % 8))) { - rtems_interrupt_enable(level); - return 0; - } - installed[source/8] |= (1 << (source % 8)); - rtems_interrupt_enable(level); - for (l = 1 ; l < 7 ; l++) { - for (p = 0 ; p < 8 ; p++) { - if ((source < 8) - || (bsp_allocate_interrupt(l,p) == RTEMS_SUCCESSFUL)) { - if (source < 8) - MCF5282_EPORT_EPIER |= 1 << source; - else - *(&MCF5282_INTC0_ICR1 + (source - 1)) = - MCF5282_INTC_ICR_IL(l) | - MCF5282_INTC_ICR_IP(p); - enable_irq(source); - return 0; - } - } - } - return -1; - } - return 0; -} - -int -BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg) -{ - rtems_isr_entry old_handler; - rtems_interrupt_level level; - - /* - * Register the handler information - */ - if (vector >= NVECTOR) - return -1; - handlerTab[vector].func = handler; - handlerTab[vector].arg = usrArg; - - /* - * If this is an external FPGA ('VME') vector set up the real IRQ. - */ - if ((vector >= 192) && (vector <= 255)) { - int i; - static volatile int setupDone; - rtems_interrupt_disable(level); - if (setupDone) { - rtems_interrupt_enable(level); - return 0; - } - setupDone = 1; - rtems_interrupt_catch(fpga_trampoline, FPGA_VECTOR, &old_handler); - i = init_intc0_bit(FPGA_VECTOR); - rtems_interrupt_enable(level); - return i; - } - - /* - * Make the connection between the interrupt and the local handler - */ - rtems_interrupt_catch(trampoline, vector, &old_handler); - - return init_intc0_bit(vector); -} - -int -BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *usrArg) -{ - if (vector >= NVECTOR) - return -1; - if ((handlerTab[vector].func != handler) - || (handlerTab[vector].arg != usrArg)) - return -1; - handlerTab[vector].func = (BSP_VME_ISR_t)NULL; - return 0; -} - -int -BSP_vme2local_adrs(unsigned am, unsigned long vmeaddr, unsigned long *plocaladdr) -{ - unsigned long offset; - - switch (am) { - default: return -1; - case VME_AM_SUP_SHORT_IO: offset = 0x31FF0000; break; /* A16/D16 */ - case VME_AM_STD_SUP_DATA: offset = 0x30000000; break; /* A24/D16 */ - case VME_AM_EXT_SUP_DATA: offset = 0x31000000; break; /* A32/D32 */ - } - *plocaladdr = vmeaddr + offset; - return 0; -} - -void -bsp_reset_cause(char *buf, size_t capacity) -{ - int bit, rsr; - size_t i; - const char *cp; - - if (buf == NULL) - return; - if (capacity) - buf[0] = '\0'; - rsr = MCF5282_RESET_RSR; - for (i = 0, bit = 0x80 ; bit != 0 ; bit >>= 1) { - if (rsr & bit) { - switch (bit) { - case MCF5282_RESET_RSR_LVD: cp = "Low voltage"; break; - case MCF5282_RESET_RSR_SOFT: cp = "Software reset"; break; - case MCF5282_RESET_RSR_WDR: cp = "Watchdog reset"; break; - case MCF5282_RESET_RSR_POR: cp = "Power-on reset"; break; - case MCF5282_RESET_RSR_EXT: cp = "External reset"; break; - case MCF5282_RESET_RSR_LOC: cp = "Loss of clock"; break; - case MCF5282_RESET_RSR_LOL: cp = "Loss of lock"; break; - default: cp = "??"; break; - } - i += snprintf(buf+i, capacity-i, cp); - if (i >= capacity) - break; - rsr &= ~bit; - if (rsr == 0) - break; - i += snprintf(buf+i, capacity-i, ", "); - if (i >= capacity) - break; - } - } -} |