diff options
Diffstat (limited to 'libgloss/bfin/basiccrt.S')
-rw-r--r-- | libgloss/bfin/basiccrt.S | 627 |
1 files changed, 0 insertions, 627 deletions
diff --git a/libgloss/bfin/basiccrt.S b/libgloss/bfin/basiccrt.S deleted file mode 100644 index beecd53f8..000000000 --- a/libgloss/bfin/basiccrt.S +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Basic startup code for Blackfin processor - * - * Copyright (C) 2008 Analog Devices, Inc. - * - * The authors hereby grant permission to use, copy, modify, distribute, - * and license this software and its documentation for any purpose, provided - * that existing copyright notices are retained in all copies and that this - * notice is included verbatim in any distributions. No written agreement, - * license, or royalty fee is required for any of the authorized uses. - * Modifications to this software may be copyrighted by their authors - * and need not follow the licensing terms described here, provided that - * the new terms are clearly indicated on the first page of each file where - * they apply. - */ - -// basic startup code which -// - turns the cycle counter on -// - loads up FP & SP (both supervisor and user) -// - initialises the device drivers (FIOCRT) -// - calls monstartup to set up the profiling routines (PROFCRT) -// - calls the C++ startup (CPLUSCRT) -// - initialises argc/argv (FIOCRT/normal) -// - calls _main -// - calls _exit (which calls monexit to dump accumulated prof data (PROFCRT)) -// - defines dummy IO routines (!FIOCRT) - -#include <sys/platform.h> -#include <cplb.h> -#include <sys/anomaly_macros_rtl.h> - -#define IVBh (EVT0 >> 16) -#define IVBl (EVT0 & 0xFFFF) -#define UNASSIGNED_VAL 0 -#define UNASSIGNED_FILL 0 -// just IVG15 -#define INTERRUPT_BITS 0x400 -#if defined(_ADI_THREADS) || \ - !defined(__ADSPLPBLACKFIN__) || defined(__ADSPBF561__) || defined(__ADSPBF566__) -#define SET_CLOCK_SPEED 0 -#else -#define SET_CLOCK_SPEED 1 -#endif - -#if SET_CLOCK_SPEED == 1 -#include <sys/pll.h> -#define SET_CLK_MSEL 0x16 -#define SET_CLK_DF 0 -#define SET_CLK_LOCK_COUNT 0x300 -#define SET_CLK_CSEL 0 -#define SET_CLK_SSEL 5 - -/* -** CLKIN == 27MHz on the EZ-Kits. -** D==0 means CLKIN is passed to PLL without dividing. -** MSEL==0x16 means VCO==27*0x16 == 594MHz -** CSEL==0 means CCLK==VCO == 594MHz -** SSEL==5 means SCLK==VCO/5 == 118MHz -*/ - -#endif - -#ifdef __ADSPBF561_COREB__ - .section .b.text,"ax",@progbits - .align 2; - .global __coreb_start; - .type __coreb_start, STT_FUNC; -__coreb_start: -#elif defined(__ADSPBF60x_CORE1__) - .section .1.text,"ax",@progbits - .align 2; - .global __core1_start; - .type __core1_start, STT_FUNC; -__core1_start: -#else - .text; - .align 2; - .global __start; - .type __start, STT_FUNC; -__start: -#endif -#if WA_05000109 - // Avoid Anomaly ID 05000109. -# define SYSCFG_VALUE 0x30 - R1 = SYSCFG_VALUE; - SYSCFG = R1; -#endif -#if WA_05000229 - // Avoid Anomaly 05-00-0229: DMA5_CONFIG and SPI_CTL not cleared on reset. - R1 = 0x400; -#if defined(__ADSPBF538__) || defined(__ADSPBF539__) - P0.L = SPI0_CTL & 0xFFFF; - P0.H = SPI0_CTL >> 16; - W[P0] = R1.L; -#else - P0.L = SPI_CTL & 0xFFFF; - P0.H = SPI_CTL >> 16; - W[P0] = R1.L; -#endif - P0.L = DMA5_CONFIG & 0xFFFF; - P0.H = DMA5_CONFIG >> 16; - R1 = 0; - W[P0] = R1.L; -#endif - // Zap loop counters to zero, to make sure that - // hw loops are disabled - it could be really baffling - // if the counters and bottom regs are set, and we happen - // to run into them. - R7 = 0; - LC0 = R7; - LC1 = R7; - - // Clear the DAG Length regs too, so that it's safe to - // use I-regs without them wrapping around. - L0 = R7; - L1 = R7; - L2 = R7; - L3 = R7; - - // Zero ITEST_COMMAND and DTEST_COMMAND - // (in case they have crud in them and - // does a write somewhere when we enable cache) - I0.L = (ITEST_COMMAND & 0xFFFF); - I0.H = (ITEST_COMMAND >> 16); - I1.L = (DTEST_COMMAND & 0xFFFF); - I1.H = (DTEST_COMMAND >> 16); - R7 = 0; - [I0] = R7; - [I1] = R7; - // It seems writing ITEST_COMMAND from SDRAM with icache enabled - // needs SSYNC. -#ifdef __BFIN_SDRAM - SSYNC; -#else - CSYNC; -#endif - - // Initialise the Event Vector table. - P0.H = IVBh; - P0.L = IVBl; - - // Install __unknown_exception_occurred in EVT so that - // there is defined behaviour. - P0 += 2*4; // Skip Emulation and Reset - P1 = 13; - R1.L = __unknown_exception_occurred; - R1.H = __unknown_exception_occurred; - LSETUP (L$ivt,L$ivt) LC0 = P1; -L$ivt: [P0++] = R1; - // Set IVG15's handler to be the start of the mode-change - // code. Then, before we return from the Reset back to user - // mode, we'll raise IVG15. This will mean we stay in supervisor - // mode, and continue from the mode-change point., but at a - // much lower priority. - P1.H = L$supervisor_mode; - P1.L = L$supervisor_mode; - [P0] = P1; - - // Initialise the stack. - // Note: this points just past the end of the section. - // First write should be with [--SP]. -#ifdef __BFIN_SDRAM - SP.L = __end + 0x400000 - 12; - SP.H = __end + 0x400000 - 12; -#else -#ifdef __ADSPBF561_COREB__ - SP.L=__coreb_stack_end - 12; - SP.H=__coreb_stack_end - 12; -#elif defined(__ADSPBF60x_CORE1__) - SP.L=__core1_stack_end - 12; - SP.H=__core1_stack_end - 12; -#else - SP.L=__stack_end - 12; - SP.H=__stack_end - 12; -#endif -#endif - usp = sp; - - // We're still in supervisor mode at the moment, so the FP - // needs to point to the supervisor stack. - FP = SP; - - // And make space for incoming "parameters" for functions - // we call from here: - SP += -12; - - // Zero out bss section -#ifdef __BFIN_SDRAM - R0.L = ___bss_start; - R0.H = ___bss_start; - R1.L = __end; - R1.H = __end; -#else -#ifdef __ADSPBF561_COREB__ - R0.L = __coreb_bss_start; - R0.H = __coreb_bss_start; - R1.L = __coreb_bss_end; - R1.H = __coreb_bss_end; -#elif defined(__ADSPBF60x_CORE1__) - R0.L = __core1_bss_start; - R0.H = __core1_bss_start; - R1.L = __core1_bss_end; - R1.H = __core1_bss_end; -#else - R0.L = __bss_start; - R0.H = __bss_start; - R1.L = __bss_end; - R1.H = __bss_end; -#endif -#endif - R2 = R1 - R0; - R1 = 0; -#ifdef __ADSPBF561_COREB__ - CALL.X __coreb_memset; -#elif defined(__ADSPBF60x_CORE1__) - CALL.X __core1_memset; -#else - CALL.X _memset; -#endif - - R0 = INTERRUPT_BITS; - R0 <<= 5; // Bits 0-4 not settable. - // CALL.X __install_default_handlers; - R4 = R0; // Save modified list - - R0 = SYSCFG; // Enable the Cycle counter - BITSET(R0,1); - SYSCFG = R0; - -#if WA_05000137 - // Avoid anomaly #05000137 - - // Set the port preferences of DAG0 and DAG1 to be - // different; this gives better performance when - // performing dual-dag operations on SDRAM. - P0.L = DMEM_CONTROL & 0xFFFF; - P0.H = DMEM_CONTROL >> 16; - R0 = [P0]; - BITSET(R0, 12); - BITCLR(R0, 13); - [P0] = R0; - CSYNC; -#endif - - // Reinitialise data areas in RAM from ROM, if MemInit's - // been used. - // CALL.X _mi_initialize; - -#if defined(__ADSPLPBLACKFIN__) -#if SET_CLOCK_SPEED == 1 - -#if 0 - // Check if this feature is enabled, i.e. ___clk_ctrl is defined to non-zero - P0.L = ___clk_ctrl; - P0.H = ___clk_ctrl; - R0 = MAX_IN_STARTUP; - R1 = [P0]; - R0 = R0 - R1; - CC = R0; - IF CC JUMP L$clock_is_set; -#endif - - // Investigate whether we are a suitable revision - // for boosting the system clocks. - // speed. - P0.L = DSPID & 0xFFFF; - P0.H = DSPID >> 16; - R0 = [P0]; - R0 = R0.L (Z); - CC = R0 < 2; - IF CC JUMP L$clock_is_set; - - // Set the internal Voltage-Controlled Oscillator (VCO) - R0 = SET_CLK_MSEL (Z); - R1 = SET_CLK_DF (Z); - R2 = SET_CLK_LOCK_COUNT (Z); - CALL.X __pll_set_system_vco; - - // Set the Core and System clocks - R0 = SET_CLK_CSEL (Z); - R1 = SET_CLK_SSEL (Z); - CALL.X __pll_set_system_clocks; - -L$clock_is_set: -#endif -#endif /* ADSPLPBLACKFIN */ - -#if defined(__ADSPBF561__) || defined(__ADSPBF566__) || defined(__ADSPBF606__) || defined(__ADSPBF607__) || defined(__ADSPBF608__) || defined(__ADSPBF609__) - - // Initialise the multi-core data tables. - // A dummy function will be called if we are not linking with - // -multicore - // CALL.X __mc_data_initialise; -#endif - -#if 0 - // Write the cplb exception handler to the EVT if approprate and - // initialise the CPLBs if they're needed. couldn't do - // this before we set up the stacks. - P2.H = ___cplb_ctrl; - P2.L = ___cplb_ctrl; - R0 = CPLB_ENABLE_ANY_CPLBS; - R6 = [P2]; - R0 = R0 & R6; - CC = R0; - IF !CC JUMP L$no_cplbs; -#if !defined(_ADI_THREADS) - P1.H = __cplb_hdr; - P1.L = __cplb_hdr; - P0.H = IVBh; - P0.L = IVBl; - [P0+12] = P1; // write exception handler -#endif /* _ADI_THREADS */ - R0 = R6; - CALL.X __cplb_init; -#endif -L$no_cplbs: - // Enable interrupts - STI R4; // Using the mask from default handlers - RAISE 15; - - // Move the processor into user mode. - P0.L=L$still_interrupt_in_ipend; - P0.H=L$still_interrupt_in_ipend; - RETI=P0; - -L$still_interrupt_in_ipend: - rti; // keep doing 'rti' until we've 'finished' servicing all - // interrupts of priority higher than IVG15. Normally one - // would expect to only have the reset interrupt in IPEND - // being serviced, but occasionally when debugging this may - // not be the case - if restart is hit when servicing an - // interrupt. - // - // When we clear all bits from IPEND, we'll enter user mode, - // then we'll automatically jump to supervisor_mode to start - // servicing IVG15 (which we will 'service' for the whole - // program, so that the program is in supervisor mode. - // - // Need to do this to 'finish' servicing the reset interupt. - -L$supervisor_mode: - [--SP] = RETI; // re-enables the interrupt system - - R0.L = UNASSIGNED_VAL; - R0.H = UNASSIGNED_VAL; -#if UNASSIGNED_FILL - R2=R0; - R3=R0; - R4=R0; - R5=R0; - R6=R0; - R7=R0; - P0=R0; - P1=R0; - P2=R0; - P3=R0; - P4=R0; - P5=R0; -#endif - // Push a RETS and Old FP onto the stack, for sanity. - [--SP]=R0; - [--SP]=R0; - // Make sure the FP is sensible. - FP = SP; - - // And leave space for incoming "parameters" - SP += -12; - -#ifdef PROFCRT - CALL.X monstartup; // initialise profiling routines -#endif /* PROFCRT */ - -#if !defined(__ADSPBF561_COREB__) && !defined(__ADSPBF60x_CORE1__) - CALL.X __init; - - R0.L = __fini; - R0.H = __fini; - CALL.X _atexit; -#endif - -#if !defined(_ADI_THREADS) -#ifdef FIOCRT - // FILE IO provides access to real command-line arguments. - CALL.X __getargv; - r1.l=__Argv; - r1.h=__Argv; -#else - // Default to having no arguments and a null list. - R0=0; -#ifdef __ADSPBF561_COREB__ - R1.L=L$argv_coreb; - R1.H=L$argv_coreb; -#elif defined(__ADSPBF60x_CORE1__) - R1.L=L$argv_core1; - R1.H=L$argv_core1; -#else - R1.L=L$argv; - R1.H=L$argv; -#endif -#endif /* FIOCRT */ -#endif /* _ADI_THREADS */ - - // At long last, call the application program. -#ifdef __ADSPBF561_COREB__ - CALL.X _coreb_main; -#elif defined(__ADSPBF60x_CORE1__) - CALL.X _core1_main; -#else - CALL.X _main; -#endif - -#if !defined(_ADI_THREADS) -#if !defined(__ADSPBF561_COREB__) && !defined(__ADSPBF60x_CORE1__) - CALL.X _exit; // passing in main's return value -#endif -#endif - -#ifdef __ADSPBF561_COREB__ - .size __coreb_start, .-__coreb_start -#elif defined(__ADSPBF60x_CORE1__) - .size __core1_start, .-__core1_start -#else - .size __start, .-__start -#endif - - .align 2 - .type __unknown_exception_occurred, STT_FUNC; -__unknown_exception_occurred: - // This function is invoked by the default exception - // handler, if it does not recognise the kind of - // exception that has occurred. In other words, the - // default handler only handles some of the system's - // exception types, and it does not expect any others - // to occur. If your application is going to be using - // other kinds of exceptions, you must replace the - // default handler with your own, that handles all the - // exceptions you will use. - // - // Since there's nothing we can do, we just loop here - // at what we hope is a suitably informative label. - IDLE; - CSYNC; - JUMP __unknown_exception_occurred; - RTS; - .size __unknown_exception_occurred, .-__unknown_exception_occurred - -#if defined(__ADSPLPBLACKFIN__) -#if SET_CLOCK_SPEED == 1 - -/* -** CLKIN == 27MHz on the EZ-Kits. -** D==0 means CLKIN is passed to PLL without dividing. -** MSEL==0x16 means VCO==27*0x16 == 594MHz -** CSEL==0 means CCLK==VCO == 594MHz -** SSEL==5 means SCLK==VCO/5 == 118MHz -*/ - -// int pll_set_system_clocks(int csel, int ssel) -// returns 0 for success, -1 for error. - - .align 2 - .type __pll_set_system_clocks, STT_FUNC; -__pll_set_system_clocks: - P0.H = PLL_DIV >> 16; - P0.L = PLL_DIV & 0xFFFF; - R2 = W[P0] (Z); - - // Plant CSEL and SSEL - R0 <<= 16; - R0.L = (4 << 8) | 2; // 2 bits, at posn 4 - R1 <<= 16; - R1.L = 4; // 4 bits, at posn 0 - R2 = DEPOSIT(R2, R0); - -#if defined(__WORKAROUND_DREG_COMP_LATENCY) - // Work around anomaly 05-00-0209 which affects the DEPOSIT - // instruction (and the EXTRACT, SIGNBITS, and EXPADJ instructions) - // if the previous instruction created any of its operands - NOP; -#endif - - R2 = DEPOSIT(R2, R1); - - W[P0] = R2; - SSYNC; - RTS; - .size __pll_set_system_clocks, .-__pll_set_system_clocks - -// int pll_set_system_vco(int msel, int df, lockcnt) - .align 2 - .type __pll_set_system_vco, STT_FUNC; -__pll_set_system_vco: - P0.H = PLL_CTL >> 16; - P0.L = PLL_CTL & 0xFFFF; - R3 = W[P0] (Z); - P2 = R3; // Save copy - R3 >>= 1; // Drop old DF - R1 = ROT R1 BY -1; // Move DF into CC - R3 = ROT R3 BY 1; // and into ctl space. - R0 <<= 16; // Set up pattern reg - R0.L = (9<<8) | 6; // (6 bits at posn 9) - R1 = P2; // Get the old version - R3 = DEPOSIT(R3, R0); - CC = R1 == R3; // and if we haven't changed - IF CC JUMP L$done; // Anything, return - - CC = R2 == 0; // Use default lockcount if - IF CC JUMP L$wakeup; // user one is zero. - P2.H = PLL_LOCKCNT >> 16; - P2.L = PLL_LOCKCNT & 0xFFFF; - W[P2] = R2; // Set the lock counter -L$wakeup: - P2.H = SIC_IWR >> 16; - P2.L = SIC_IWR & 0xFFFF; - R2 = [P2]; - BITSET(R2, 0); // enable PLL Wakeup - [P2] = R2; - - W[P0] = R3; // Update PLL_CTL - SSYNC; - - CLI R2; // Avoid unnecessary interrupts - IDLE; // Wait until PLL has locked - STI R2; // Restore interrupts. - -L$done: - RTS; - .size __pll_set_system_vco, .-__pll_set_system_vco -#endif -#endif /* ADSPLPBLACKFIN */ - -#if defined(__ADSPBF561_COREB__) || defined(__ADSPBF60x_CORE1__) -#ifdef __ADSPBF561_COREB__ - .section .b.text,"ax",@progbits - .type __coreb_memset, STT_FUNC -__coreb_memset: -#else - .section .1.text,"ax",@progbits - .type __core1_memset, STT_FUNC -__core1_memset: -#endif - P0 = R0 ; /* P0 = address */ - P2 = R2 ; /* P2 = count */ - R3 = R0 + R2; /* end */ - CC = R2 <= 7(IU); - IF CC JUMP .Ltoo_small; - R1 = R1.B (Z); /* R1 = fill char */ - R2 = 3; - R2 = R0 & R2; /* addr bottom two bits */ - CC = R2 == 0; /* AZ set if zero. */ - IF !CC JUMP .Lforce_align ; /* Jump if addr not aligned. */ - -.Laligned: - P1 = P2 >> 2; /* count = n/4 */ - R2 = R1 << 8; /* create quad filler */ - R2.L = R2.L + R1.L(NS); - R2.H = R2.L + R1.H(NS); - P2 = R3; - - LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1; -.Lquad_loop: - [P0++] = R2; - - CC = P0 == P2; - IF !CC JUMP .Lbytes_left; - RTS; - -.Lbytes_left: - R2 = R3; /* end point */ - R3 = P0; /* current position */ - R2 = R2 - R3; /* bytes left */ - P2 = R2; - -.Ltoo_small: - CC = P2 == 0; /* Check zero count */ - IF CC JUMP .Lfinished; /* Unusual */ - -.Lbytes: - LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2; -.Lbyte_loop: - B[P0++] = R1; - -.Lfinished: - RTS; - -.Lforce_align: - CC = BITTST (R0, 0); /* odd byte */ - R0 = 4; - R0 = R0 - R2; - P1 = R0; - R0 = P0; /* Recover return address */ - IF !CC JUMP .Lskip1; - B[P0++] = R1; -.Lskip1: - CC = R2 <= 2; /* 2 bytes */ - P2 -= P1; /* reduce count */ - IF !CC JUMP .Laligned; - B[P0++] = R1; - B[P0++] = R1; - JUMP .Laligned; -#ifdef __ADSPBF561_COREB__ -.size __coreb_memset,.-__coreb_memset -#else -.size __core1_memset,.-__core1_memset -#endif -#endif - -#ifdef __ADSPBF561_COREB__ - .section .b.bss,"aw",@progbits - .align 4 - .type L$argv_coreb, @object - .size L$argv_coreb, 4 -L$argv_coreb: - .zero 4 -#elif defined(__ADSPBF60x_CORE1__) - .section .1.bss,"aw",@progbits - .align 4 - .type L$argv_core1, @object - .size L$argv_core1, 4 -L$argv_core1: - .zero 4 -#else - .local L$argv - .comm L$argv,4,4 -#endif - |