float32 IfxScuCcu_setSriFrequency(float32 sriFreq) { float32 freq = 0; float32 source = IfxScuCcu_getSourceFrequency(); Ifx_SCU_CCUCON0 ccucon0; uint16 l_SEndInitPW; uint32 sriDiv = (uint32)__roundf(source / sriFreq); sriDiv = __maxu(sriDiv, 1); if ((sriDiv >= 7) && (sriDiv < 14) && ((sriDiv & 1) == 1)) { sriDiv = sriDiv - 1; } if (sriDiv == 14) { sriDiv = 12; } l_SEndInitPW = IfxScuWdt_getSafetyWatchdogPassword(); IfxScuWdt_clearSafetyEndinit(l_SEndInitPW); ccucon0.U = SCU_CCUCON0.U; ccucon0.B.SRIDIV = sriDiv; ccucon0.B.UP = 1; SCU_CCUCON0.U = ccucon0.U; IfxScuWdt_setSafetyEndinit(l_SEndInitPW); while (SCU_CCUCON0.B.LCK != 0U) {} freq = IfxScuCcu_getSriFrequency(); return freq; }
float32 IfxScuCcu_setGtmFrequency(float32 gtmFreq) { uint16 l_SEndInitPW; Ifx_SCU_CCUCON1 ccucon1 = SCU_CCUCON1; float32 inputFreq = IfxScuCcu_getSourceFrequency(); uint32 gtmDiv = (uint32)__roundf(inputFreq / gtmFreq); gtmDiv = __maxu(gtmDiv, 1); /*gtmDiv = gtmDiv & 0x2U;*//* only even dividers */ if ((gtmDiv >= 7) && (gtmDiv < 14) && ((gtmDiv & 1) == 1)) { gtmDiv = gtmDiv - 1; } if (gtmDiv == 14) { gtmDiv = 12; } l_SEndInitPW = IfxScuWdt_getSafetyWatchdogPassword(); IfxScuWdt_clearSafetyEndinit(l_SEndInitPW); ccucon1.B.GTMDIV = gtmDiv; ccucon1.B.UP = 1U; SCU_CCUCON1.U = ccucon1.U; IfxScuWdt_setSafetyEndinit(l_SEndInitPW); return IfxScuCcu_getGtmFrequency(); }
float32 IfxScuCcu_setPll2ErayFrequency(float32 pll2ErayFreq) { uint16 password = IfxScuWdt_getSafetyWatchdogPassword(); uint32 pll2Div = (uint32)((IfxScuCcu_getPllErayVcoFrequency() / pll2ErayFreq) - 1); { IfxScuWdt_clearSafetyEndinit(password); SCU_PLLERAYCON1.B.K3DIV = pll2Div; IfxScuWdt_setSafetyEndinit(password); } return IfxScuCcu_getPll2ErayFrequency(); }
float32 IfxScuCcu_setPll2Frequency(float32 pll2Freq) { uint16 endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword(); uint32 pll2Div = (uint32)((IfxScuCcu_getPllVcoFrequency() / pll2Freq) - 1); { IfxScuWdt_clearSafetyEndinit(endinitSfty_pw); SCU_PLLCON1.B.K3DIV = pll2Div; IfxScuWdt_setSafetyEndinit(endinitSfty_pw); } return IfxScuCcu_getPll2Frequency(); }
float32 IfxScuCcu_setCpuFrequency(IfxCpu_ResourceCpu cpu, float32 cpuFreq) { uint16 endinitSfty_pw; float32 sriFreq; uint32 cpuDiv; sriFreq = IfxScuCcu_getSriFrequency(); if (cpuFreq >= sriFreq) { cpuDiv = 0; } else { cpuDiv = (uint32)((cpuFreq * 64) / sriFreq); } endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword(); { IfxScuWdt_clearSafetyEndinit(endinitSfty_pw); switch (cpu) { case IfxCpu_ResourceCpu_0: SCU_CCUCON6.U = cpuDiv; break; case IfxCpu_ResourceCpu_1: SCU_CCUCON7.U = cpuDiv; break; case IfxCpu_ResourceCpu_2: SCU_CCUCON8.U = cpuDiv; break; default: break; } IfxScuWdt_setSafetyEndinit(endinitSfty_pw); } if (cpuDiv != 0) { sriFreq = sriFreq * (cpuDiv / 64); } return sriFreq; }
float32 IfxScuCcu_setSpbFrequency(float32 spbFreq) { /* TODO: check whether it is necessary to disable trap and/or the safety */ uint16 l_EndInitPW; uint16 l_SEndInitPW; Ifx_SCU_CCUCON0 ccucon0; float32 inputFreq = IfxScuCcu_getSourceFrequency(); uint32 spbDiv = (uint32)(inputFreq / spbFreq); spbDiv = __maxu(spbDiv, 2); if ((spbDiv >= 7) && (spbDiv < 14) && ((spbDiv & 1) == 1)) { spbDiv = spbDiv - 1; } if (spbDiv == 14) { spbDiv = 12; } l_EndInitPW = IfxScuWdt_getCpuWatchdogPassword(); l_SEndInitPW = IfxScuWdt_getSafetyWatchdogPassword(); IfxScuWdt_clearCpuEndinit(l_EndInitPW); SCU_TRAPDIS.U = SCU_TRAPDIS.U | 0x3E0U; IfxScuWdt_setCpuEndinit(l_EndInitPW); IfxScuWdt_clearSafetyEndinit(l_SEndInitPW); ccucon0.U = SCU_CCUCON0.U; ccucon0.B.SPBDIV = spbDiv; ccucon0.B.UP = 1; SCU_CCUCON0.U = ccucon0.U; IfxScuWdt_setSafetyEndinit(l_SEndInitPW); IfxScuWdt_clearCpuEndinit(l_EndInitPW); SCU_TRAPDIS.U = SCU_TRAPDIS.U & (uint32)~0x3E0UL; IfxScuWdt_setCpuEndinit(l_EndInitPW); while (SCU_CCUCON0.B.LCK != 0U) {} return IfxScuCcu_getSpbFrequency(); }
boolean IfxCpu_setCoreMode(Ifx_CPU *cpu, IfxCpu_CoreMode mode) { // this switch is only temporary required // once the IfxCan driver is generated via lldgen, we will vary the code without #ifdef #ifdef IFX_TC27x /* FIXME Copied from old TC27xA code, check that this is up to date code */ IfxCpu_CoreMode cpuMode; boolean RetVal; IfxScu_PMCSR_REQSLP modeSet; RetVal = TRUE; modeSet = IfxScu_PMCSR_REQSLP_Idle; /* Check the mode the CPU is in */ cpuMode = IfxCpu_getCoreMode(cpu); /* if requested mode is same as current mode nothing to do */ if (cpuMode != mode) { /* transition from halt to Run */ if (IfxCpu_CoreMode_halt == cpuMode) { if (IfxCpu_CoreMode_run == mode) { Ifx_CPU_DBGSR dbgsr; if (IfxCpu_getCoreId() != IfxCpu_getIndex(cpu)) { cpu->DBGSR.B.HALT = 0x2; } else { dbgsr.U = __mfcr(CPU_DBGSR); dbgsr.B.HALT = 0x2; __mtcr(CPU_DBGSR, dbgsr.U); } } else /* cannot go to any other mode e.g. IfxCpu_CoreMode_idle */ { RetVal = FALSE; } } /* From Run to Idle or vice versa */ else { if (IfxCpu_CoreMode_run == cpuMode) { if (IfxCpu_CoreMode_idle == mode) { modeSet = IfxScu_PMCSR_REQSLP_Idle; } else { RetVal = FALSE; } } /* idle to Run */ else if (IfxCpu_CoreMode_idle == cpuMode) { if (IfxCpu_CoreMode_run == mode) { modeSet = IfxScu_PMCSR_REQSLP_Run; } else { RetVal = FALSE; } } else { RetVal = FALSE; } if (TRUE == RetVal) { /* To take care of the Work Around in A step * In A Step the PMCSR is Cpu Endinit protected * in B step it is by safety endinit*/ uint16 password; uint32 wdtCon0_Val; Ifx_SCU_WDTCPU *watchdog; watchdog = &MODULE_SCU.WDTCPU[IfxCpu_getCoreId()]; /* FIXME access to the watchdog of an other CPU, this might not work! */ password = IfxScuWdt_getCpuWatchdogPassword(); IfxScuWdt_clearCpuEndinit(password); /* password access */ watchdog->CON0.U = (password << 2U) | 0x1U; /* modify access, E=0 */ watchdog->CON0.U = (password << 2U) | 0x2U; /* password access in advance */ watchdog->CON0.U = (password << 2U) | 0x1U; /* prepare write value */ wdtCon0_Val = ((0x0000U) << 16U) | (password << 2U) | (0x3U); MODULE_SCU.PMCSR[(uint32)IfxCpu_getIndex(cpu)].B.REQSLP = modeSet; /* modify access, E=1, reload WDT */ watchdog->CON0.U = wdtCon0_Val; IfxScuWdt_setCpuEndinit(password); } } } return RetVal; #else uint8 reqslp; boolean retValue; IfxCpu_ResourceCpu index = IfxCpu_getIndex(cpu); /*Modes such as HALT, SLEEP and STBY are not handled at CPU level */ retValue = ((mode == IfxCpu_CoreMode_halt) || (mode == IfxCpu_CoreMode_sleep) || (mode == IfxCpu_CoreMode_stby)) ? FALSE : TRUE; reqslp = (mode == IfxCpu_CoreMode_idle) ? IfxScu_PMCSR_REQSLP_Idle : IfxScu_PMCSR_REQSLP_Run; if (retValue == TRUE) { /*Check if the same core is requesting to change the core run mode */ if (IfxCpu_getCoreId() != index) { /*Request is for the other core */ /*To access PMCSR of other CPUs handle the safety EndInit protection */ uint16 safetyWdtPw = IfxScuWdt_getSafetyWatchdogPassword(); IfxScuWdt_clearSafetyEndinit(safetyWdtPw); MODULE_SCU.PMCSR[(uint32)IfxCpu_getIndex(cpu)].B.REQSLP = reqslp; IfxScuWdt_setSafetyEndinit(safetyWdtPw); cpu->DBGSR.B.HALT = 2; /*reset the HALT bit, if it is already done it is no harm in writing again */ } else { /*Request is for self, this request normally only for halt, otherwise the core is already running anyway! */ /*To access PMCSR of self handle the cpu EndInit protection */ uint16 cpuWdtPw = IfxScuWdt_getCpuWatchdogPassword(); IfxScuWdt_clearCpuEndinit(cpuWdtPw); MODULE_SCU.PMCSR[(uint32)index].B.REQSLP = reqslp; IfxScuWdt_setCpuEndinit(cpuWdtPw); } } return retValue; #endif }
boolean IfxScuCcu_initErayPll(const IfxScuCcu_ErayPllConfig *cfg) { uint8 smuTrapEnable; uint16 endinit_pw, endinitSfty_pw; boolean status = 0; endinit_pw = IfxScuWdt_getCpuWatchdogPassword(); endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword(); { /* Disable TRAP for SMU (oscillator watchdog and unlock detection) */ IfxScuWdt_clearCpuEndinit(endinit_pw); smuTrapEnable = SCU_TRAPDIS.B.SMUT; SCU_TRAPDIS.B.SMUT = 1U; IfxScuWdt_setCpuEndinit(endinit_pw); } IfxScuWdt_clearSafetyEndinit(endinitSfty_pw); // ensure that PLL enabled if (!SCU_PLLERAYCON0.B.PLLPWD || SCU_PLLERAYCON0.B.VCOPWD || SCU_PLLERAYSTAT.B.PWDSTAT) { // PLLPWD=0 or VCOPWD=1 or PWDSTAT=1? // enable PLL and leave power saving mode SCU_PLLERAYCON0.B.PLLPWD = 1; SCU_PLLERAYCON0.B.VCOPWD = 0; while (SCU_PLLERAYSTAT.B.PWDSTAT) // poll PWDSTAT {} /*Wait for waitCounter corresponding to the pll step */ IfxScuCcu_wait(cfg->pllInitialStep.waitTime); } /* Enter Prescalar mode */ /* Update K and N dividers */ if (!SCU_PLLERAYSTAT.B.VCOBYST) // checking PLLERAYBYPST flag { // select "secure" K1 value - please check @silicon if K1=4 is ok while (!SCU_PLLERAYSTAT.B.K1RDY) // poll K1RDY before changing K {} SCU_PLLERAYCON1.B.K1DIV = 3; // activate VCO bypass (bit 0: VCOBYP=1) SCU_PLLERAYCON0.B.VCOBYP = 1; } while (!SCU_PLLERAYSTAT.B.K2RDY) // poll K1RDY before changing K {} SCU_PLLERAYCON1.B.K2DIV = cfg->pllInitialStep.k2Initial; SCU_PLLERAYCON0.B.PDIV = cfg->pllInitialStep.pDivider; SCU_PLLERAYCON0.B.NDIV = cfg->pllInitialStep.nDivider; /* * RESLD = 1 ==> Restart VCO lock detection * CLRFINDIS = 1 ==> Connect OSC to PLL * PLLPWD = 1 ==> PLL Power Saving Mode : Normal behaviour * NDIV = NDIV */ SCU_PLLERAYCON0.B.RESLD = 1U; SCU_PLLERAYCON0.B.CLRFINDIS = 1U; IfxScuWdt_setSafetyEndinit(endinitSfty_pw); // Wait until VCO LOCK bit is set uint32 time_out_ctr = 50000; // higher time out value as for clib_pll, since system is clocked much faster while polling the lock flag while (--time_out_ctr && !SCU_PLLERAYSTAT.B.VCOLOCK) {} // check for timeout, exit immediately (don't disable VCO bypass) of not locked if (!time_out_ctr) { status = FALSE; } IfxScuWdt_clearSafetyEndinit(endinitSfty_pw); /*Bypass VCO*/ SCU_PLLERAYCON0.B.VCOBYP = 0U; // wait until bypass has been deactivated while (SCU_PLLERAYSTAT.B.VCOBYST) // poll VCOBYST {} if (!SCU_PLLERAYSTAT.B.VCOLOCK) { status = FALSE; } IfxScuWdt_setSafetyEndinit(endinitSfty_pw); { /* Enable VCO unlock Trap if it was disabled before */ IfxScuWdt_clearCpuEndinit(endinit_pw); SCU_TRAPCLR.B.SMUT = 1U; SCU_TRAPDIS.B.SMUT = smuTrapEnable; IfxScuWdt_setCpuEndinit(endinit_pw); } return status; }
boolean IfxScuCcu_init(const IfxScuCcu_Config *cfg) { uint8 smuTrapEnable; uint16 endinit_pw, endinitSfty_pw; boolean status = 0; endinit_pw = IfxScuWdt_getCpuWatchdogPassword(); endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPassword(); { /* Disable TRAP for SMU (oscillator watchdog and unlock detection) */ IfxScuWdt_clearCpuEndinit(endinit_pw); smuTrapEnable = SCU_TRAPDIS.B.SMUT; SCU_TRAPDIS.B.SMUT = 1U; IfxScuWdt_setCpuEndinit(endinit_pw); } { /* Select fback (fosc-evr) as CCU input clock */ IfxScuWdt_clearSafetyEndinit(endinitSfty_pw); while (SCU_CCUCON0.B.LCK != 0U) { /*Wait till ccucon0 lock is set */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } SCU_CCUCON0.B.CLKSEL = 0; /*Select the EVR as fOSC for the clock distribution */ SCU_CCUCON0.B.UP = 1; /*Update the ccucon0 register */ /* Disconnet PLL (SETFINDIS=1): oscillator clock is disconnected from PLL */ SCU_PLLCON0.B.SETFINDIS = 1; /* Now PLL is in free running mode */ /* Select Clock Source as PLL input clock */ while (SCU_CCUCON0.B.LCK != 0U) { /*Wait till ccucon0 lock is set */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } SCU_CCUCON1.B.INSEL = 1; /*Select oscillator OSC0 as clock to PLL */ SCU_CCUCON1.B.UP = 1; /*Update the ccucon0 register */ status |= IfxScuCcu_isOscillatorStable(); IfxScuWdt_setSafetyEndinit(endinitSfty_pw); } if (status == 0) { /*Start the PLL configuration sequence */ uint8 pllStepsCount; /*Setting up P N and K2 values equate pll to evr osc freq */ { { /*Set the K2 divider value for the step corresponding to step count */ IfxScuWdt_clearSafetyEndinit(endinitSfty_pw); while (SCU_PLLSTAT.B.K2RDY == 0U) { /*Wait until K2 divider is ready */ /*No "timeout" required because Safety Endinit will give a trap */ } SCU_PLLCON1.B.K2DIV = cfg->sysPll.pllInitialStep.k2Initial; { /*change P and N divider values */ SCU_PLLCON0.B.PDIV = cfg->sysPll.pllInitialStep.pDivider; SCU_PLLCON0.B.NDIV = cfg->sysPll.pllInitialStep.nDivider; /* Disable oscillator disconnect feature * in case of PLL unlock, PLL stays connected to fref */ SCU_PLLCON0.B.OSCDISCDIS = 1; /* Connect PLL to fREF as oscillator clock is connected to PLL */ SCU_PLLCON0.B.CLRFINDIS = 1; /* Restart PLL lock detection (RESLD = 1) */ SCU_PLLCON0.B.RESLD = 1; IfxScuCcu_wait(0.000050F); /*Wait for 50us */ while (SCU_PLLSTAT.B.VCOLOCK == 0U) { /* Wait for PLL lock */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } SCU_PLLCON0.B.VCOBYP = 0; /*VCO bypass disabled */ while (SCU_CCUCON0.B.LCK != 0U) { /*Wait till ccucon registers can be written with new value */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } SCU_CCUCON0.B.CLKSEL = 0x01; /*Configure the clock distribution */ while (SCU_CCUCON0.B.LCK != 0U) { /*Wait till ccucon registers can be written with new value */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } /*Wait until the initial clock configurations take in to effect for the PLL*/ IfxScuCcu_wait(cfg->sysPll.pllInitialStep.waitTime); /*Wait for configured initial time */ { /*Write CCUCON0 configuration */ Ifx_SCU_CCUCON0 ccucon0; ccucon0.U = SCU_CCUCON0.U & ~cfg->clockDistribution.ccucon0.mask; /*update with configured value */ ccucon0.U |= (cfg->clockDistribution.ccucon0.mask & cfg->clockDistribution.ccucon0.value); ccucon0.B.CLKSEL = 0x01; /* Select fpll as CCU input clock, even if this was not selected by configuration */ ccucon0.B.UP = 1; SCU_CCUCON0 = ccucon0; /*Set update bit explicitly to make above configurations effective */ } while (SCU_CCUCON1.B.LCK != 0U) { /*Wait till ccucon registers can be written with new value */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } { /*Write CCUCON1 configuration */ Ifx_SCU_CCUCON1 ccucon1; ccucon1.U = SCU_CCUCON1.U & ~cfg->clockDistribution.ccucon1.mask; /*update with configured value */ ccucon1.U |= (cfg->clockDistribution.ccucon1.mask & cfg->clockDistribution.ccucon1.value); ccucon1.B.INSEL = 1; ccucon1.B.UP = 1; SCU_CCUCON1 = ccucon1; } while (SCU_CCUCON2.B.LCK != 0U) { /*Wait till ccucon registers can be written with new value */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } { /*Write CCUCON2 configuration */ Ifx_SCU_CCUCON2 ccucon2; ccucon2.U = SCU_CCUCON2.U & ~cfg->clockDistribution.ccucon2.mask; /*update with configured value */ ccucon2.U |= (cfg->clockDistribution.ccucon2.mask & cfg->clockDistribution.ccucon2.value); ccucon2.B.UP = 1; SCU_CCUCON2 = ccucon2; } while (SCU_CCUCON5.B.LCK != 0U) { /*Wait till ccucon registers can be written with new value */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } { /*Write CCUCON5 configuration */ Ifx_SCU_CCUCON5 ccucon5; ccucon5.U = SCU_CCUCON5.U & ~cfg->clockDistribution.ccucon5.mask; /*update with configured value */ ccucon5.U |= (cfg->clockDistribution.ccucon5.mask & cfg->clockDistribution.ccucon5.value); ccucon5.B.UP = 1; SCU_CCUCON5 = ccucon5; } { /*Write CCUCON6 configuration */ Ifx_SCU_CCUCON6 ccucon6; ccucon6.U = SCU_CCUCON6.U & ~cfg->clockDistribution.ccucon6.mask; /*update with configured value */ ccucon6.U |= (cfg->clockDistribution.ccucon6.mask & cfg->clockDistribution.ccucon6.value); SCU_CCUCON6 = ccucon6; } { /*Write CCUCON7 configuration */ Ifx_SCU_CCUCON7 ccucon7; ccucon7.U = SCU_CCUCON7.U & ~cfg->clockDistribution.ccucon7.mask; /*update with configured value */ ccucon7.U |= (cfg->clockDistribution.ccucon7.mask & cfg->clockDistribution.ccucon7.value); SCU_CCUCON7 = ccucon7; } { /*Write CCUCON8 configuration */ Ifx_SCU_CCUCON8 ccucon8; ccucon8.U = SCU_CCUCON8.U & ~cfg->clockDistribution.ccucon8.mask; /*update with configured value */ ccucon8.U |= (cfg->clockDistribution.ccucon8.mask & cfg->clockDistribution.ccucon8.value); SCU_CCUCON8 = ccucon8; } } IfxScuWdt_setSafetyEndinit(endinitSfty_pw); } } { /*Write Flash waitstate configuration */ Ifx_FLASH_FCON fcon; fcon.U = FLASH0_FCON.U & ~cfg->flashFconWaitStateConfig.mask; /*update with configured value */ fcon.U &= ~cfg->flashFconWaitStateConfig.mask; fcon.U |= (cfg->flashFconWaitStateConfig.mask & cfg->flashFconWaitStateConfig.value); { IfxScuWdt_clearCpuEndinit(endinit_pw); FLASH0_FCON = fcon; IfxScuWdt_setCpuEndinit(endinit_pw); } } /*Start Pll ramp up sequence */ for (pllStepsCount = 0; pllStepsCount < cfg->sysPll.numOfPllDividerSteps; pllStepsCount++) { /*iterate through number of pll steps */ { IfxScuWdt_clearSafetyEndinit(endinitSfty_pw); /*Configure K2 divider */ while (SCU_PLLSTAT.B.K2RDY == 0U) { /*Wait until K2 divider is ready */ /*No "timeout" required, because if it hangs, Safety Endinit will give a trap */ } /*Now set the K2 divider value for the step corresponding to step count */ SCU_PLLCON1.B.K2DIV = cfg->sysPll.pllDividerStep[pllStepsCount].k2Step; IfxScuWdt_setSafetyEndinit(endinitSfty_pw); } /*call the hook function if configured */ if (cfg->sysPll.pllDividerStep[pllStepsCount].hookFunction != (IfxScuCcu_PllStepsFunctionHook)0) { cfg->sysPll.pllDividerStep[pllStepsCount].hookFunction(); } /*Wait for waitCounter corresponding to the pll step */ IfxScuCcu_wait(cfg->sysPll.pllDividerStep[pllStepsCount].waitTime); } } { /* Enable oscillator disconnect feature */ IfxScuWdt_clearSafetyEndinit(endinitSfty_pw); SCU_PLLCON0.B.OSCDISCDIS = 0U; IfxScuWdt_setSafetyEndinit(endinitSfty_pw); } { /* Enable VCO unlock Trap if it was disabled before */ IfxScuWdt_clearCpuEndinit(endinit_pw); SCU_TRAPCLR.B.SMUT = 1U; SCU_TRAPDIS.B.SMUT = smuTrapEnable; IfxScuWdt_setCpuEndinit(endinit_pw); } return status; }