/* sysinit.c - MCF5282 lo-level routines */ /* * File: sysinit.c * * Purpose: Reset configuration of the M5282EVB * * ** THIS FILE SUPPORTS Motorola, Avnet, and Arrow EVBs ** * */ #include "rtxcapi.h" #include "sysinit.h" #include "enable.h" /* NOTE: This File contains RTXCgen Project **DEPENDENCIES** as follows: */ #include "kproject.h" /* CLKTICK */ #include "m52xxevb.h" #include "mcf5xxx.h" #include "mcf5282.h" #if 0 /* { */ /* debug stuff */ typedef struct _icr_struct { unsigned char icr[64]; } ICR_Struct; /* NOTE: _pICR must be FORCED or else trashed */ extern const ICR_Struct *pICR = (ICR_Struct *)(&__IPSBAR[0x0C40]); #endif /* } 0 */ /* PRESCALER value used is log2'(x) where x is divider */ /* */ /* log2' / N */ /* -- ---- */ /* 0 0000 2 */ /* 1 0001 4 */ /* 2 0010 8 */ /* 3 0011 16 */ /* 4 0100 32 */ /* 5 0101 64 */ /* 6 0110 128 */ /* 7 0111 256 */ /* 8 1000 512 */ /* 9 1001 1024 */ /* 10 1010 2048 */ /* 11 1011 4096 */ /* 12 1100 8192 */ /* 13 1101 16384 */ /* 14 1110 32768 */ /* 15 1111 65536 */ /* * Ideally, LOAD_VALUE = (CLKTICK * 1.0E6) / SYSTEM_CLK_PERIOD * but LOAD_VALUE is limited to 16-bits so you must divide using PRESCALER_VALUE * which means that SYSTEM_CLK_PERIOD term must be multiplied by same value * * The goal is to use as small as a divider as possible to get largest 16-bit load * value. Selecting a divisor of 16 will span CLKTICK of 1 - 10 ms @ 64 MHz. */ #define LOAD0_VALUE (uint16)( (CLKTICK * 1.0E6) / ( 8 * SYSTEM_CLK_PERIOD * 2) ) #define PRESCALER0_VALUE 1 #define LOAD1_VALUE (uint16)( (CLKTICK * 1.0E6) / ( 8 * SYSTEM_CLK_PERIOD * 2) ) #define PRESCALER1_VALUE 1 #define LOAD2_VALUE (uint16)( (CLKTICK * 1.0E6) / (16 * SYSTEM_CLK_PERIOD * 2) ) #define PRESCALER2_VALUE 3 #define LOAD3_VALUE (uint16)( (CLKTICK * 1.0E6) / (32 * SYSTEM_CLK_PERIOD * 2) ) #define PRESCALER3_VALUE 4 /* PIT device handles for internal use */ #define PIT0_DEVICE 0 /* do not change */ #define PIT1_DEVICE 1 /* do not change */ #define PIT2_DEVICE 2 /* do not change */ #define PIT3_DEVICE 3 /* do not change */ static void write_RAMBAR(unsigned long x) { __asm__ __volatile__("movec %[val],%%rambar" : : [val] "d" (x)); } void write_FLASHBAR(register unsigned long x) { __asm__ __volatile__("movec %[val],%%flashbar" : : [val] "d" (x)); } void mcf5282_init(void) { write_RAMBAR( RAMBAR_BA(SRAM_ADDRESS) + RAMBAR_PRI(RAMBAR_PRI_CPU_CPU) + RAMBAR_SPV(RAMBAR_SPV_ENABLE) + RAMBAR_WP(RAMBAR_WP_RW) + RAMBAR_CI(0) + RAMBAR_SC(0) + RAMBAR_SD(0) + RAMBAR_UC(0) + RAMBAR_UD(0) + RAMBAR_V ); MCF5282_SCM_RAMBAR = MCF5282_SCM_RAMBAR_BA(SRAM_ADDRESS) + MCF5282_SCM_RAMBAR_BDE; mcf5282_wtm_init(); mcf5282_pll_init(); mcf5282_scm_init(); mcf5282_cs_init(); mcf5282_gpio_init(); mcf5282_sdram_init(); mcf5282_emac_init(); mcf5282_flash_init(); mcf5282_can_init(); } /********************************************************************/ void mcf5282_pit_init(void) { #ifdef HAS_PIT0 /* { */ /* Enable PIT 0 interrupts to ColdFire core */ if (checkICR(55, PIT0_LEVEL, PIT0_PRIORITY) ) __asm__("halt"); MCF5282_INTC0_ICR55 = MCF5282_INTC_ICR_IL(PIT0_LEVEL) | MCF5282_INTC_ICR_IP(PIT0_PRIORITY); /* Set Timer Interrupt Mask Register */ MCF5282_INTC0_IMRH &= (unsigned long) ~(MCF5282_INTC_IMRH_INT55); MCF5282_PIT_PCSR(PIT0_DEVICE) = MCF5282_PIT_PCSR_PRE(PRESCALER0_VALUE) | MCF5282_PIT_PCSR_OVW | MCF5282_PIT_PCSR_RLD; MCF5282_PIT_PMR(PIT0_DEVICE) = LOAD0_VALUE - 1; /* enable count and enable interrupt, disable overwrite PMR */ MCF5282_PIT_PCSR(PIT0_DEVICE) |= MCF5282_PIT_PCSR_EN | MCF5282_PIT_PCSR_PIE; MCF5282_PIT_PCSR(PIT0_DEVICE) &= (uint16) ~(MCF5282_PIT_PCSR_OVW); #endif /* } HAS_PIT0 */ #ifdef HAS_PIT1 /* { */ /* Enable PIT 1 interrupts to ColdFire core */ if (checkICR(56, PIT1_LEVEL, PIT1_PRIORITY) ) __asm__("halt"); MCF5282_INTC0_ICR56 = MCF5282_INTC_ICR_IL(PIT1_LEVEL) | MCF5282_INTC_ICR_IP(PIT1_PRIORITY); /* Set Timer Interrupt Mask Register */ MCF5282_INTC0_IMRH &= (unsigned long) ~(MCF5282_INTC_IMRH_INT56); MCF5282_PIT_PCSR(PIT1_DEVICE) = MCF5282_PIT_PCSR_PRE(PRESCALER1_VALUE) | MCF5282_PIT_PCSR_OVW | MCF5282_PIT_PCSR_RLD; MCF5282_PIT_PMR(PIT1_DEVICE) = LOAD1_VALUE - 1; /* enable count and enable interrupt, disable overwrite PMR */ MCF5282_PIT_PCSR(PIT1_DEVICE) |= MCF5282_PIT_PCSR_EN | MCF5282_PIT_PCSR_PIE; MCF5282_PIT_PCSR(PIT1_DEVICE) &= (uint16) ~(MCF5282_PIT_PCSR_OVW); #endif /* } HAS_PIT1 */ #ifdef HAS_PIT2 /* { */ /* Enable PIT 2 interrupts to ColdFire core */ if (checkICR(57, PIT2_LEVEL, PIT2_PRIORITY) ) __asm__("halt"); MCF5282_INTC0_ICR57 = MCF5282_INTC_ICR_IL(PIT2_LEVEL) | MCF5282_INTC_ICR_IP(PIT2_PRIORITY); /* Set Timer Interrupt Mask Register */ MCF5282_INTC0_IMRH &= (unsigned long) ~(MCF5282_INTC_IMRH_INT57); MCF5282_PIT_PCSR(PIT2_DEVICE) = MCF5282_PIT_PCSR_PRE(PRESCALER2_VALUE) | MCF5282_PIT_PCSR_OVW | MCF5282_PIT_PCSR_RLD; MCF5282_PIT_PMR(PIT2_DEVICE) = LOAD2_VALUE - 1; /* enable count and enable interrupt, disable overwrite PMR */ MCF5282_PIT_PCSR(PIT2_DEVICE) |= MCF5282_PIT_PCSR_EN | MCF5282_PIT_PCSR_PIE; MCF5282_PIT_PCSR(PIT2_DEVICE) &= (uint16) ~(MCF5282_PIT_PCSR_OVW); #endif /* } HAS_PIT2 */ #ifdef HAS_PIT3 /* { */ /* Enable PIT 3 interrupts to ColdFire core */ if (checkICR(58, PIT3_LEVEL, PIT3_PRIORITY) ) __asm__("halt"); MCF5282_INTC0_ICR58 = MCF5282_INTC_ICR_IL(PIT3_LEVEL) | MCF5282_INTC_ICR_IP(PIT3_PRIORITY); /* Set Timer Interrupt Mask Register */ MCF5282_INTC0_IMRH &= (unsigned long) ~(MCF5282_INTC_IMRH_INT58); MCF5282_PIT_PCSR(PIT3_DEVICE) = MCF5282_PIT_PCSR_PRE(PRESCALER3_VALUE) | MCF5282_PIT_PCSR_OVW | MCF5282_PIT_PCSR_RLD; MCF5282_PIT_PMR(PIT3_DEVICE) = LOAD3_VALUE - 1; /* enable count and enable interrupt, disable overwrite PMR */ MCF5282_PIT_PCSR(PIT3_DEVICE) |= (MCF5282_PIT_PCSR_EN | MCF5282_PIT_PCSR_PIE); MCF5282_PIT_PCSR(PIT3_DEVICE) &= (uint16) ~(MCF5282_PIT_PCSR_OVW); #endif /* } HAS_PIT3 */ } /* PIT 0 interrupt handler */ void pit0isrc(void); #ifdef HAS_PIT0 /* { */ uint32 pit0cnt; void pit0isrc(void) { pit0cnt++; /* clear interrupt */ MCF5282_PIT_PMR(PIT0_DEVICE) = LOAD0_VALUE - 1; IS_ProcessEventSourceTick((EVNTSRC)0, 1); LOWER; } #else void pit0isrc(void) { ; } #endif /* } HAS_PIT0 */ /* PIT 1 interrupt handler */ void pit1isrc(void); #ifdef HAS_PIT1 /* { */ uint32 pit1cnt; void pit1isrc(void) { pit1cnt++; /* clear interrupt */ MCF5282_PIT_PMR(PIT1_DEVICE) = LOAD1_VALUE - 1; LOWER; } #else void pit1isrc(void) { ; } #endif /* } HAS_PIT1 */ /* PIT 2 interrupt handler */ void pit2isrc(void); #ifdef HAS_PIT2 /* { */ uint32 pit2cnt; void pit2isrc(void) { pit2cnt++; /* clear interrupt */ MCF5282_PIT_PMR(PIT2_DEVICE) = LOAD2_VALUE - 1; LOWER; } #else void pit2isrc(void) { ; } #endif /* } HAS_PIT2 */ /* PIT 3 interrupt handler */ void pit3isrc(void); #ifdef HAS_PIT3 /* { */ uint32 pit3cnt; void pit3isrc(void) { pit3cnt++; /* clear interrupt */ MCF5282_PIT_PMR(PIT3_DEVICE) = LOAD3_VALUE - 1; LOWER; } #else void pit3isrc(void) { ; } #endif /* } HAS_PIT3 */ /********************************************************************/ void mcf5282_wtm_init(void) { /* * Disable Software Watchdog Timer */ MCF5282_WTM_WCR = 0; } /********************************************************************/ void mcf5282_pll_init(void); void mcf5282_pll_init(void) { /* WARNING: Changing the clock synchronization while running */ /* in SDRAM causes the system to crash. */ /* * Multiply reference crystal by 8 to achieve system clock of 8 x Ref * (at reset MFD=2, RFD=1 yielding x 4 factor = 32 MHz) */ #if 0 /* { */ // net 4x clock - reset condition MCF5282_CLOCK_SYNCR = MCF5282_CLOCK_SYNCR_MFD(2) + MCF5282_CLOCK_SYNCR_RFD(1); #else // net 8x clock MCF5282_CLOCK_SYNCR = MCF5282_CLOCK_SYNCR_MFD(2) + MCF5282_CLOCK_SYNCR_RFD(1); #endif /* } 0 */ while (!(MCF5282_CLOCK_SYNSR & MCF5282_CLOCK_SYNSR_LOCK)) { ; } } /****************************************************************/ void mcf5282_scm_init(void) { /* * Enable on-chip modules to access internal SRAM */ MCF5282_SCM_RAMBAR = MCF5282_SCM_RAMBAR_BA(SRAM_ADDRESS) | MCF5282_SCM_RAMBAR_BDE; /* * Enable FEC via MPR + PACR8 (later move this to FEC driver) */ MCF5282_SCM_MPR |= MCF5282_SCM_MPR_MPR(MCF5282_SCM_MPR_FEC); } /********************************************************************/ void mcf5282_gpio_init(void) { /* * When booting from external Flash, the port-size is less than * the port-size of SDRAM. In this case it is necessary to enable * Data[23:0] on Ports B, C, and D. */ MCF5282_GPIO_PBCDPAR = MCF5282_GPIO_PBCDPAR_PBPA | MCF5282_GPIO_PBCDPAR_PCDPA; } /********************************************************************/ #if defined(MOTOROLA_M5282EVB) || defined(AXIOM_M5282EVB) /* { */ /* Motorola and Axiom M5282EVBs are 32-bit wide */ void mcf5282_sdram_init(void) { int i; if (!(MCF5282_SDRAMC_DACR0 & MCF5282_SDRAMC_DACR_RE)) { /* * Initialize DRAM Control Register: DCR */ MCF5282_SDRAMC_DCR = (0 | MCF5282_SDRAMC_DCR_RTIM_6 | MCF5282_SDRAMC_DCR_RC( ((int)(15 * SYSTEM_CLOCK) / 16)) ); /* * Initialize DACR0 */ MCF5282_SDRAMC_DACR0 = (0 | MCF5282_SDRAMC_DACR_BASE(SDRAM_ADDRESS) | MCF5282_SDRAMC_DACR_CASL(1) | MCF5282_SDRAMC_DACR_CBM(3) | MCF5282_SDRAMC_DACR_PS_32); /* * Initialize DMR0 */ MCF5282_SDRAMC_DMR0 = (0 | MCF5282_SDRAMC_DMR_BAM_16M | MCF5282_SDRAMC_DMR_V); /* * Set IP (bit 3) in DACR */ MCF5282_SDRAMC_DACR0 |= MCF5282_SDRAMC_DACR_IP; /* * Write to this block to initiate precharge */ *(uint32 *)(SDRAM_ADDRESS + 0x0000) = 0xA5A59696; /* * Set RE (bit 15) in DACR */ MCF5282_SDRAMC_DACR0 |= MCF5282_SDRAMC_DACR_RE; /* * Wait for at least 8 auto refresh cycles to occur */ for (i = 0; i < 2000; i++) { __asm__("nop"); } /* * Finish the configuration by issuing the IMRS */ MCF5282_SDRAMC_DACR0 |= MCF5282_SDRAMC_DACR_IMRS; /* * Write to the SDRAM Mode Register */ *(uint32 *)(SDRAM_ADDRESS + 0x0400) = 0xA5A59696; } } #endif /* } MOTOROLA_M5282EVB || AXIOM_M5282EVB */ /********************************************************************/ #if defined(MOTOROLA_M5282EVB) || defined(AVNET_M5282EVB) || defined(AXIOM_M5282EVB) /* { */ void mcf5282_cs_init(void) { MCF5282_CS6_CSMR = 0; /* Disable */ MCF5282_CS5_CSMR = 0; /* Disable */ MCF5282_CS4_CSMR = 0; /* Disable */ MCF5282_CS3_CSMR = 0; /* Disable */ MCF5282_CS2_CSMR = 0; /* Disable */ MCF5282_CS1_CSMR = 0; /* Disable */ MCF5282_CS1_CSAR = 0x3000; /* set the base address 0x3000,0000 */ MCF5282_CS1_CSCR = MCF5282_CS_CSCR_PS_32 | MCF5282_CS_CSCR_AA | MCF5282_CS_CSCR_WS(0xF); /* 32 bits access, internal wait state, set up 15 clock ticks */ MCF5282_CS1_CSMR = 0x10001; /* 128K memory size, vaild */ MCF5282_CS2_CSAR = 0x3100; /* set the base address 0x3100,0000 */ /* MCF5282_CS2_CSCR = MCF5282_CS_CSCR_PS_32 | MCF5282_CS_CSCR_AA | MCF5282_CS_CSCR_WS(0xF); */ MCF5282_CS2_CSCR = MCF5282_CS_CSCR_PS_32 | MCF5282_CS_CSCR_WS(0xF); /* 32 bits access, internal wait state, set up 15 clock ticks */ MCF5282_CS2_CSMR = 0x10001; /* 128K memory size, vaild */ } #endif /* } MOTOROLA_M5282EVB || AVNET_M5282EVB || AXIOM_M5282EVB */ /********************************************************************/ /* validate that duplicates level/priority settings don't exist within INTC */ int checkICR(int n, int level, int priority) { int i; unsigned char *pICR, icrvalue; icrvalue = (unsigned char) (MCF5282_INTC_ICR_IL(level) | MCF5282_INTC_ICR_IP(priority)); if (n < 64) { pICR = (unsigned char *)(&__IPSBAR[0x0C40]); /* INTC0 */ /* check ICR range ICR8...62 in INTC0 */ for(i = 8; i <= 62; i++) { if (i == n) /* skip self */ continue; if (*(pICR + i) == icrvalue) return 1; /* failure - duplicate IL/IP combo */ } } else { pICR = (unsigned char *)(&__IPSBAR[0x0D40 - 64]); /* INTC1 */ /* check ICR range ICR8...26 in INTC1 */ for(i = 8; i <= 26; i++) { if (i == n) /* skip self */ continue; if (*(pICR + i) == icrvalue) return 1; /* failure - duplicate IL/IP combo */ } } return 0; } /* NOTE: ICR # .GT. 63 refers to INTC1; e.g., 72 -> INTC1 + ICR8 */ void writeICR(int n, int level, int priority); void writeICR(int n, int level, int priority) { unsigned char *pICR, icrvalue; icrvalue = (unsigned char) (MCF5282_INTC_ICR_IL(level) | MCF5282_INTC_ICR_IP(priority)); if (n < 64) pICR = (unsigned char *)(&__IPSBAR[0x0C40]); /* INTC0 */ else pICR = (unsigned char *)(&__IPSBAR[0x0D40 - 64]); /* INTC1 */ *(pICR + n) = icrvalue; } /* sample code - nested traps */ void trap2isrc(void); void trap3isrc(void); void trap2isrc(void) { __asm__("trap #3"); } void trap3isrc(void) { __asm__("nop"); } void _stopN(int lvl); /* Put processor in SLEEP (aka WAIT) mode */ void _sleepmode(void); void _sleepmode(void) { int level = 0; MCF5282_SCM_LPICR = MCF5282_SCM_LPICR_XLPM_IPL(level); __asm__ __volatile__("move #0x2700,%sr"); MCF5282_PMM_LPCR = MCF5282_PMM_LPCR_LPMD_WAIT + MCF5282_PMM_LPCR_STPMD(0); _stopN(level); } /* Put processor in DOZE mode */ void _dozemode(void); void _dozemode(void) { PPL_TYPE ppl; int level = 5; PUSHPPL(ppl); MCF5282_SCM_LPICR = MCF5282_SCM_LPICR_XLPM_IPL(level); __asm__ __volatile__("move #0x2700,%sr"); MCF5282_PMM_LPCR = MCF5282_PMM_LPCR_LPMD_DOZE + MCF5282_PMM_LPCR_STPMD(0); _stopN(level); POPPPL(ppl); } /* Put processor in STOP mode THIS IS TRICKY SINCE SDRAM Controller needs re-initialization AND NO accesses to SDRAM in interrupt code until after re-init. */ void _stopmode(void); void _stopmode(void) { int level = 0; MCF5282_SCM_LPICR = MCF5282_SCM_LPICR_ENBSTOP | MCF5282_SCM_LPICR_XLPM_IPL(level); __asm__ __volatile__("move #0x2700,%sr"); MCF5282_PMM_LPCR = MCF5282_PMM_LPCR_LPMD_STOP + MCF5282_PMM_LPCR_STPMD(0); _stopN(level); } /* stop processor in supervisor mode at level N (0...7) */ void _stopN(int lvl); void _stopN(int lvl) { int level = lvl; __asm__ __volatile__( "move.l %[level],%%d0 \n\t" "andi.l #0x0007,%%d0 \n\t" "beq.s stop0 \n\t" "cmp.l #1,%%d0 \n\t" "beq.s stop1 \n\t" "cmp.l #2,%%d0 \n\t" "beq.s stop2 \n\t" "cmp.l #3,%%d0 \n\t" "beq.s stop3 \n\t" "cmp.l #4,%%d0 \n\t" "beq.s stop4 \n\t" "cmp.l #5,%%d0 \n\t" "beq.s stop5 \n\t" "cmp.l #6,%%d0 \n\t" "beq.s stop6 \n" "stop7: \n\t" "stop #0x2700 \n\t" "bra end_stop \n" "stop6: \n\t" "stop #0x2600 \n\t" "bra end_stop \n" "stop5: \n\t" "stop #0x2500 \n\t" "bra end_stop \n" "stop4: \n\t" "stop #0x2400 \n\t" "bra end_stop \n" "stop3: \n\t" "stop #0x2300 \n\t" "bra end_stop \n" "stop2: \n\t" "stop #0x2200 \n\t" "bra end_stop \n" "stop1: \n\t" "stop #0x2100 \n\t" "bra end_stop \n" "stop0:stop #0x2000 \n" "end_stop: \n" : : [level] "d" (level) : "d0"); } /* this routine builds a STOP #0x2000+level & RTS instruction in 3 word stack area and then executes it. currently, not used by any code since MAY not be able to execute from RAM DATA space in ALL environments */ #define INSTR_STOP 0x4e72 #define INSTR_RTS 0x4e75 void dynamic_stop(int ipl); void dynamic_stop(int ipl) { unsigned short stopcode[3]; void (*p)(void); ipl &= 7; /* limit IPL to 0..7 */ stopcode[1] = (unsigned short) (ipl << 8) + 0x2000u; /* + SUPV */ stopcode[0] = INSTR_STOP; stopcode[2] = INSTR_RTS; p = (void (*)(void))&stopcode[0]; (*p)(); } void mcf5282_emac_init(void) { } void mcf5282_flash_init(void) { } void mcf5282_soft_reset(void) { MCF5282_RESET_RCR |= MCF5282_RESET_RCR_SOFTRST | MCF5282_RESET_RCR_FRCRSTOUT; } int mcf5282_abort_requested(void) { /* NOTE: This assumes reset state for all EPORT registers */ /* ABORT IRQ7 on Motorola, Avnet, and Axiom M5282EVB is active low */ #if defined(MOTOROLA_M5282EVB) || defined(AVNET_M5282EVB) || defined(AXIOM_M5282EVB) /* { */ if ( (MCF5282_EPORT_EPPDR & MCF5282_EPORT_EPPDR_EPPD7) == 0x00) return 1; #endif /* } MOTOROLA_M5282EVB || AVNET_M5282EVB || AXIOM_M5282EVB */ return 0; } void mcf5282_can_init(void) { /* to be defined */ } void mcf5282_fec_init(void) { /* Enable FEC Rx Frame interrupts to ColdFire core */ if(checkICR(27, FEC_LEVEL, FEC_PRIORITY)) __asm__("halt"); MCF5282_INTC0_ICR27 = MCF5282_INTC_ICR_IL(FEC_LEVEL) | MCF5282_INTC_ICR_IP(FEC_PRIORITY); /* Set FEC Interrupt Mask Register */ MCF5282_INTC0_IMRL &= (unsigned long) ~(MCF5282_INTC_IMRL_INT27 | MCF5282_INTC_IMRL_MASKALL); } /* end of file - sysinit.c */