blob: c0b417560714c7dac8027d194f8a3854117d6620 [file] [log] [blame]
/*
* 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
******************************************************************************/