Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Revision:
0:01f31e923fe2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/hic_hal/nxp/lpc4322/lpc43xx_cgu.c	Tue Apr 07 12:55:42 2020 +0200
@@ -0,0 +1,1132 @@
+/**
+ * @file    lpc43xx_cgu.c
+ * @brief   
+ *
+ * DAPLink Interface Firmware
+ * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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 Rough approximation of a delay function with microsecond resolution.
+ *
+ * Used during initial clock setup as the Timers are not configured yet.
+ *
+ * @param [in] us  The number of microseconds to wait
+ *
+ *****************************************************************************/
+static void cgu_WaitUS(volatile uint32_t us)
+{
+    us *= (SystemCoreClock / 1000000) / 3;
+
+    while (us--);
+}
+
+/**************************************************************************//**
+ *
+ * @brief Simple lookup of best MSEL and NSEL values for wanted frequency
+ *
+ * Not optimized.
+ *
+ * @param [in]  wantedFreq  The wanted PLL1 frequency
+ * @param [out] pMsel       The best MSEL value for the PLL1_CTRL register
+ * @param [out] pNsel       The best NSEL value for the PLL1_CTRL register
+ *
+ *****************************************************************************/
+static void cgu_findMN(uint32_t wantedFreq, uint32_t *pMsel, uint32_t *pNsel)
+{
+    uint32_t besterr = wantedFreq;
+    uint32_t m, n, f, tmp, err;
+#define ABSDIFF(__a, __b) ( ((__a) < (__b)) ? ((__b) - (__a)) : ((__a) - (__b)) )
+
+    for (n = 1; n <= 4; n++) {
+        f = 12000000 / n;
+        tmp = 0;
+
+        for (m = 1; m <= 256; m++) {
+            tmp += f;
+            err = ABSDIFF(tmp, wantedFreq);
+
+            if (err == 0) {
+                // found perfect match
+                *pMsel = m - 1;
+                *pNsel = n - 1;
+                return;
+
+            } else if (err < besterr) {
+                *pMsel = m - 1;
+                *pNsel = n - 1;
+                besterr = err;
+            }
+
+            if (tmp > wantedFreq) {
+                // no point in continuing to increase tmp as value is too high already
+                break;
+            }
+        }
+    }
+}
+
+/*********************************************************************//**
+ * @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(uint32_t wantedFreq)
+{
+    uint32_t msel = 0;
+    uint32_t nsel = 0;
+    uint32_t tmp;
+    // Setup PLL1 to 204MHz
+    // 0. Select IRC as BASE_M4_CLK source
+    CGU_EntityConnect(CGU_CLKSRC_IRC, CGU_BASE_M4);
+    SystemCoreClock = 96000000;
+    // 1. Enable the crystal oscillator
+    CGU_SetXTALOSC(12000000);
+    CGU_EnableEntity(CGU_CLKSRC_XTAL_OSC, ENABLE);
+    // 2. Wait 250us
+    cgu_WaitUS(250);
+    // 3. Reconfigure PLL1 as follows:
+    //    - Select the M and N divider values to produce the final desired
+    //      PLL1 output frequency (204MHz => M=17,N=1 => msel=16,nsel=0)
+    //    - Select the crystal oscillator as clock source for PLL1
+    cgu_findMN(wantedFreq, &msel, &nsel);
+    tmp = LPC_CGU->PLL1_CTRL & ~((0xFF << 16) | (0x03 << 12));
+    LPC_CGU->PLL1_CTRL = tmp | (msel << 16) | (nsel << 12);
+    CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL1);
+
+    // 4. Wait for the PLL1 to lock
+    while ((LPC_CGU->PLL1_STAT & 1) == 0x0);
+
+    // 5. Set PLL1 P-divider to divide by 2 (DIRECT=0 and PSEL=0)
+    LPC_CGU->PLL1_CTRL &= ~((0x03 << 8) | CGU_PLL1_DIRECT_MASK);
+    // 6. Select PLL1 as BASE_M4_CLK source. The BASE_M4_CLK now operates at
+    //    the mid frequency range
+    CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_M4);
+    SystemCoreClock = (12000000 * (msel + 1)) / ((nsel + 1) * 2);
+    // 7. Wait 20us
+    cgu_WaitUS(20);
+    // 8. Set PLL P-divider to direct output mode (DIRECT=1)
+    LPC_CGU->PLL1_CTRL |= CGU_PLL1_DIRECT_MASK;
+    // The BASE_M4_CLK now operates in the high frequency range
+    CGU_UpdateClock();
+    SystemCoreClock = (12000000 * (msel + 1)) / (nsel + 1);
+    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;
+}
+