422 lines
20 KiB
C
422 lines
20 KiB
C
/**
|
|
* @file fc7xxx_driver_pcc.c
|
|
* @author Flagchip
|
|
* @brief FC7xxx PCC driver type definition and API
|
|
* @version 0.1.0
|
|
* @date 2024-01-12
|
|
*
|
|
* @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd.
|
|
*
|
|
*/
|
|
|
|
/********************************************************************************
|
|
* Revision History:
|
|
*
|
|
* Version Date Initials CR# Descriptions
|
|
* --------- ---------- ------------ ---------- ---------------
|
|
* 0.1.0 2024-01-12 Flagchip085 N/A First version for FC7240
|
|
********************************************************************************/
|
|
|
|
#include "fc7xxx_driver_pcc.h"
|
|
#include "fc7xxx_driver_scg.h"
|
|
#include "fc7xxx_board_conf.h"
|
|
|
|
/***************** mcaro *********************/
|
|
/* PCC property MACRO, defines every peripheral clock system architecture */
|
|
#define PCC_CLK_NOT_APPLY (0U)
|
|
#define PCC_CGC_AVAILABLE (1U << 0U)
|
|
#define PCC_FUNCCLK_MUXDIVH_USED (1U << 1U)
|
|
#define PCC_FUNCCLK_MUXDIVM_USED (1U << 2U)
|
|
#define PCC_FUNCCLK_MUXDIVL_USED (1U << 3U)
|
|
#define PCC_FUNCCLK_MUXDIVHPIN_USED (1U << 4U)
|
|
#define PCC_MOUDULE_DIV_USED (1U << 5U)
|
|
#define PCC_CLK_DOMAIN_CORE (1U << 6U)
|
|
#define PCC_CLK_DOMAIN_BUS (1U << 7U)
|
|
#define PCC_CLK_DOMAIN_SLOW (1U << 8U)
|
|
#define PCC_DWP_SWR_AVAILABLE (0U << 9U)
|
|
|
|
#define PCC_PROPERTY_MUXDIV_MASK (PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVM_USED | PCC_FUNCCLK_MUXDIVL_USED)
|
|
#define PCC_PROPERTY_MUXDIV_ALL_MASK (PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVM_USED | PCC_FUNCCLK_MUXDIVL_USED | PCC_FUNCCLK_MUXDIVHPIN_USED)
|
|
|
|
/***************** Type define *********************/
|
|
/**
|
|
* @brief PCC clock attribution.
|
|
* @param u32RegOffset: the register offset base on PCC module base address 0x4002_4000h
|
|
* @param u8ClockProperty include clock domain and clock MUX information by bit filed setting.
|
|
*/
|
|
typedef struct
|
|
{
|
|
uint32_t u32RegOffset;
|
|
uint32_t u32ClockProperty;
|
|
} PCC_ClockMapType;
|
|
|
|
/**
|
|
* @brief PCC peripheral clock index map to SCG clock source
|
|
* @param ePccClkIndex: PCC peripheral clock index
|
|
* @param eScgClkIndex SCG clock source
|
|
*/
|
|
typedef struct
|
|
{
|
|
PCC_ClkGateSrcType ePccClkIndex;
|
|
SCG_ClkSrcType eScgClkIndex;
|
|
} PCC_ClockIndexMap;
|
|
|
|
/***************** Local Variables *********************/
|
|
/**
|
|
* @brief PCC clock index to SCG clock source map.
|
|
*/
|
|
static const PCC_ClockIndexMap s_tPccClocIndexkMap[PCC_MUX_MAX_NUMBER] = {
|
|
{PCC_CLKGATE_SRC_OFF_OR_TCLK, SCG_END_OF_CLOCKS},
|
|
{PCC_CLKGATE_SRC_FOSCDIV, SCG_FOSCDIVH_CLK},
|
|
{PCC_CLKGATE_SRC_SIRCDIV, SCG_SIRCDIVH_CLK},
|
|
{PCC_CLKGATE_SRC_FIRCDIV, SCG_FIRCDIVH_CLK},
|
|
{PCC_CLKGATE_SRC_RESERVE0, SCG_END_OF_CLOCKS},
|
|
{PCC_CLKGATE_SRC_PLL1DIV, SCG_PLL1DIVH_CLK},
|
|
{PCC_CLKGATE_SRC_PLL0DIV, SCG_PLL0DIVH_CLK},
|
|
{PCC_CLKGATE_SRC_RESERVE1, SCG_END_OF_CLOCKS}
|
|
};
|
|
|
|
/**
|
|
* @brief clock attribution map.
|
|
*/
|
|
static const PCC_ClockMapType s_tPccClockMap[PCC_END_OF_CLOCKS] =
|
|
{
|
|
{0x20, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* DMA0 */
|
|
{0x28, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* DMAMUX0 */
|
|
{0x4C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* ROMC */
|
|
{0x60, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* ERM0 */
|
|
{0x64, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* EIM0 */
|
|
{0x68, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* INTM0 */
|
|
{0x6C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* ISM0 */
|
|
{0x88, PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* WDOG0 */
|
|
{0x98, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL0 */
|
|
{0x9C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL1 */
|
|
{0xA0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL2 */
|
|
{0xA4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL3 */
|
|
{0xA8, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* CRC0 */
|
|
{0xAC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* CORDIC */
|
|
{0xB0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* TSTMP0 */
|
|
{0xB4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* TSTMP1 */
|
|
{0xB8, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_DWP_SWR_AVAILABLE}, /* FCPIT0 */
|
|
{0xBC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_FUNCCLK_MUXDIVL_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* AONTIMER0 */
|
|
{0xC0, PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* RTC */
|
|
{0xC4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU0 */
|
|
{0xC8, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU1 */
|
|
{0xCC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU2 */
|
|
{0xD0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU3 */
|
|
{0xD4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMU4 */
|
|
{0xDC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* PTIMER0 */
|
|
{0xE0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* PTIMER1 */
|
|
{0xEC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* ADC0 */
|
|
{0xF0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* ADC1 */
|
|
{0xFC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* WKU0 */
|
|
{0x100, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMP0 */
|
|
{0x104, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* CMP1 */
|
|
{0x10C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_FUNCCLK_MUXDIVL_USED | PCC_DWP_SWR_AVAILABLE}, /* TMU0 */
|
|
{0x150, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVL_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* SENT0 */
|
|
{0x160, PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* MB0 */
|
|
{0x170, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU0 */
|
|
{0x174, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU1 */
|
|
{0x178, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU2 */
|
|
{0x17C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU3 */
|
|
{0x188, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI0 */
|
|
{0x18C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI1 */
|
|
{0x190, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI2 */
|
|
{0x198, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCIIC0 */
|
|
{0x1A0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART0 */
|
|
{0x1A4, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART1 */
|
|
{0x1A8, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART2 */
|
|
{0x1AC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART3 */
|
|
{0x1C0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* LU0 */
|
|
{0x1E0, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_DWP_SWR_AVAILABLE}, /* FREQM */
|
|
{0x1FC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* STCU */
|
|
{0x200, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* FLEXCAN0 */
|
|
{0x210, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* FLEXCAN1 */
|
|
{0x34C, PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* WDOG1 */
|
|
{0x36C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL4 */
|
|
{0x370, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_SLOW | PCC_DWP_SWR_AVAILABLE}, /* TRGSEL5 */
|
|
{0x37C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI3 */
|
|
{0x380, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI4 */
|
|
{0x384, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCSPI5 */
|
|
{0x3FC, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU4 */
|
|
{0x400, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU5 */
|
|
{0x404, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU6 */
|
|
{0x408, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_FUNCCLK_MUXDIVHPIN_USED | PCC_DWP_SWR_AVAILABLE}, /* FTU7 */
|
|
{0x41C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCIIC1 */
|
|
{0x420, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART4 */
|
|
{0x424, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART5 */
|
|
{0x428, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART6 */
|
|
{0x42C, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_DWP_SWR_AVAILABLE}, /* FCUART7 */
|
|
{0x450, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVM_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* MSC0 */
|
|
{0x480, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* FLEXCAN2 */
|
|
{0x490, PCC_CGC_AVAILABLE | PCC_CLK_DOMAIN_BUS | PCC_FUNCCLK_MUXDIVH_USED | PCC_MOUDULE_DIV_USED | PCC_DWP_SWR_AVAILABLE}, /* FLEXCAN3 */
|
|
};
|
|
|
|
/***************** Local Prototype Functions *********************/
|
|
|
|
/***************** Local Functions *********************/
|
|
|
|
/***************** Global Functions *********************/
|
|
|
|
/**
|
|
* @brief get PCC function clock status and value.
|
|
*
|
|
* @param pcc_ClkSrcType eClockName: used for choose PCC clock source to query.
|
|
*/
|
|
uint32_t PCC_GetPccFunctionClock(const PCC_ClkSrcType eClockName)
|
|
{
|
|
uint32_t u32DivVal;
|
|
PCC_ClkGateSrcType eSelVal;
|
|
uint32_t u32ScgClkIndex = 0U;
|
|
uint32_t u32FunctionFreqVal = 0U;
|
|
uint32_t u32RegVal, u32ScgClkDivIndex;
|
|
const PCC_ClockMapType *pAttributeVal;
|
|
|
|
DEV_ASSERT((uint32_t)eClockName < (uint32_t)PCC_END_OF_CLOCKS);
|
|
|
|
/* Get peripheral PCC register value */
|
|
u32RegVal = PCC_HWA_GetRegister(s_tPccClockMap[(uint32_t)eClockName].u32RegOffset);
|
|
pAttributeVal = &s_tPccClockMap[(uint32_t)eClockName];
|
|
|
|
/* Check peripheral PCC is valid or not and peripheral have function clock or not */
|
|
if ((PCC_CGC_MASK == (u32RegVal & PCC_CGC_MASK)) && (0U != (pAttributeVal->u32ClockProperty & PCC_PROPERTY_MUXDIV_ALL_MASK)))
|
|
{
|
|
eSelVal = (PCC_ClkGateSrcType)((uint8_t)PCC_GetSEL(u32RegVal));
|
|
/* Get PCC divide value */
|
|
if (PCC_MOUDULE_DIV_USED == (pAttributeVal->u32ClockProperty & PCC_MOUDULE_DIV_USED))
|
|
{
|
|
u32DivVal = PCC_GetDIV(u32RegVal) + (uint32_t)1U;
|
|
}
|
|
else
|
|
{
|
|
u32DivVal = 1U;
|
|
}
|
|
|
|
/* Get peripheral function clock source which is from SCG or TCLK */
|
|
if (PCC_CLKGATE_SRC_OFF_OR_TCLK == eSelVal)
|
|
{
|
|
if (PCC_FUNCCLK_MUXDIVHPIN_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVHPIN_USED))
|
|
{
|
|
u32FunctionFreqVal = PCC_FTU_TCLK_FREQ;
|
|
}
|
|
else
|
|
{
|
|
u32FunctionFreqVal = 0U;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (PCC_FUNCCLK_MUXDIVH_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVH_USED))
|
|
{
|
|
u32ScgClkDivIndex = 0U;
|
|
}
|
|
else if (PCC_FUNCCLK_MUXDIVM_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVM_USED))
|
|
{
|
|
u32ScgClkDivIndex = 1U;
|
|
}
|
|
else if (PCC_FUNCCLK_MUXDIVL_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVL_USED))
|
|
{
|
|
u32ScgClkDivIndex = 2U;
|
|
}
|
|
else
|
|
{
|
|
u32ScgClkDivIndex = 0U;
|
|
}
|
|
u32ScgClkIndex = (uint32_t)s_tPccClocIndexkMap[eSelVal].eScgClkIndex + u32ScgClkDivIndex;
|
|
}
|
|
|
|
/* If clock source is valid, calculate peripheral function clock */
|
|
if (u32ScgClkIndex < (uint32_t)SCG_END_OF_CLOCKS)
|
|
{
|
|
u32FunctionFreqVal = SCG_GetScgClockFreq((SCG_ClkSrcType)u32ScgClkIndex) / u32DivVal;
|
|
}
|
|
}
|
|
|
|
return u32FunctionFreqVal;
|
|
}
|
|
|
|
/**
|
|
* @brief get PCC interface clock status and value.
|
|
*
|
|
* @param pcc_ClkSrcType eClockName: used for choose PCC clock source to query.
|
|
*/
|
|
uint32_t PCC_GetPccInterfaceClock(const PCC_ClkSrcType eClockName)
|
|
{
|
|
uint32_t u32InterfaceFreqVal, u32AttributeVal;
|
|
|
|
DEV_ASSERT((uint32_t)eClockName < (uint32_t)PCC_END_OF_CLOCKS);
|
|
|
|
u32AttributeVal = s_tPccClockMap[(uint32_t)eClockName].u32ClockProperty;
|
|
if (PCC_CLK_DOMAIN_BUS == (u32AttributeVal & PCC_CLK_DOMAIN_BUS))
|
|
{
|
|
u32InterfaceFreqVal = SCG_GetScgClockFreq(SCG_BUS_CLK);
|
|
}
|
|
else if (PCC_CLK_DOMAIN_SLOW == (u32AttributeVal & PCC_CLK_DOMAIN_SLOW))
|
|
{
|
|
u32InterfaceFreqVal = SCG_GetScgClockFreq(SCG_SLOW_CLK);
|
|
}
|
|
else
|
|
{
|
|
u32InterfaceFreqVal = 0U;
|
|
}
|
|
|
|
return u32InterfaceFreqVal;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief set PCC one peripheral clock configuration.
|
|
*
|
|
* @param PCC_CtrlType* pConfig: the PCC initialize value point set by user.
|
|
* @return PCC_StatusType pcc function status
|
|
*/
|
|
PCC_StatusType PCC_SetPcc(const PCC_CtrlType *const pConfig)
|
|
{
|
|
PCC_StatusType eStatus = PCC_STATUS_SUCCESS;
|
|
uint32_t u32DivVal;
|
|
uint32_t u32ScgClkIndex = 0U, u32ScgClkDivIndex;
|
|
uint32_t u32FreqVal = 0U;
|
|
uint32_t u32FunctionFreqVal = 0U;
|
|
uint32_t u32RegVal = 0U;
|
|
uint32_t u32ExpectedRegVal;
|
|
const PCC_ClockMapType *pAttributeVal;
|
|
|
|
DEV_ASSERT(NULL_PTR != pConfig);
|
|
DEV_ASSERT((uint32_t)pConfig->eClockName < (uint32_t)PCC_END_OF_CLOCKS);
|
|
|
|
pAttributeVal = &s_tPccClockMap[(uint32_t)pConfig->eClockName];
|
|
/* check peripheral clock domain to calculate module clock */
|
|
if (PCC_CLK_DOMAIN_BUS == (pAttributeVal->u32ClockProperty & PCC_CLK_DOMAIN_BUS))
|
|
{
|
|
u32FreqVal = SCG_GetScgClockFreq(SCG_BUS_CLK);
|
|
}
|
|
else if (PCC_CLK_DOMAIN_SLOW == (pAttributeVal->u32ClockProperty & PCC_CLK_DOMAIN_SLOW))
|
|
{
|
|
u32FreqVal = SCG_GetScgClockFreq(SCG_SLOW_CLK);
|
|
}
|
|
else
|
|
{
|
|
/* Do nothing */
|
|
}
|
|
|
|
if (0U == u32FreqVal)
|
|
{
|
|
/* Please call SCG function first */
|
|
eStatus = PCC_STATUS_CLOCK_INVALID;
|
|
}
|
|
|
|
if (PCC_STATUS_SUCCESS == eStatus)
|
|
{
|
|
/* Disable PCC gate */
|
|
PCC_HWA_SetClockGateControl(pAttributeVal->u32RegOffset,false);
|
|
if (pConfig->bEn)
|
|
{
|
|
if (PCC_MOUDULE_DIV_USED == (pAttributeVal->u32ClockProperty & PCC_MOUDULE_DIV_USED))
|
|
{
|
|
u32DivVal = (uint32_t)pConfig->eDivider + (uint32_t)1U;
|
|
u32RegVal |= PCC_DIV(pConfig->eDivider);
|
|
}
|
|
else
|
|
{
|
|
u32DivVal = 1U;
|
|
}
|
|
|
|
if (0U != (pAttributeVal->u32ClockProperty & PCC_PROPERTY_MUXDIV_ALL_MASK))
|
|
{
|
|
u32RegVal |= PCC_SEL(pConfig->eClkSrc);
|
|
}
|
|
|
|
if (PCC_CGC_AVAILABLE == (pAttributeVal->u32ClockProperty & PCC_CGC_AVAILABLE))
|
|
{
|
|
/* Enable peripheral clock */
|
|
u32RegVal |= PCC_CGC_MASK;
|
|
}
|
|
|
|
/* Configure PCC register */
|
|
PCC_HWA_SetRegister(pAttributeVal->u32RegOffset,u32RegVal);
|
|
|
|
/* Get peripheral function clock source which is from SCG or TCLK */
|
|
if (PCC_CLKGATE_SRC_OFF_OR_TCLK == pConfig->eClkSrc)
|
|
{
|
|
if (PCC_FUNCCLK_MUXDIVHPIN_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVHPIN_USED))
|
|
{
|
|
u32FunctionFreqVal = PCC_FTU_TCLK_FREQ;
|
|
}
|
|
else
|
|
{
|
|
u32FunctionFreqVal = 0U;
|
|
}
|
|
}
|
|
else if (PCC_CLKGATE_UNINVOLVED == pConfig->eClkSrc)
|
|
{
|
|
/* do nothing */
|
|
}
|
|
else
|
|
{
|
|
if (PCC_FUNCCLK_MUXDIVH_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVH_USED))
|
|
{
|
|
u32ScgClkDivIndex = 0U;
|
|
}
|
|
else if (PCC_FUNCCLK_MUXDIVM_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVM_USED))
|
|
{
|
|
u32ScgClkDivIndex = 1U;
|
|
}
|
|
else if (PCC_FUNCCLK_MUXDIVL_USED == (pAttributeVal->u32ClockProperty & PCC_FUNCCLK_MUXDIVL_USED))
|
|
{
|
|
u32ScgClkDivIndex = 2U;
|
|
}
|
|
else
|
|
{
|
|
u32ScgClkDivIndex = 0U;
|
|
}
|
|
u32ScgClkIndex = (uint32_t)s_tPccClocIndexkMap[(uint32_t)pConfig->eClkSrc].eScgClkIndex + u32ScgClkDivIndex;
|
|
}
|
|
|
|
/* Calculate peripheral function clock */
|
|
if (u32ScgClkIndex < (uint32_t)SCG_END_OF_CLOCKS)
|
|
{
|
|
u32FunctionFreqVal = SCG_GetScgClockFreq((SCG_ClkSrcType)u32ScgClkIndex) / u32DivVal;
|
|
}
|
|
u32ExpectedRegVal = u32RegVal;
|
|
}
|
|
else
|
|
{
|
|
/* Clear PCC register */
|
|
PCC_HWA_SetRegister(pAttributeVal->u32RegOffset,0U);
|
|
u32ExpectedRegVal = 0U;
|
|
u32FunctionFreqVal = 0U;
|
|
}
|
|
|
|
/* Check PCC register has been configured, If current CPU do not have permission to configure the PCC register, the except value
|
|
* will not match the actual value */
|
|
if (u32ExpectedRegVal != PCC_HWA_GetRegister(pAttributeVal->u32RegOffset))
|
|
{
|
|
/* In this case, current core does not have permission to control the register */
|
|
eStatus = PCC_STATUS_CONFIGURED_NOT_SUPPORT;
|
|
}
|
|
else if (u32FunctionFreqVal > 160000000U)
|
|
{
|
|
/* In this case, current function clock too high, must configured below 150M */
|
|
eStatus = PCC_STATUS_CONFIGURED_NOT_SUPPORT;
|
|
}
|
|
else
|
|
{
|
|
/* do nothing */
|
|
}
|
|
}
|
|
|
|
return eStatus;
|
|
}
|
|
|
|
/**
|
|
* @brief Generate peripheral reset
|
|
*
|
|
*/
|
|
void PCC_GenPeripheralReset(const PCC_ClkSrcType eClockName)
|
|
{
|
|
DEV_ASSERT((uint32_t)eClockName < (uint32_t)PCC_END_OF_CLOCKS);
|
|
PCC_HWA_SoftwareReset(s_tPccClockMap[(uint32_t)eClockName].u32RegOffset);
|
|
}
|
|
|
|
|