mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-31 05:52:55 +08:00
971 lines
39 KiB
C
971 lines
39 KiB
C
|
/**********************************************************************
|
|||
|
* $Id$ lpc43xx_cgu.c 2011-06-02
|
|||
|
*//**
|
|||
|
* @file lpc43xx_cgu.c
|
|||
|
* @brief Contains all functions support for Clock Generation and Control
|
|||
|
* firmware library on lpc43xx
|
|||
|
* @version 1.0
|
|||
|
* @date 02. June. 2011
|
|||
|
* @author NXP MCU SW Application Team
|
|||
|
*
|
|||
|
* Copyright(C) 2011, NXP Semiconductor
|
|||
|
* All rights reserved.
|
|||
|
*
|
|||
|
***********************************************************************
|
|||
|
* Software that is described herein is for illustrative purposes only
|
|||
|
* which provides customers with programming information regarding the
|
|||
|
* products. This software is supplied "AS IS" without any warranties.
|
|||
|
* NXP Semiconductors assumes no responsibility or liability for the
|
|||
|
* use of the software, conveys no license or title under any patent,
|
|||
|
* copyright, or mask work right to the product. NXP Semiconductors
|
|||
|
* reserves the right to make changes in the software without
|
|||
|
* notification. NXP Semiconductors also make no representation or
|
|||
|
* warranty that such application will be suitable for the specified
|
|||
|
* use without further testing or modification.
|
|||
|
* Permission to use, copy, modify, and distribute this software and its
|
|||
|
* documentation is hereby granted, under NXP Semiconductors<EFBFBD>
|
|||
|
* relevant copyright in the software, without fee, provided that it
|
|||
|
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
|||
|
* copyright, permission, and disclaimer notice must appear in all copies of
|
|||
|
* this code.
|
|||
|
**********************************************************************/
|
|||
|
|
|||
|
/* Peripheral group ----------------------------------------------------------- */
|
|||
|
/** @addtogroup CGU
|
|||
|
* @{
|
|||
|
*/
|
|||
|
|
|||
|
/* Includes ------------------------------------------------------------------- */
|
|||
|
#include "lpc_types.h"
|
|||
|
#include "lpc43xx_scu.h"
|
|||
|
#include "lpc43xx_cgu.h"
|
|||
|
|
|||
|
/** This define used to fix mistake when run with IAR compiler */
|
|||
|
#ifdef __ICCARM__
|
|||
|
#define CGU_BRANCH_STATUS_ENABLE_MASK 0x80000001
|
|||
|
#else
|
|||
|
#define CGU_BRANCH_STATUS_ENABLE_MASK 0x01
|
|||
|
#endif
|
|||
|
|
|||
|
/*TODO List:
|
|||
|
* SET PLL0
|
|||
|
* UPDATE Clock from PLL0
|
|||
|
* SetDIV uncheck value
|
|||
|
* GetBaseStatus BASE_SAFE
|
|||
|
* */
|
|||
|
/* Local definition */
|
|||
|
#define CGU_ADDRESS32(x,y) (*(uint32_t*)((uint32_t)x+y))
|
|||
|
|
|||
|
/* Local Variable */
|
|||
|
const int16_t CGU_Entity_ControlReg_Offset[CGU_ENTITY_NUM] = {
|
|||
|
-1, //CGU_CLKSRC_32KHZ_OSC,
|
|||
|
-1, //CGU_CLKSRC_IRC,
|
|||
|
-1, //CGU_CLKSRC_ENET_RX_CLK,
|
|||
|
-1, //CGU_CLKSRC_ENET_TX_CLK,
|
|||
|
-1, //CGU_CLKSRC_GP_CLKIN,
|
|||
|
-1, //CGU_CLKSRC_TCK,
|
|||
|
0x18, //CGU_CLKSRC_XTAL_OSC,
|
|||
|
0x20, //CGU_CLKSRC_PLL0,
|
|||
|
0x30, //CGU_CLKSRC_PLL0_AUDIO **REV A**
|
|||
|
0x44, //CGU_CLKSRC_PLL1,
|
|||
|
-1, //CGU_CLKSRC_RESERVE,
|
|||
|
-1, //CGU_CLKSRC_RESERVE,
|
|||
|
0x48, //CGU_CLKSRC_IDIVA,,
|
|||
|
0x4C, //CGU_CLKSRC_IDIVB,
|
|||
|
0x50, //CGU_CLKSRC_IDIVC,
|
|||
|
0x54, //CGU_CLKSRC_IDIVD,
|
|||
|
0x58, //CGU_CLKSRC_IDIVE,
|
|||
|
|
|||
|
0x5C, //CGU_BASE_SAFE,
|
|||
|
0x60, //CGU_BASE_USB0,
|
|||
|
0x64, //CGU_BASE_PERIPH, // used for SPGPIO, peripheral control
|
|||
|
0x68, //CGU_BASE_USB1,
|
|||
|
0x6C, //CGU_BASE_M4,
|
|||
|
0x70, //CGU_BASE_SPIFI,
|
|||
|
-1, //CGU_BASE_RESERVE,
|
|||
|
0x78, //CGU_BASE_PHY_RX,
|
|||
|
0x7C, //CGU_BASE_PHY_TX,
|
|||
|
0x80, //CGU_BASE_APB1,
|
|||
|
0x84, //CGU_BASE_APB3,
|
|||
|
0x88, //CGU_BASE_LCD,
|
|||
|
0X8C, //CGU_BASE_ENET_CSR, **REV A**
|
|||
|
0x90, //CGU_BASE_SDIO,
|
|||
|
0x94, //CGU_BASE_SSP0,
|
|||
|
0x98, //CGU_BASE_SSP1,
|
|||
|
0x9C, //CGU_BASE_UART0,
|
|||
|
0xA0, //CGU_BASE_UART1,
|
|||
|
0xA4, //CGU_BASE_UART2,
|
|||
|
0xA8, //CGU_BASE_UART3,
|
|||
|
0xAC, //CGU_BASE_CLKOUT
|
|||
|
-1,
|
|||
|
-1,
|
|||
|
-1,
|
|||
|
-1,
|
|||
|
0xC0, //CGU_BASE_APLL
|
|||
|
0xC4, //CGU_BASE_OUT0
|
|||
|
0xC8 //CGU_BASE_OUT1
|
|||
|
};
|
|||
|
|
|||
|
const uint8_t CGU_ConnectAlloc_Tbl[CGU_CLKSRC_NUM][CGU_ENTITY_NUM] = {
|
|||
|
// 3 I E E G T X P P P x x D D D D D S U P U M S x P P A A L E S S S U U U U C x x x x A O O
|
|||
|
// 2 R R T P C T L L L I I I I I A S E S 3 P H H P P C N D S S R R R R O P U U
|
|||
|
// C X X I K A 0 A 1 A B C D E F B R B F RxTx1 3 D T I 0 1 0 1 2 3 L T T
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_32KHZ_OSC = 0,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_IRC,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_ENET_RX_CLK,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_ENET_TX_CLK,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_GP_CLKIN,*/
|
|||
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0},/*CGU_CLKSRC_TCK,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_XTAL_OSC,*/
|
|||
|
{0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1},/*CGU_CLKSRC_PLL0,*/
|
|||
|
{0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_PLL0_AUDIO,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_PLL1,*/
|
|||
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
|||
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_IDIVA = CGU_CLKSRC_PLL1 + 3,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_IDIVB,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_IDIVC,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1},/*CGU_CLKSRC_IDIVD,*/
|
|||
|
{0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1}/*CGU_CLKSRC_IDIVE,*/
|
|||
|
};
|
|||
|
|
|||
|
const CGU_PERIPHERAL_S CGU_PERIPHERAL_Info[CGU_PERIPHERAL_NUM] = {
|
|||
|
/* Register Clock | Peripheral Clock
|
|||
|
| BASE | BRANCH | BASE | BRANCH */
|
|||
|
{CGU_BASE_APB3, 0x1118, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_ADC0,
|
|||
|
{CGU_BASE_APB3, 0x1120, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_ADC1,
|
|||
|
{CGU_BASE_M4, 0x1460, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_AES,
|
|||
|
//// CGU_PERIPHERAL_ALARMTIMER_CGU_RGU_RTC_WIC,
|
|||
|
{CGU_BASE_APB1, 0x1200, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_APB1_BUS,
|
|||
|
{CGU_BASE_APB3, 0x1100, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_APB3_BUS,
|
|||
|
{CGU_BASE_APB3, 0x1128, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_CAN0,
|
|||
|
{CGU_BASE_M4, 0x1538, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_CREG,
|
|||
|
{CGU_BASE_APB3, 0x1110, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_DAC,
|
|||
|
{CGU_BASE_M4, 0x1440, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_DMA,
|
|||
|
{CGU_BASE_M4, 0x1430, CGU_BASE_M4, 0x1478, 0},//CGU_PERIPHERAL_EMC,
|
|||
|
{CGU_BASE_M4, 0x1420, CGU_BASE_PHY_RX, 0x0000, CGU_PERIPHERAL_ETHERNET_TX},//CGU_PERIPHERAL_ETHERNET,
|
|||
|
{CGU_ENTITY_NONE,0x0000, CGU_BASE_PHY_TX, 0x0000, 0},//CGU_PERIPHERAL_ETHERNET_TX
|
|||
|
{CGU_BASE_M4, 0x1410, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_GPIO,
|
|||
|
{CGU_BASE_APB1, 0x1210, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_I2C0,
|
|||
|
{CGU_BASE_APB3, 0x1108, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_I2C1,
|
|||
|
{CGU_BASE_APB1, 0x1218, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_I2S,
|
|||
|
{CGU_BASE_M4, 0x1418, CGU_BASE_LCD, 0x0000, 0},//CGU_PERIPHERAL_LCD,
|
|||
|
{CGU_BASE_M4, 0x1448, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_M3CORE,
|
|||
|
{CGU_BASE_M4, 0x1400, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_M3_BUS,
|
|||
|
{CGU_BASE_APB1, 0x1208, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_MOTOCON,
|
|||
|
{CGU_BASE_M4, 0x1630, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_QEI,
|
|||
|
{CGU_BASE_M4, 0x1600, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_RITIMER,
|
|||
|
{CGU_BASE_M4, 0x1468, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_SCT,
|
|||
|
{CGU_BASE_M4, 0x1530, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_SCU,
|
|||
|
{CGU_BASE_M4, 0x1438, CGU_BASE_SDIO, 0x2800, 0},//CGU_PERIPHERAL_SDIO,
|
|||
|
{CGU_BASE_M4, 0x1408, CGU_BASE_SPIFI, 0x1300, 0},//CGU_PERIPHERAL_SPIFI,
|
|||
|
{CGU_BASE_M4, 0x1518, CGU_BASE_SSP0, 0x2700, 0},//CGU_PERIPHERAL_SSP0,
|
|||
|
{CGU_BASE_M4, 0x1628, CGU_BASE_SSP1, 0x2600, 0},//CGU_PERIPHERAL_SSP1,
|
|||
|
{CGU_BASE_M4, 0x1520, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_TIMER0,
|
|||
|
{CGU_BASE_M4, 0x1528, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_TIMER1,
|
|||
|
{CGU_BASE_M4, 0x1618, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_TIMER2,
|
|||
|
{CGU_BASE_M4, 0x1620, CGU_ENTITY_NONE, 0x0000, 0},//CGU_PERIPHERAL_TIMER3,
|
|||
|
{CGU_BASE_M4, 0x1508, CGU_BASE_UART0, 0x2500, 0},//CGU_PERIPHERAL_UART0,
|
|||
|
{CGU_BASE_M4, 0x1510, CGU_BASE_UART1, 0x2400, 0},//CGU_PERIPHERAL_UART1,
|
|||
|
{CGU_BASE_M4, 0x1608, CGU_BASE_UART2, 0x2300, 0},//CGU_PERIPHERAL_UART2,
|
|||
|
{CGU_BASE_M4, 0x1610, CGU_BASE_UART3, 0x2200, 0},//CGU_PERIPHERAL_UART3,
|
|||
|
{CGU_BASE_M4, 0x1428, CGU_BASE_USB0, 0x1800, 0},//CGU_PERIPHERAL_USB0,
|
|||
|
{CGU_BASE_M4, 0x1470, CGU_BASE_USB1, 0x1900, 0},//CGU_PERIPHERAL_USB1,
|
|||
|
{CGU_BASE_M4, 0x1500, CGU_BASE_SAFE, 0x0000, 0},//CGU_PERIPHERAL_WWDT,
|
|||
|
};
|
|||
|
|
|||
|
uint32_t CGU_ClockSourceFrequency[CGU_CLKSRC_NUM] = {0,12000000,0,0,0,0, 0, 480000000,0,0,0,0,0,0,0,0,0};
|
|||
|
|
|||
|
#define CGU_CGU_ADDR ((uint32_t)LPC_CGU)
|
|||
|
#define CGU_REG_BASE_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_Entity_ControlReg_Offset[CGU_PERIPHERAL_Info[x].RegBaseEntity]))
|
|||
|
#define CGU_REG_BRANCH_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].RegBranchOffset))
|
|||
|
#define CGU_REG_BRANCH_STATUS(x) (*(volatile uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].RegBranchOffset+4))
|
|||
|
|
|||
|
#define CGU_PER_BASE_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_Entity_ControlReg_Offset[CGU_PERIPHERAL_Info[x].PerBaseEntity]))
|
|||
|
#define CGU_PER_BRANCH_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].PerBranchOffset))
|
|||
|
#define CGU_PER_BRANCH_STATUS(x) (*(volatile uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].PerBranchOffset+4))
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Initialize default clock for LPC4300 Eval board
|
|||
|
* @param[in] None
|
|||
|
* @return Initialize status, could be:
|
|||
|
* - CGU_ERROR_SUCCESS: successful
|
|||
|
* - Other: error
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_Init(void){
|
|||
|
CGU_SetXTALOSC(12000000);
|
|||
|
CGU_EnableEntity(CGU_CLKSRC_XTAL_OSC, ENABLE);
|
|||
|
CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL1);
|
|||
|
// Disable PLL1 CPU hang???
|
|||
|
//CGU_EnableEntity(CGU_CLKSRC_PLL1, DISABLE);
|
|||
|
CGU_SetPLL1(6);
|
|||
|
CGU_EnableEntity(CGU_CLKSRC_PLL1, ENABLE);
|
|||
|
CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_M4);
|
|||
|
CGU_UpdateClock();
|
|||
|
SystemCoreClock = 6*12000000;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Configure power for individual peripheral
|
|||
|
* @param[in] PPType peripheral type, should be:
|
|||
|
* - CGU_PERIPHERAL_ADC0 :ADC0
|
|||
|
* - CGU_PERIPHERAL_ADC1 :ADC1
|
|||
|
* - CGU_PERIPHERAL_AES :AES
|
|||
|
* - CGU_PERIPHERAL_APB1_BUS :APB1 bus
|
|||
|
* - CGU_PERIPHERAL_APB3_BUS :APB3 bus
|
|||
|
* - CGU_PERIPHERAL_CAN :CAN
|
|||
|
* - CGU_PERIPHERAL_CREG :CREG
|
|||
|
* - CGU_PERIPHERAL_DAC :DAC
|
|||
|
* - CGU_PERIPHERAL_DMA :DMA
|
|||
|
* - CGU_PERIPHERAL_EMC :EMC
|
|||
|
* - CGU_PERIPHERAL_ETHERNET :ETHERNET
|
|||
|
* - CGU_PERIPHERAL_GPIO :GPIO
|
|||
|
* - CGU_PERIPHERAL_I2C0 :I2C0
|
|||
|
* - CGU_PERIPHERAL_I2C1 :I2C1
|
|||
|
* - CGU_PERIPHERAL_I2S :I2S
|
|||
|
* - CGU_PERIPHERAL_LCD :LCD
|
|||
|
* - CGU_PERIPHERAL_M3CORE :M3 core
|
|||
|
* - CGU_PERIPHERAL_M3_BUS :M3 bus
|
|||
|
* - CGU_PERIPHERAL_MOTOCON :Motor control
|
|||
|
* - CGU_PERIPHERAL_QEI :QEI
|
|||
|
* - CGU_PERIPHERAL_RITIMER :RIT timer
|
|||
|
* - CGU_PERIPHERAL_SCT :SCT
|
|||
|
* - CGU_PERIPHERAL_SCU :SCU
|
|||
|
* - CGU_PERIPHERAL_SDIO :SDIO
|
|||
|
* - CGU_PERIPHERAL_SPIFI :SPIFI
|
|||
|
* - CGU_PERIPHERAL_SSP0 :SSP0
|
|||
|
* - CGU_PERIPHERAL_SSP1 :SSP1
|
|||
|
* - CGU_PERIPHERAL_TIMER0 :TIMER0
|
|||
|
* - CGU_PERIPHERAL_TIMER1 :TIMER1
|
|||
|
* - CGU_PERIPHERAL_TIMER2 :TIMER2
|
|||
|
* - CGU_PERIPHERAL_TIMER3 :TIMER3
|
|||
|
* - CGU_PERIPHERAL_UART0 :UART0
|
|||
|
* - CGU_PERIPHERAL_UART1 :UART1
|
|||
|
* - CGU_PERIPHERAL_UART2 :UART2
|
|||
|
* - CGU_PERIPHERAL_UART3 :UART3
|
|||
|
* - CGU_PERIPHERAL_USB0 :USB0
|
|||
|
* - CGU_PERIPHERAL_USB1 :USB1
|
|||
|
* - CGU_PERIPHERAL_WWDT :WWDT
|
|||
|
* @param[in] en status, should be:
|
|||
|
* - ENABLE: Enable power
|
|||
|
* - DISABLE: Disable power
|
|||
|
* @return Configure status, could be:
|
|||
|
* - CGU_ERROR_SUCCESS: successful
|
|||
|
* - Other: error
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_ConfigPWR (CGU_PERIPHERAL_T PPType, FunctionalState en){
|
|||
|
if(PPType >= CGU_PERIPHERAL_WWDT && PPType <= CGU_PERIPHERAL_ADC0)
|
|||
|
return CGU_ERROR_INVALID_PARAM;
|
|||
|
if(en == DISABLE){/* Going to disable clock */
|
|||
|
/*Get Reg branch status */
|
|||
|
if(CGU_PERIPHERAL_Info[PPType].RegBranchOffset!= 0 &&
|
|||
|
CGU_REG_BRANCH_STATUS(PPType) & 1){
|
|||
|
CGU_REG_BRANCH_CTRL(PPType) &= ~1; /* Disable branch clock */
|
|||
|
while(CGU_REG_BRANCH_STATUS(PPType) & 1);
|
|||
|
}
|
|||
|
/* GetBase Status*/
|
|||
|
if((CGU_PERIPHERAL_Info[PPType].RegBaseEntity!=CGU_ENTITY_NONE) &&
|
|||
|
CGU_GetBaseStatus((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity) == 0){
|
|||
|
/* Disable Base */
|
|||
|
CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity,0);
|
|||
|
}
|
|||
|
|
|||
|
/* Same for Peripheral */
|
|||
|
if((CGU_PERIPHERAL_Info[PPType].PerBranchOffset!= 0) && (CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)){
|
|||
|
CGU_PER_BRANCH_CTRL(PPType) &= ~1; /* Disable branch clock */
|
|||
|
while(CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK);
|
|||
|
}
|
|||
|
/* GetBase Status*/
|
|||
|
if((CGU_PERIPHERAL_Info[PPType].PerBaseEntity!=CGU_ENTITY_NONE) &&
|
|||
|
CGU_GetBaseStatus((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity) == 0){
|
|||
|
/* Disable Base */
|
|||
|
CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity,0);
|
|||
|
}
|
|||
|
}else{
|
|||
|
/* enable */
|
|||
|
/* GetBase Status*/
|
|||
|
if((CGU_PERIPHERAL_Info[PPType].RegBaseEntity!=CGU_ENTITY_NONE) && CGU_REG_BASE_CTRL(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK){
|
|||
|
/* Enable Base */
|
|||
|
CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity, 1);
|
|||
|
}
|
|||
|
/*Get Reg branch status */
|
|||
|
if((CGU_PERIPHERAL_Info[PPType].RegBranchOffset!= 0) && !(CGU_REG_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)){
|
|||
|
CGU_REG_BRANCH_CTRL(PPType) |= 1; /* Enable branch clock */
|
|||
|
while(!(CGU_REG_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK));
|
|||
|
}
|
|||
|
|
|||
|
/* Same for Peripheral */
|
|||
|
/* GetBase Status*/
|
|||
|
if((CGU_PERIPHERAL_Info[PPType].PerBaseEntity != CGU_ENTITY_NONE) &&
|
|||
|
(CGU_PER_BASE_CTRL(PPType) & 1)){
|
|||
|
/* Enable Base */
|
|||
|
CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity, 1);
|
|||
|
}
|
|||
|
/*Get Reg branch status */
|
|||
|
if((CGU_PERIPHERAL_Info[PPType].PerBranchOffset!= 0) && !(CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)){
|
|||
|
CGU_PER_BRANCH_CTRL(PPType) |= 1; /* Enable branch clock */
|
|||
|
while(!(CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK));
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if(CGU_PERIPHERAL_Info[PPType].next){
|
|||
|
return CGU_ConfigPWR((CGU_PERIPHERAL_T)CGU_PERIPHERAL_Info[PPType].next, en);
|
|||
|
}
|
|||
|
return CGU_ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Get peripheral clock frequency
|
|||
|
* @param[in] Clock Peripheral type, should be:
|
|||
|
* - CGU_PERIPHERAL_ADC0 :ADC0
|
|||
|
* - CGU_PERIPHERAL_ADC1 :ADC1
|
|||
|
* - CGU_PERIPHERAL_AES :AES
|
|||
|
* - CGU_PERIPHERAL_APB1_BUS :APB1 bus
|
|||
|
* - CGU_PERIPHERAL_APB3_BUS :APB3 bus
|
|||
|
* - CGU_PERIPHERAL_CAN :CAN
|
|||
|
* - CGU_PERIPHERAL_CREG :CREG
|
|||
|
* - CGU_PERIPHERAL_DAC :DAC
|
|||
|
* - CGU_PERIPHERAL_DMA :DMA
|
|||
|
* - CGU_PERIPHERAL_EMC :EMC
|
|||
|
* - CGU_PERIPHERAL_ETHERNET :ETHERNET
|
|||
|
* - CGU_PERIPHERAL_GPIO :GPIO
|
|||
|
* - CGU_PERIPHERAL_I2C0 :I2C0
|
|||
|
* - CGU_PERIPHERAL_I2C1 :I2C1
|
|||
|
* - CGU_PERIPHERAL_I2S :I2S
|
|||
|
* - CGU_PERIPHERAL_LCD :LCD
|
|||
|
* - CGU_PERIPHERAL_M3CORE :M3 core
|
|||
|
* - CGU_PERIPHERAL_M3_BUS :M3 bus
|
|||
|
* - CGU_PERIPHERAL_MOTOCON :Motor control
|
|||
|
* - CGU_PERIPHERAL_QEI :QEI
|
|||
|
* - CGU_PERIPHERAL_RITIMER :RIT timer
|
|||
|
* - CGU_PERIPHERAL_SCT :SCT
|
|||
|
* - CGU_PERIPHERAL_SCU :SCU
|
|||
|
* - CGU_PERIPHERAL_SDIO :SDIO
|
|||
|
* - CGU_PERIPHERAL_SPIFI :SPIFI
|
|||
|
* - CGU_PERIPHERAL_SSP0 :SSP0
|
|||
|
* - CGU_PERIPHERAL_SSP1 :SSP1
|
|||
|
* - CGU_PERIPHERAL_TIMER0 :TIMER0
|
|||
|
* - CGU_PERIPHERAL_TIMER1 :TIMER1
|
|||
|
* - CGU_PERIPHERAL_TIMER2 :TIMER2
|
|||
|
* - CGU_PERIPHERAL_TIMER3 :TIMER3
|
|||
|
* - CGU_PERIPHERAL_UART0 :UART0
|
|||
|
* - CGU_PERIPHERAL_UART1 :UART1
|
|||
|
* - CGU_PERIPHERAL_UART2 :UART2
|
|||
|
* - CGU_PERIPHERAL_UART3 :UART3
|
|||
|
* - CGU_PERIPHERAL_USB0 :USB0
|
|||
|
* - CGU_PERIPHERAL_USB1 :USB1
|
|||
|
* - CGU_PERIPHERAL_WWDT :WWDT
|
|||
|
* @return Return frequently value
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_GetPCLKFrequency (CGU_PERIPHERAL_T Clock){
|
|||
|
uint32_t ClkSrc;
|
|||
|
if(Clock >= CGU_PERIPHERAL_WWDT && Clock <= CGU_PERIPHERAL_ADC0)
|
|||
|
return CGU_ERROR_INVALID_PARAM;
|
|||
|
|
|||
|
if(CGU_PERIPHERAL_Info[Clock].PerBaseEntity != CGU_ENTITY_NONE){
|
|||
|
/* Get Base Clock Source */
|
|||
|
ClkSrc = (CGU_PER_BASE_CTRL(Clock) & CGU_CTRL_SRC_MASK) >> 24;
|
|||
|
/* GetBase Status*/
|
|||
|
if(CGU_PER_BASE_CTRL(Clock) & 1)
|
|||
|
return 0;
|
|||
|
/* check Branch if it is enabled */
|
|||
|
if((CGU_PERIPHERAL_Info[Clock].PerBranchOffset!= 0) && !(CGU_PER_BRANCH_STATUS(Clock) & CGU_BRANCH_STATUS_ENABLE_MASK)) return 0;
|
|||
|
}else{
|
|||
|
if(CGU_REG_BASE_CTRL(Clock) & 1) return 0;
|
|||
|
ClkSrc = (CGU_REG_BASE_CTRL(Clock) & CGU_CTRL_SRC_MASK) >> 24;
|
|||
|
/* check Branch if it is enabled */
|
|||
|
if((CGU_PERIPHERAL_Info[Clock].RegBranchOffset!= 0) && !(CGU_REG_BRANCH_STATUS(Clock) & CGU_BRANCH_STATUS_ENABLE_MASK)) return 0;
|
|||
|
}
|
|||
|
return CGU_ClockSourceFrequency[ClkSrc];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Update clock
|
|||
|
* @param[in] None
|
|||
|
* @return None
|
|||
|
**********************************************************************/
|
|||
|
void CGU_UpdateClock(void){
|
|||
|
uint32_t ClkSrc;
|
|||
|
uint32_t div;
|
|||
|
uint32_t divisor;
|
|||
|
int32_t RegOffset;
|
|||
|
/* 32OSC */
|
|||
|
if(ISBITSET(LPC_CREG->CREG0,1) && ISBITCLR(LPC_CREG->CREG0,3))
|
|||
|
CGU_ClockSourceFrequency[CGU_CLKSRC_32KHZ_OSC] = 32768;
|
|||
|
else
|
|||
|
CGU_ClockSourceFrequency[CGU_CLKSRC_32KHZ_OSC] = 0;
|
|||
|
/*PLL0*/
|
|||
|
/* PLL1 */
|
|||
|
if(ISBITCLR(LPC_CGU->PLL1_CTRL,0) /* Enabled */ /* EA ANDLI: Original code tested bit 1 which is BYPASS, not PD */
|
|||
|
&& (LPC_CGU->PLL1_STAT&1)){ /* Locked? */
|
|||
|
ClkSrc = (LPC_CGU->PLL1_CTRL & CGU_CTRL_SRC_MASK)>>24;
|
|||
|
CGU_ClockSourceFrequency[CGU_CLKSRC_PLL1] = CGU_ClockSourceFrequency[ClkSrc] *
|
|||
|
(((LPC_CGU->PLL1_CTRL>>16)&0xFF)+1);
|
|||
|
}else
|
|||
|
CGU_ClockSourceFrequency[CGU_CLKSRC_PLL1] = 0;
|
|||
|
|
|||
|
/* DIV */
|
|||
|
for(div = CGU_CLKSRC_IDIVA; div <= CGU_CLKSRC_IDIVE; div++){
|
|||
|
RegOffset = CGU_Entity_ControlReg_Offset[div];
|
|||
|
if(ISBITCLR(CGU_ADDRESS32(LPC_CGU,RegOffset),1)){
|
|||
|
ClkSrc = (CGU_ADDRESS32(LPC_CGU,RegOffset) & CGU_CTRL_SRC_MASK) >> 24;
|
|||
|
divisor = (CGU_ADDRESS32(LPC_CGU,RegOffset)>>2) & 0xFF;
|
|||
|
divisor ++;
|
|||
|
CGU_ClockSourceFrequency[div] = CGU_ClockSourceFrequency[ClkSrc] / divisor;
|
|||
|
}else
|
|||
|
CGU_ClockSourceFrequency[div] = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Set XTAL oscillator value
|
|||
|
* @param[in] ClockFrequency XTAL Frequency value
|
|||
|
* @return Setting status, could be:
|
|||
|
* - CGU_ERROR_SUCCESS: successful
|
|||
|
* - CGU_ERROR_FREQ_OUTOF_RANGE: XTAL value set is out of range
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_SetXTALOSC(uint32_t ClockFrequency){
|
|||
|
if(ClockFrequency < 15000000){
|
|||
|
LPC_CGU->XTAL_OSC_CTRL &= ~(1<<2);
|
|||
|
}else if(ClockFrequency < 25000000){
|
|||
|
LPC_CGU->XTAL_OSC_CTRL |= (1<<2);
|
|||
|
}else
|
|||
|
return CGU_ERROR_FREQ_OUTOF_RANGE;
|
|||
|
|
|||
|
CGU_ClockSourceFrequency[CGU_CLKSRC_XTAL_OSC] = ClockFrequency;
|
|||
|
return CGU_ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Set clock divider
|
|||
|
* @param[in] SelectDivider Clock source, should be:
|
|||
|
* - CGU_CLKSRC_IDIVA :Integer divider register A
|
|||
|
* - CGU_CLKSRC_IDIVB :Integer divider register B
|
|||
|
* - CGU_CLKSRC_IDIVC :Integer divider register C
|
|||
|
* - CGU_CLKSRC_IDIVD :Integer divider register D
|
|||
|
* - CGU_CLKSRC_IDIVE :Integer divider register E
|
|||
|
* @param[in] divisor Divisor value, should be: 0..255
|
|||
|
* @return Setting status, could be:
|
|||
|
* - CGU_ERROR_SUCCESS: successful
|
|||
|
* - CGU_ERROR_INVALID_ENTITY: Invalid entity
|
|||
|
**********************************************************************/
|
|||
|
/* divisor number must >=1*/
|
|||
|
uint32_t CGU_SetDIV(CGU_ENTITY_T SelectDivider, uint32_t divisor){
|
|||
|
int32_t RegOffset;
|
|||
|
uint32_t tempReg;
|
|||
|
if(SelectDivider>=CGU_CLKSRC_IDIVA && SelectDivider<=CGU_CLKSRC_IDIVE){
|
|||
|
RegOffset = CGU_Entity_ControlReg_Offset[SelectDivider];
|
|||
|
if(RegOffset == -1) return CGU_ERROR_INVALID_ENTITY;
|
|||
|
tempReg = CGU_ADDRESS32(LPC_CGU,RegOffset);
|
|||
|
tempReg &= ~(0xFF<<2);
|
|||
|
tempReg |= ((divisor-1)&0xFF)<<2;
|
|||
|
CGU_ADDRESS32(LPC_CGU,RegOffset) = tempReg;
|
|||
|
return CGU_ERROR_SUCCESS;
|
|||
|
}
|
|||
|
return CGU_ERROR_INVALID_ENTITY;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Enable clock entity
|
|||
|
* @param[in] ClockEntity Clock entity, should be:
|
|||
|
* - CGU_CLKSRC_32KHZ_OSC :32Khz oscillator
|
|||
|
* - CGU_CLKSRC_IRC :IRC clock
|
|||
|
* - CGU_CLKSRC_ENET_RX_CLK :Ethernet receive clock
|
|||
|
* - CGU_CLKSRC_ENET_TX_CLK :Ethernet transmit clock
|
|||
|
* - CGU_CLKSRC_GP_CLKIN :General purpose input clock
|
|||
|
* - CGU_CLKSRC_XTAL_OSC :Crystal oscillator
|
|||
|
* - CGU_CLKSRC_PLL0 :PLL0 clock
|
|||
|
* - CGU_CLKSRC_PLL1 :PLL1 clock
|
|||
|
* - CGU_CLKSRC_IDIVA :Integer divider register A
|
|||
|
* - CGU_CLKSRC_IDIVB :Integer divider register B
|
|||
|
* - CGU_CLKSRC_IDIVC :Integer divider register C
|
|||
|
* - CGU_CLKSRC_IDIVD :Integer divider register D
|
|||
|
* - CGU_CLKSRC_IDIVE :Integer divider register E
|
|||
|
* - CGU_BASE_SAFE :Base safe clock (always on)for WDT
|
|||
|
* - CGU_BASE_USB0 :Base clock for USB0
|
|||
|
* - CGU_BASE_PERIPH :Base clock for Peripheral bus
|
|||
|
* - CGU_BASE_USB1 :Base clock for USB1
|
|||
|
* - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core
|
|||
|
* and APB peripheral blocks #0 and #2
|
|||
|
* - CGU_BASE_SPIFI :Base clock for SPIFI
|
|||
|
* - CGU_BASE_PHY_RX :Base clock for Ethernet PHY Rx
|
|||
|
* - CGU_BASE_PHY_TX :Base clock for Ethernet PHY Tx
|
|||
|
* - CGU_BASE_APB1 :Base clock for APB peripheral block #1
|
|||
|
* - CGU_BASE_APB3 :Base clock for APB peripheral block #3
|
|||
|
* - CGU_BASE_LCD :Base clock for LCD
|
|||
|
* - CGU_BASE_SDIO :Base clock for SDIO card reader
|
|||
|
* - CGU_BASE_SSP0 :Base clock for SSP0
|
|||
|
* - CGU_BASE_SSP1 :Base clock for SSP1
|
|||
|
* - CGU_BASE_UART0 :Base clock for UART0
|
|||
|
* - CGU_BASE_UART1 :Base clock for UART1
|
|||
|
* - CGU_BASE_UART2 :Base clock for UART2
|
|||
|
* - CGU_BASE_UART3 :Base clock for UART3
|
|||
|
* - CGU_BASE_CLKOUT :Base clock for CLKOUT pin
|
|||
|
* @param[in] en status, should be:
|
|||
|
* - ENABLE: Enable power
|
|||
|
* - DISABLE: Disable power
|
|||
|
* @return Setting status, could be:
|
|||
|
* - CGU_ERROR_SUCCESS: successful
|
|||
|
* - CGU_ERROR_INVALID_ENTITY: Invalid entity
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_EnableEntity(CGU_ENTITY_T ClockEntity, uint32_t en){
|
|||
|
int32_t RegOffset;
|
|||
|
int32_t i;
|
|||
|
if(ClockEntity == CGU_CLKSRC_32KHZ_OSC){
|
|||
|
if(en){
|
|||
|
LPC_CREG->CREG0 &= ~((1<<3)|(1<<2));
|
|||
|
LPC_CREG->CREG0 |= (1<<1)|(1<<0);
|
|||
|
}else{
|
|||
|
LPC_CREG->CREG0 &= ~((1<<1)|(1<<0));
|
|||
|
LPC_CREG->CREG0 |= (1<<3);
|
|||
|
}
|
|||
|
for(i = 0;i<1000000;i++);
|
|||
|
|
|||
|
}else if(ClockEntity == CGU_CLKSRC_ENET_RX_CLK){
|
|||
|
scu_pinmux(0xC ,0 , MD_PLN, FUNC3);
|
|||
|
|
|||
|
}else if(ClockEntity == CGU_CLKSRC_ENET_TX_CLK){
|
|||
|
scu_pinmux(0x1 ,19 , MD_PLN, FUNC0);
|
|||
|
|
|||
|
}else if(ClockEntity == CGU_CLKSRC_GP_CLKIN){
|
|||
|
|
|||
|
}else if(ClockEntity == CGU_CLKSRC_TCK){
|
|||
|
|
|||
|
}else if(ClockEntity == CGU_CLKSRC_XTAL_OSC){
|
|||
|
if(!en)
|
|||
|
LPC_CGU->XTAL_OSC_CTRL |= CGU_CTRL_EN_MASK;
|
|||
|
else
|
|||
|
LPC_CGU->XTAL_OSC_CTRL &= ~CGU_CTRL_EN_MASK;
|
|||
|
/*Delay for stable clock*/
|
|||
|
for(i = 0;i<1000000;i++);
|
|||
|
|
|||
|
}else{
|
|||
|
RegOffset = CGU_Entity_ControlReg_Offset[ClockEntity];
|
|||
|
if(RegOffset == -1) return CGU_ERROR_INVALID_ENTITY;
|
|||
|
if(!en){
|
|||
|
CGU_ADDRESS32(CGU_CGU_ADDR,RegOffset) |= CGU_CTRL_EN_MASK;
|
|||
|
}else{
|
|||
|
CGU_ADDRESS32(CGU_CGU_ADDR,RegOffset) &= ~CGU_CTRL_EN_MASK;
|
|||
|
/*if PLL is selected check if it is locked */
|
|||
|
if(ClockEntity == CGU_CLKSRC_PLL0){
|
|||
|
while((LPC_CGU->PLL0USB_STAT&1) == 0x0);
|
|||
|
}
|
|||
|
if(ClockEntity == CGU_CLKSRC_PLL0_AUDIO){
|
|||
|
while((LPC_CGU->PLL0AUDIO_STAT&1) == 0x0);
|
|||
|
}
|
|||
|
if(ClockEntity == CGU_CLKSRC_PLL1){
|
|||
|
while((LPC_CGU->PLL1_STAT&1) == 0x0);
|
|||
|
/*post check lock status */
|
|||
|
if(!(LPC_CGU->PLL1_STAT&1))
|
|||
|
while(1);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return CGU_ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Connect entity clock source
|
|||
|
* @param[in] ClockSource Clock source, should be:
|
|||
|
* - CGU_CLKSRC_32KHZ_OSC :32Khz oscillator
|
|||
|
* - CGU_CLKSRC_IRC :IRC clock
|
|||
|
* - CGU_CLKSRC_ENET_RX_CLK :Ethernet receive clock
|
|||
|
* - CGU_CLKSRC_ENET_TX_CLK :Ethernet transmit clock
|
|||
|
* - CGU_CLKSRC_GP_CLKIN :General purpose input clock
|
|||
|
* - CGU_CLKSRC_XTAL_OSC :Crystal oscillator
|
|||
|
* - CGU_CLKSRC_PLL0 :PLL0 clock
|
|||
|
* - CGU_CLKSRC_PLL1 :PLL1 clock
|
|||
|
* - CGU_CLKSRC_IDIVA :Integer divider register A
|
|||
|
* - CGU_CLKSRC_IDIVB :Integer divider register B
|
|||
|
* - CGU_CLKSRC_IDIVC :Integer divider register C
|
|||
|
* - CGU_CLKSRC_IDIVD :Integer divider register D
|
|||
|
* - CGU_CLKSRC_IDIVE :Integer divider register E
|
|||
|
* @param[in] ClockEntity Clock entity, should be:
|
|||
|
* - CGU_CLKSRC_PLL0 :PLL0 clock
|
|||
|
* - CGU_CLKSRC_PLL1 :PLL1 clock
|
|||
|
* - CGU_CLKSRC_IDIVA :Integer divider register A
|
|||
|
* - CGU_CLKSRC_IDIVB :Integer divider register B
|
|||
|
* - CGU_CLKSRC_IDIVC :Integer divider register C
|
|||
|
* - CGU_CLKSRC_IDIVD :Integer divider register D
|
|||
|
* - CGU_CLKSRC_IDIVE :Integer divider register E
|
|||
|
* - CGU_BASE_SAFE :Base safe clock (always on)for WDT
|
|||
|
* - CGU_BASE_USB0 :Base clock for USB0
|
|||
|
* - CGU_BASE_USB1 :Base clock for USB1
|
|||
|
* - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core
|
|||
|
* and APB peripheral blocks #0 and #2
|
|||
|
* - CGU_BASE_SPIFI :Base clock for SPIFI
|
|||
|
* - CGU_BASE_PHY_RX :Base clock for Ethernet PHY Rx
|
|||
|
* - CGU_BASE_PHY_TX :Base clock for Ethernet PHY Tx
|
|||
|
* - CGU_BASE_APB1 :Base clock for APB peripheral block #1
|
|||
|
* - CGU_BASE_APB3 :Base clock for APB peripheral block #3
|
|||
|
* - CGU_BASE_LCD :Base clock for LCD
|
|||
|
* - CGU_BASE_SDIO :Base clock for SDIO card reader
|
|||
|
* - CGU_BASE_SSP0 :Base clock for SSP0
|
|||
|
* - CGU_BASE_SSP1 :Base clock for SSP1
|
|||
|
* - CGU_BASE_UART0 :Base clock for UART0
|
|||
|
* - CGU_BASE_UART1 :Base clock for UART1
|
|||
|
* - CGU_BASE_UART2 :Base clock for UART2
|
|||
|
* - CGU_BASE_UART3 :Base clock for UART3
|
|||
|
* - CGU_BASE_CLKOUT :Base clock for CLKOUT pin
|
|||
|
* @return Setting status, could be:
|
|||
|
* - CGU_ERROR_SUCCESS: successful
|
|||
|
* - CGU_ERROR_CONNECT_TOGETHER: Error when 2 clock source connect together
|
|||
|
* - CGU_ERROR_INVALID_CLOCK_SOURCE: Invalid clock source error
|
|||
|
* - CGU_ERROR_INVALID_ENTITY: Invalid entity error
|
|||
|
**********************************************************************/
|
|||
|
/* Connect one entity into clock source */
|
|||
|
uint32_t CGU_EntityConnect(CGU_ENTITY_T ClockSource, CGU_ENTITY_T ClockEntity){
|
|||
|
int32_t RegOffset;
|
|||
|
uint32_t tempReg;
|
|||
|
|
|||
|
if(ClockSource > CGU_CLKSRC_IDIVE)
|
|||
|
return CGU_ERROR_INVALID_CLOCK_SOURCE;
|
|||
|
|
|||
|
if(ClockEntity >= CGU_CLKSRC_PLL0 && ClockEntity <= CGU_BASE_CLKOUT){
|
|||
|
if(CGU_ConnectAlloc_Tbl[ClockSource][ClockEntity]){
|
|||
|
RegOffset = CGU_Entity_ControlReg_Offset[ClockSource];
|
|||
|
if(RegOffset != -1){
|
|||
|
if(ClockEntity<=CGU_CLKSRC_IDIVE &&
|
|||
|
ClockEntity>=CGU_CLKSRC_PLL0)
|
|||
|
{
|
|||
|
//RegOffset = (CGU_ADDRESS32(LPC_CGU,RegOffset)>>24)&0xF;
|
|||
|
if(((CGU_ADDRESS32(LPC_CGU,RegOffset)>>24)& 0xF) == ClockEntity)
|
|||
|
return CGU_ERROR_CONNECT_TOGETHER;
|
|||
|
}
|
|||
|
}
|
|||
|
RegOffset = CGU_Entity_ControlReg_Offset[ClockEntity];
|
|||
|
if(RegOffset == -1) return CGU_ERROR_INVALID_ENTITY;
|
|||
|
tempReg = CGU_ADDRESS32(LPC_CGU,RegOffset);
|
|||
|
tempReg &= ~CGU_CTRL_SRC_MASK;
|
|||
|
tempReg |= ClockSource<<24 | CGU_CTRL_AUTOBLOCK_MASK;
|
|||
|
CGU_ADDRESS32(LPC_CGU,RegOffset) = tempReg;
|
|||
|
return CGU_ERROR_SUCCESS;
|
|||
|
}else
|
|||
|
return CGU_ERROR_INVALID_CLOCK_SOURCE;
|
|||
|
}else
|
|||
|
return CGU_ERROR_INVALID_ENTITY;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Get current USB PLL clock from XTAL
|
|||
|
* @param[in] None
|
|||
|
* @return Returned clock value
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_SetPLL0(void){
|
|||
|
// Setup PLL550 to generate 480MHz from 12 MHz crystal
|
|||
|
LPC_CGU->PLL0USB_CTRL |= 1; // Power down PLL
|
|||
|
// P N
|
|||
|
LPC_CGU->PLL0USB_NP_DIV = (98<<0) | (514<<12);
|
|||
|
// SELP SELI SELR MDEC
|
|||
|
LPC_CGU->PLL0USB_MDIV = (0xB<<17)|(0x10<<22)|(0<<28)|(0x7FFA<<0);
|
|||
|
LPC_CGU->PLL0USB_CTRL =(CGU_CLKSRC_XTAL_OSC<<24) | (0x3<<2) | (1<<4);
|
|||
|
return CGU_ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Get current Audio PLL clock from XTAL
|
|||
|
* @param[in] None
|
|||
|
* @return Returned clock value
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_SetPLL0audio(void){
|
|||
|
/* disable clock, disable skew enable, power down pll,
|
|||
|
* (dis/en)able post divider, (dis/en)able pre-divider,
|
|||
|
* disable free running mode, disable bandsel,
|
|||
|
* enable up limmiter, disable bypass
|
|||
|
*/
|
|||
|
LPC_CGU->PLL0AUDIO_CTRL = (6 << 24) /* source = XTAL OSC 12 MHz */
|
|||
|
| _BIT(0); /* power down */
|
|||
|
/* PLL should be set to 512fs rate 512 * 48000 = 24576000 Hz */
|
|||
|
/* set mdec register */
|
|||
|
#if 1 // results from gcc program
|
|||
|
LPC_CGU->PLL0AUDIO_MDIV = 0x23e34d3;
|
|||
|
LPC_CGU->PLL0AUDIO_NP_DIV = 0x3f00e;
|
|||
|
LPC_CGU->PLL0AUDIO_CTRL = (6 << 24) /* source = XTAL OSC 12 MHz */
|
|||
|
| (6<< 12) // fractional divider off and bypassed
|
|||
|
| _BIT(4); /* CLKEN */
|
|||
|
#else
|
|||
|
LPC_CGU->PLL0AUDIO_MDIV = (0 << 28) /* SELR */
|
|||
|
| (40 << 22) /* SELI */
|
|||
|
| (31 << 17) /* SELP */
|
|||
|
| 11372; /* MDEC */
|
|||
|
/* set ndec, pdec register */
|
|||
|
LPC_CGU->PLL0AUDIO_NP_DIV = (22 << 12) /* ndec */
|
|||
|
| (10); /* pdec */
|
|||
|
|
|||
|
/* set fraction divider register. [21:15] = m, [14:0] = fractional value */
|
|||
|
LPC_CGU->PLL0AUDIO_FRAC = (86 << 15) | 0x1B7;
|
|||
|
LPC_CGU->PLL0AUDIO_CTRL = (6 << 24) /* source = XTAL OSC 12 MHz */
|
|||
|
| _BIT(12) /* enable SD modulator to update mdec*/
|
|||
|
| _BIT(4); /* CLKEN */
|
|||
|
#endif
|
|||
|
/* wait for lock */
|
|||
|
while (!(LPC_CGU->PLL0AUDIO_STAT & 1));
|
|||
|
|
|||
|
return CGU_ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Setting PLL1
|
|||
|
* @param[in] mult Multiple value
|
|||
|
* @return Setting status, could be:
|
|||
|
* - CGU_ERROR_SUCCESS: successful
|
|||
|
* - CGU_ERROR_INVALID_PARAM: Invalid parameter error
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_SetPLL1(uint32_t mult){
|
|||
|
uint32_t msel=0, nsel=0, psel=0, pval=1;
|
|||
|
uint32_t freq;
|
|||
|
uint32_t ClkSrc = (LPC_CGU->PLL1_CTRL & CGU_CTRL_SRC_MASK)>>24;
|
|||
|
freq = CGU_ClockSourceFrequency[ClkSrc];
|
|||
|
freq *= mult;
|
|||
|
msel = mult-1;
|
|||
|
|
|||
|
LPC_CGU->PLL1_CTRL &= ~(CGU_PLL1_FBSEL_MASK |
|
|||
|
CGU_PLL1_BYPASS_MASK |
|
|||
|
CGU_PLL1_DIRECT_MASK |
|
|||
|
(0x03<<8) | (0xFF<<16) | (0x03<<12));
|
|||
|
|
|||
|
if(freq<156000000){
|
|||
|
//psel is encoded such that 0=1, 1=2, 2=4, 3=8
|
|||
|
while(2*(pval)*freq < 156000000) {
|
|||
|
psel++;
|
|||
|
pval*=2;
|
|||
|
}
|
|||
|
// if(2*(pval)*freq > 320000000) {
|
|||
|
// //THIS IS OUT OF RANGE!!!
|
|||
|
// //HOW DO WE ASSERT IN SAMPLE CODE?
|
|||
|
// //__breakpoint(0);
|
|||
|
// return CGU_ERROR_INVALID_PARAM;
|
|||
|
// }
|
|||
|
LPC_CGU->PLL1_CTRL |= (msel<<16) | (nsel<<12) | (psel<<8) | CGU_PLL1_FBSEL_MASK;
|
|||
|
}else if(freq<320000000){
|
|||
|
LPC_CGU->PLL1_CTRL |= (msel<<16) | (nsel<<12) | (psel<<8) |CGU_PLL1_DIRECT_MASK | CGU_PLL1_FBSEL_MASK;
|
|||
|
}else
|
|||
|
return CGU_ERROR_INVALID_PARAM;
|
|||
|
|
|||
|
return CGU_ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Get current base status
|
|||
|
* @param[in] Base Base type, should be:
|
|||
|
* - CGU_BASE_USB0 :Base clock for USB0
|
|||
|
* - CGU_BASE_USB1 :Base clock for USB1
|
|||
|
* - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core
|
|||
|
* and APB peripheral blocks #0 and #2
|
|||
|
* - CGU_BASE_SPIFI :Base clock for SPIFI
|
|||
|
* - CGU_BASE_APB1 :Base clock for APB peripheral block #1
|
|||
|
* - CGU_BASE_APB3 :Base clock for APB peripheral block #3
|
|||
|
* - CGU_BASE_SDIO :Base clock for SDIO card reader
|
|||
|
* - CGU_BASE_SSP0 :Base clock for SSP0
|
|||
|
* - CGU_BASE_SSP1 :Base clock for SSP1
|
|||
|
* - CGU_BASE_UART0 :Base clock for UART0
|
|||
|
* - CGU_BASE_UART1 :Base clock for UART1
|
|||
|
* - CGU_BASE_UART2 :Base clock for UART2
|
|||
|
* - CGU_BASE_UART3 :Base clock for UART3
|
|||
|
* @return Always return 0
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_GetBaseStatus(CGU_ENTITY_T Base){
|
|||
|
switch(Base){
|
|||
|
/*CCU1*/
|
|||
|
case CGU_BASE_APB3:
|
|||
|
return LPC_CCU1->BASE_STAT & 1;
|
|||
|
|
|||
|
case CGU_BASE_APB1:
|
|||
|
return (LPC_CCU1->BASE_STAT>>1) & 1;
|
|||
|
|
|||
|
case CGU_BASE_SPIFI:
|
|||
|
return (LPC_CCU1->BASE_STAT>>2) & 1;
|
|||
|
|
|||
|
case CGU_BASE_M4:
|
|||
|
return (LPC_CCU1->BASE_STAT>>3) & 1;
|
|||
|
|
|||
|
case CGU_BASE_USB0:
|
|||
|
return (LPC_CCU1->BASE_STAT>>7) & 1;
|
|||
|
|
|||
|
case CGU_BASE_USB1:
|
|||
|
return (LPC_CCU1->BASE_STAT>>8) & 1;
|
|||
|
|
|||
|
/*CCU2*/
|
|||
|
case CGU_BASE_UART3:
|
|||
|
return (LPC_CCU2->BASE_STAT>>1) & 1;
|
|||
|
|
|||
|
case CGU_BASE_UART2:
|
|||
|
return (LPC_CCU2->BASE_STAT>>2) & 1;
|
|||
|
|
|||
|
case CGU_BASE_UART1:
|
|||
|
return (LPC_CCU2->BASE_STAT>>3) & 1;
|
|||
|
|
|||
|
case CGU_BASE_UART0:
|
|||
|
return (LPC_CCU2->BASE_STAT>>4) & 1;
|
|||
|
|
|||
|
case CGU_BASE_SSP1:
|
|||
|
return (LPC_CCU2->BASE_STAT>>5) & 1;
|
|||
|
|
|||
|
case CGU_BASE_SSP0:
|
|||
|
return (LPC_CCU2->BASE_STAT>>6) & 1;
|
|||
|
|
|||
|
case CGU_BASE_SDIO:
|
|||
|
return (LPC_CCU2->BASE_STAT>>7) & 1;
|
|||
|
|
|||
|
/*BASE SAFE is used by WWDT and RGU*/
|
|||
|
case CGU_BASE_SAFE:
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Compare one source clock to IRC clock
|
|||
|
* @param[in] Clock Clock entity that will be compared to IRC, should be:
|
|||
|
* - CGU_CLKSRC_32KHZ_OSC :32Khz crystal oscillator
|
|||
|
* - CGU_CLKSRC_ENET_RX_CLK :Ethernet receive clock
|
|||
|
* - CGU_CLKSRC_ENET_TX_CLK :Ethernet transmit clock
|
|||
|
* - CGU_CLKSRC_GP_CLKIN :General purpose input clock
|
|||
|
* - CGU_CLKSRC_XTAL_OSC :Crystal oscillator
|
|||
|
* - CGU_CLKSRC_PLL0 :PLL0 clock
|
|||
|
* - CGU_CLKSRC_PLL1 :PLL1 clock
|
|||
|
* - CGU_CLKSRC_IDIVA :Integer divider register A
|
|||
|
* - CGU_CLKSRC_IDIVB :Integer divider register B
|
|||
|
* - CGU_CLKSRC_IDIVC :Integer divider register C
|
|||
|
* - CGU_CLKSRC_IDIVD :Integer divider register D
|
|||
|
* - CGU_CLKSRC_IDIVE :Integer divider register E
|
|||
|
* - CGU_BASE_SAFE :Base safe clock (always on)for WDT
|
|||
|
* - CGU_BASE_USB0 :Base clock for USB0
|
|||
|
* - CGU_BASE_USB1 :Base clock for USB1
|
|||
|
* - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core
|
|||
|
* and APB peripheral blocks #0 and #2
|
|||
|
* - CGU_BASE_SPIFI :Base clock for SPIFI
|
|||
|
* - CGU_BASE_PHY_RX :Base clock for Ethernet PHY Rx
|
|||
|
* - CGU_BASE_PHY_TX :Base clock for Ethernet PHY Tx
|
|||
|
* - CGU_BASE_APB1 :Base clock for APB peripheral block #1
|
|||
|
* - CGU_BASE_APB3 :Base clock for APB peripheral block #3
|
|||
|
* - CGU_BASE_LCD :Base clock for LCD
|
|||
|
* - CGU_BASE_SDIO :Base clock for SDIO card reader
|
|||
|
* - CGU_BASE_SSP0 :Base clock for SSP0
|
|||
|
* - CGU_BASE_SSP1 :Base clock for SSP1
|
|||
|
* - CGU_BASE_UART0 :Base clock for UART0
|
|||
|
* - CGU_BASE_UART1 :Base clock for UART1
|
|||
|
* - CGU_BASE_UART2 :Base clock for UART2
|
|||
|
* - CGU_BASE_UART3 :Base clock for UART3
|
|||
|
* - CGU_BASE_CLKOUT :Base clock for CLKOUT pin
|
|||
|
* @param[in] m Multiple value pointer
|
|||
|
* @param[in] d Divider value pointer
|
|||
|
* @return Compare status, could be:
|
|||
|
* - (-1): fail
|
|||
|
* - 0: successful
|
|||
|
* @note Formula used to compare:
|
|||
|
* FClock = F_IRC* m / d
|
|||
|
**********************************************************************/
|
|||
|
int CGU_FrequencyMonitor(CGU_ENTITY_T Clock, uint32_t *m, uint32_t *d){
|
|||
|
uint32_t n,c,temp;
|
|||
|
int i;
|
|||
|
|
|||
|
/* Maximum allow RCOUNT number */
|
|||
|
c= 511;
|
|||
|
/* Check Source Clock Freq is larger or smaller */
|
|||
|
LPC_CGU->FREQ_MON = (Clock<<24) | 1<<23 | c;
|
|||
|
while(LPC_CGU->FREQ_MON & (1 <<23));
|
|||
|
for(i=0;i<10000;i++);
|
|||
|
temp = (LPC_CGU->FREQ_MON >>9) & 0x3FFF;
|
|||
|
|
|||
|
if(temp == 0) /* too low F < 12000000/511*/
|
|||
|
return -1;
|
|||
|
if(temp > 511){ /* larger */
|
|||
|
|
|||
|
c = 511 - (LPC_CGU->FREQ_MON&0x1FF);
|
|||
|
}else{
|
|||
|
do{
|
|||
|
c--;
|
|||
|
LPC_CGU->FREQ_MON = (Clock<<24) | 1<<23 | c;
|
|||
|
while(LPC_CGU->FREQ_MON & (1 <<23));
|
|||
|
for(i=0;i<10000;i++);
|
|||
|
n = (LPC_CGU->FREQ_MON >>9) & 0x3FFF;
|
|||
|
}while(n==temp);
|
|||
|
c++;
|
|||
|
}
|
|||
|
*m = temp;
|
|||
|
*d = c;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************//**
|
|||
|
* @brief Compare one source clock to another source clock
|
|||
|
* @param[in] Clock Clock entity that will be compared to second source, should be:
|
|||
|
* - CGU_CLKSRC_32KHZ_OSC :32Khz crystal oscillator
|
|||
|
* - CGU_CLKSRC_ENET_RX_CLK :Ethernet receive clock
|
|||
|
* - CGU_CLKSRC_ENET_TX_CLK :Ethernet transmit clock
|
|||
|
* - CGU_CLKSRC_GP_CLKIN :General purpose input clock
|
|||
|
* - CGU_CLKSRC_XTAL_OSC :Crystal oscillator
|
|||
|
* - CGU_CLKSRC_PLL0 :PLL0 clock
|
|||
|
* - CGU_CLKSRC_PLL1 :PLL1 clock
|
|||
|
* - CGU_CLKSRC_IDIVA :Integer divider register A
|
|||
|
* - CGU_CLKSRC_IDIVB :Integer divider register B
|
|||
|
* - CGU_CLKSRC_IDIVC :Integer divider register C
|
|||
|
* - CGU_CLKSRC_IDIVD :Integer divider register D
|
|||
|
* - CGU_CLKSRC_IDIVE :Integer divider register E
|
|||
|
* - CGU_BASE_SAFE :Base safe clock (always on)for WDT
|
|||
|
* - CGU_BASE_USB0 :Base clock for USB0
|
|||
|
* - CGU_BASE_USB1 :Base clock for USB1
|
|||
|
* - CGU_BASE_M4 :System base clock for ARM Cortex-M3 core
|
|||
|
* and APB peripheral blocks #0 and #2
|
|||
|
* - CGU_BASE_SPIFI :Base clock for SPIFI
|
|||
|
* - CGU_BASE_PHY_RX :Base clock for Ethernet PHY Rx
|
|||
|
* - CGU_BASE_PHY_TX :Base clock for Ethernet PHY Tx
|
|||
|
* - CGU_BASE_APB1 :Base clock for APB peripheral block #1
|
|||
|
* - CGU_BASE_APB3 :Base clock for APB peripheral block #3
|
|||
|
* - CGU_BASE_LCD :Base clock for LCD
|
|||
|
* - CGU_BASE_SDIO :Base clock for SDIO card reader
|
|||
|
* - CGU_BASE_SSP0 :Base clock for SSP0
|
|||
|
* - CGU_BASE_SSP1 :Base clock for SSP1
|
|||
|
* - CGU_BASE_UART0 :Base clock for UART0
|
|||
|
* - CGU_BASE_UART1 :Base clock for UART1
|
|||
|
* - CGU_BASE_UART2 :Base clock for UART2
|
|||
|
* - CGU_BASE_UART3 :Base clock for UART3
|
|||
|
* - CGU_BASE_CLKOUT :Base clock for CLKOUT pin
|
|||
|
* @param[in] CompareToClock Clock source that to be compared to first source, should be different
|
|||
|
* to first source.
|
|||
|
* @param[in] m Multiple value pointer
|
|||
|
* @param[in] d Divider value pointer
|
|||
|
* @return Compare status, could be:
|
|||
|
* - (-1): fail
|
|||
|
* - 0: successful
|
|||
|
* @note Formula used to compare:
|
|||
|
* FClock = m*FCompareToClock/d
|
|||
|
**********************************************************************/
|
|||
|
uint32_t CGU_RealFrequencyCompare(CGU_ENTITY_T Clock, CGU_ENTITY_T CompareToClock, uint32_t *m, uint32_t *d){
|
|||
|
uint32_t m1,m2,d1,d2;
|
|||
|
/* Check Parameter */
|
|||
|
if((Clock>CGU_CLKSRC_IDIVE) || (CompareToClock>CGU_CLKSRC_IDIVE))
|
|||
|
return CGU_ERROR_INVALID_PARAM;
|
|||
|
/* Check for Clock Enable - Not yet implement
|
|||
|
* The Comparator will hang if Clock has not been set*/
|
|||
|
CGU_FrequencyMonitor(Clock, &m1, &d1);
|
|||
|
CGU_FrequencyMonitor(CompareToClock, &m2, &d2);
|
|||
|
*m= m1*d2;
|
|||
|
*d= d1*m2;
|
|||
|
return 0;
|
|||
|
|
|||
|
}
|
|||
|
/**
|
|||
|
* @}
|
|||
|
*/
|
|||
|
|
|||
|
/**
|
|||
|
* @}
|
|||
|
*/
|
|||
|
|