/* * Copyright (c) 2015, Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * o Neither the name of Freescale Semiconductor, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "ccm_analog_imx6sx.h" /******************************************************************************* * Code ******************************************************************************/ /*FUNCTION********************************************************************** * * Function Name : CCM_ANALOG_PowerUpPll * Description : Power up PLL. * *END**************************************************************************/ void CCM_ANALOG_PowerUpPll(CCM_ANALOG_Type * base, uint32_t pllControl) { /* Judge PLL_USB1 and PLL_USB2 according to register offset value. Because the definition of power control bit is different from the other PLL.*/ if((CCM_ANALOG_TUPLE_OFFSET(pllControl) == 0x10) || (CCM_ANALOG_TUPLE_OFFSET(pllControl) == 0x20)) CCM_ANALOG_TUPLE_REG_SET(base, pllControl) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllControl); else CCM_ANALOG_TUPLE_REG_CLR(base, pllControl) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllControl); } /*FUNCTION********************************************************************** * * Function Name : CCM_ANALOG_PowerDownPll * Description : Power down PLL. * *END**************************************************************************/ void CCM_ANALOG_PowerDownPll(CCM_ANALOG_Type * base, uint32_t pllControl) { /* Judge PLL_USB1 and PLL_USB2 according to register offset value. Because the definition of power control bit is different from the other PLL.*/ if((CCM_ANALOG_TUPLE_OFFSET(pllControl) == 0x10) || (CCM_ANALOG_TUPLE_OFFSET(pllControl) == 0x20)) CCM_ANALOG_TUPLE_REG_CLR(base, pllControl) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllControl); else CCM_ANALOG_TUPLE_REG_SET(base, pllControl) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllControl); } /*FUNCTION********************************************************************** * * Function Name : CCM_ANALOG_SetPllBypass * Description : PLL bypass setting. * *END**************************************************************************/ void CCM_ANALOG_SetPllBypass(CCM_ANALOG_Type * base, uint32_t pllControl, bool bypass) { if(bypass) CCM_ANALOG_TUPLE_REG_SET(base, pllControl) = CCM_ANALOG_PLL_ARM_BYPASS_MASK; else CCM_ANALOG_TUPLE_REG_CLR(base, pllControl) = CCM_ANALOG_PLL_ARM_BYPASS_MASK; } /*FUNCTION********************************************************************** * * Function Name : CCM_ANALOG_GetPllFreq * Description : Get PLL frequency * *END**************************************************************************/ uint32_t CCM_ANALOG_GetPllFreq(CCM_ANALOG_Type * base, uint32_t pllControl) { uint8_t divSelect; float numerator, denomitor; uint32_t hz = 0; if (CCM_ANALOG_IsPllBypassed(base, pllControl)) return 24000000; switch(CCM_ANALOG_TUPLE_OFFSET(pllControl)) { /* Get PLL_ARM frequency. */ case 0x0: { divSelect = CCM_ANALOG_PLL_ARM & CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK; hz = 24000000 * divSelect / 2; break; } /* Get PLL_USB1(PLL3) frequency. */ case 0x10: { divSelect = CCM_ANALOG_PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK; if(divSelect == 0) hz = 480000000; else if(divSelect == 1) hz = 528000000; break; } /* Get PLL_USB2 frequency. */ case 0x20: { divSelect = CCM_ANALOG_PLL_USB2 & CCM_ANALOG_PLL_USB2_DIV_SELECT_MASK; if(divSelect == 0) hz = 480000000; else if(divSelect == 1) hz = 528000000; break; } /* Get PLL_SYS(PLL2) frequency. */ case 0x30: { divSelect = CCM_ANALOG_PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK; if(divSelect == 0) hz = 480000000; else hz = 528000000; break; } /* Get PLL_AUDIO frequency. */ case 0x70: { divSelect = CCM_ANALOG_PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK; numerator = CCM_ANALOG_PLL_AUDIO_NUM & CCM_ANALOG_PLL_AUDIO_NUM_A_MASK; denomitor = CCM_ANALOG_PLL_AUDIO_DENOM & CCM_ANALOG_PLL_AUDIO_DENOM_B_MASK; hz = (uint32_t)(24000000 * (divSelect + (numerator / denomitor))); break; } /* Get PLL_VIDEO frequency. */ case 0xA0: { divSelect = CCM_ANALOG_PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK; numerator = CCM_ANALOG_PLL_VIDEO_NUM & CCM_ANALOG_PLL_VIDEO_NUM_A_MASK; denomitor = CCM_ANALOG_PLL_VIDEO_DENOM & CCM_ANALOG_PLL_VIDEO_DENOM_B_MASK; hz = (uint32_t)(24000000 * (divSelect + (numerator / denomitor))); break; } } return hz; } /*FUNCTION********************************************************************** * * Function Name : CCM_ANALOG_GetPfdFreq * Description : Get PFD frequency * *END**************************************************************************/ uint32_t CCM_ANALOG_GetPfdFreq(CCM_ANALOG_Type * base, uint32_t pfdFrac) { uint32_t main, frac; /* Judge whether pfdFrac is PLL2 PFD or not. */ if(CCM_ANALOG_TUPLE_OFFSET(pfdFrac) == 0x100) { /* PFD should work with PLL2 without bypass */ assert(!CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllSysControl)); main = CCM_ANALOG_GetPllFreq(base, ccmAnalogPllSysControl); } else if(CCM_ANALOG_TUPLE_OFFSET(pfdFrac) == 0xF0) { /* PFD should work with PLL3 without bypass */ assert(!CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllUsb1Control)); main = CCM_ANALOG_GetPllFreq(base, ccmAnalogPllUsb1Control); } else main = 0; frac = CCM_ANALOG_GetPfdFrac(base, pfdFrac); return main / frac * 18; } /******************************************************************************* * EOF ******************************************************************************/