Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lpc43xx_cgu.c Source File

lpc43xx_cgu.c

Go to the documentation of this file.
00001 /**
00002  * @file    lpc43xx_cgu.c
00003  * @brief   
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include "lpc_types.h"
00023 #include "lpc43xx_scu.h"
00024 #include "lpc43xx_cgu.h"
00025 
00026 /** This define used to fix mistake when run with IAR compiler */
00027 #ifdef __ICCARM__
00028 #define CGU_BRANCH_STATUS_ENABLE_MASK  0x80000001
00029 #else
00030 #define CGU_BRANCH_STATUS_ENABLE_MASK  0x01
00031 #endif
00032 
00033 /*TODO List:
00034  * SET PLL0
00035  * UPDATE Clock from PLL0
00036  * SetDIV uncheck value
00037  * GetBaseStatus BASE_SAFE
00038  * */
00039 /* Local definition */
00040 #define CGU_ADDRESS32(x,y) (*(uint32_t*)((uint32_t)x+y))
00041 
00042 /* Local Variable */
00043 const int16_t CGU_Entity_ControlReg_Offset[CGU_ENTITY_NUM] = {
00044     -1,     //CGU_CLKSRC_32KHZ_OSC,
00045     -1,     //CGU_CLKSRC_IRC,
00046     -1,     //CGU_CLKSRC_ENET_RX_CLK,
00047     -1,     //CGU_CLKSRC_ENET_TX_CLK,
00048     -1,     //CGU_CLKSRC_GP_CLKIN,
00049     -1,     //CGU_CLKSRC_TCK,
00050     0x18,   //CGU_CLKSRC_XTAL_OSC,
00051     0x20,   //CGU_CLKSRC_PLL0,
00052     0x30,   //CGU_CLKSRC_PLL0_AUDIO **REV A**
00053     0x44,   //CGU_CLKSRC_PLL1,
00054     -1,     //CGU_CLKSRC_RESERVE,
00055     -1,     //CGU_CLKSRC_RESERVE,
00056     0x48,   //CGU_CLKSRC_IDIVA,,
00057     0x4C,   //CGU_CLKSRC_IDIVB,
00058     0x50,   //CGU_CLKSRC_IDIVC,
00059     0x54,   //CGU_CLKSRC_IDIVD,
00060     0x58,   //CGU_CLKSRC_IDIVE,
00061 
00062     0x5C,   //CGU_BASE_SAFE,
00063     0x60,   //CGU_BASE_USB0,
00064     0x64,   //CGU_BASE_PERIPH,  // used for SPGPIO, peripheral control
00065     0x68,   //CGU_BASE_USB1,
00066     0x6C,   //CGU_BASE_M4,
00067     0x70,   //CGU_BASE_SPIFI,
00068     -1,     //CGU_BASE_RESERVE,
00069     0x78,   //CGU_BASE_PHY_RX,
00070     0x7C,   //CGU_BASE_PHY_TX,
00071     0x80,   //CGU_BASE_APB1,
00072     0x84,   //CGU_BASE_APB3,
00073     0x88,   //CGU_BASE_LCD,
00074     0X8C,   //CGU_BASE_ENET_CSR, **REV A**
00075     0x90,   //CGU_BASE_SDIO,
00076     0x94,   //CGU_BASE_SSP0,
00077     0x98,   //CGU_BASE_SSP1,
00078     0x9C,   //CGU_BASE_UART0,
00079     0xA0,   //CGU_BASE_UART1,
00080     0xA4,   //CGU_BASE_UART2,
00081     0xA8,   //CGU_BASE_UART3,
00082     0xAC,   //CGU_BASE_CLKOUT
00083     -1,
00084     -1,
00085     -1,
00086     -1,
00087     0xC0,   //CGU_BASE_APLL
00088     0xC4,   //CGU_BASE_OUT0
00089     0xC8    //CGU_BASE_OUT1
00090 };
00091 
00092 const uint8_t CGU_ConnectAlloc_Tbl[CGU_CLKSRC_NUM][CGU_ENTITY_NUM] = {
00093 //       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
00094 //       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
00095 //         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
00096     {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,*/
00097     {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,*/
00098     {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,*/
00099     {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,*/
00100     {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,*/
00101     {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,*/
00102     {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,*/
00103     {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,*/
00104     {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,*/
00105     {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,*/
00106     {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},
00107     {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},
00108     {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,*/
00109     {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,*/
00110     {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,*/
00111     {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,*/
00112     {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,*/
00113 };
00114 
00115 const CGU_PERIPHERAL_S CGU_PERIPHERAL_Info[CGU_PERIPHERAL_NUM] = {
00116     /*  Register Clock          |   Peripheral Clock
00117     |   BASE    |   BRANCH  |   BASE    |   BRANCH      */
00118     {CGU_BASE_APB3, 0x1118, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_ADC0,
00119     {CGU_BASE_APB3, 0x1120, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_ADC1,
00120     {CGU_BASE_M4,   0x1460, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_AES,
00121     ////    CGU_PERIPHERAL_ALARMTIMER_CGU_RGU_RTC_WIC,
00122     {CGU_BASE_APB1, 0x1200, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_APB1_BUS,
00123     {CGU_BASE_APB3, 0x1100, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_APB3_BUS,
00124     {CGU_BASE_APB3, 0x1128, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_CAN0,
00125     {CGU_BASE_M4,   0x1538, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_CREG,
00126     {CGU_BASE_APB3, 0x1110, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_DAC,
00127     {CGU_BASE_M4,   0x1440, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_DMA,
00128     {CGU_BASE_M4,   0x1430, CGU_BASE_M4,        0x1478, 0},//CGU_PERIPHERAL_EMC,
00129     {CGU_BASE_M4,   0x1420, CGU_BASE_PHY_RX,    0x0000, CGU_PERIPHERAL_ETHERNET_TX},//CGU_PERIPHERAL_ETHERNET,
00130     {CGU_ENTITY_NONE, 0x0000, CGU_BASE_PHY_TX,  0x0000, 0}, //CGU_PERIPHERAL_ETHERNET_TX
00131     {CGU_BASE_M4,   0x1410, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_GPIO,
00132     {CGU_BASE_APB1, 0x1210, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_I2C0,
00133     {CGU_BASE_APB3, 0x1108, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_I2C1,
00134     {CGU_BASE_APB1, 0x1218, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_I2S,
00135     {CGU_BASE_M4,   0x1418, CGU_BASE_LCD,   0x0000, 0},//CGU_PERIPHERAL_LCD,
00136     {CGU_BASE_M4,   0x1448, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_M3CORE,
00137     {CGU_BASE_M4,   0x1400, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_M3_BUS,
00138     {CGU_BASE_APB1, 0x1208, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_MOTOCON,
00139     {CGU_BASE_M4,   0x1630, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_QEI,
00140     {CGU_BASE_M4,   0x1600, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_RITIMER,
00141     {CGU_BASE_M4,   0x1468, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_SCT,
00142     {CGU_BASE_M4,   0x1530, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_SCU,
00143     {CGU_BASE_M4,   0x1438, CGU_BASE_SDIO,  0x2800, 0},//CGU_PERIPHERAL_SDIO,
00144     {CGU_BASE_M4,   0x1408, CGU_BASE_SPIFI, 0x1300, 0},//CGU_PERIPHERAL_SPIFI,
00145     {CGU_BASE_M4,   0x1518, CGU_BASE_SSP0,  0x2700, 0},//CGU_PERIPHERAL_SSP0,
00146     {CGU_BASE_M4,   0x1628, CGU_BASE_SSP1,  0x2600, 0},//CGU_PERIPHERAL_SSP1,
00147     {CGU_BASE_M4,   0x1520, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_TIMER0,
00148     {CGU_BASE_M4,   0x1528, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_TIMER1,
00149     {CGU_BASE_M4,   0x1618, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_TIMER2,
00150     {CGU_BASE_M4,   0x1620, CGU_ENTITY_NONE,    0x0000, 0},//CGU_PERIPHERAL_TIMER3,
00151     {CGU_BASE_M4,   0x1508, CGU_BASE_UART0, 0x2500, 0},//CGU_PERIPHERAL_UART0,
00152     {CGU_BASE_M4,   0x1510, CGU_BASE_UART1, 0x2400, 0},//CGU_PERIPHERAL_UART1,
00153     {CGU_BASE_M4,   0x1608, CGU_BASE_UART2, 0x2300, 0},//CGU_PERIPHERAL_UART2,
00154     {CGU_BASE_M4,   0x1610, CGU_BASE_UART3, 0x2200, 0},//CGU_PERIPHERAL_UART3,
00155     {CGU_BASE_M4,   0x1428, CGU_BASE_USB0,  0x1800, 0},//CGU_PERIPHERAL_USB0,
00156     {CGU_BASE_M4,   0x1470, CGU_BASE_USB1,  0x1900, 0},//CGU_PERIPHERAL_USB1,
00157     {CGU_BASE_M4,   0x1500, CGU_BASE_SAFE,  0x0000, 0},//CGU_PERIPHERAL_WWDT,
00158 };
00159 
00160 uint32_t CGU_ClockSourceFrequency[CGU_CLKSRC_NUM] = {0, 12000000, 0, 0, 0, 0, 0, 480000000, 0, 0, 0, 0, 0, 0, 0, 0, 0};
00161 
00162 #define CGU_CGU_ADDR    ((uint32_t)LPC_CGU)
00163 #define CGU_REG_BASE_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_Entity_ControlReg_Offset[CGU_PERIPHERAL_Info[x].RegBaseEntity]))
00164 #define CGU_REG_BRANCH_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].RegBranchOffset))
00165 #define CGU_REG_BRANCH_STATUS(x) (*(volatile uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].RegBranchOffset+4))
00166 
00167 #define CGU_PER_BASE_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_Entity_ControlReg_Offset[CGU_PERIPHERAL_Info[x].PerBaseEntity]))
00168 #define CGU_PER_BRANCH_CTRL(x) (*(uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].PerBranchOffset))
00169 #define CGU_PER_BRANCH_STATUS(x) (*(volatile uint32_t*)(CGU_CGU_ADDR+CGU_PERIPHERAL_Info[x].PerBranchOffset+4))
00170 
00171 /**************************************************************************//**
00172  *
00173  * @brief Rough approximation of a delay function with microsecond resolution.
00174  *
00175  * Used during initial clock setup as the Timers are not configured yet.
00176  *
00177  * @param [in] us  The number of microseconds to wait
00178  *
00179  *****************************************************************************/
00180 static void cgu_WaitUS(volatile uint32_t us)
00181 {
00182     us *= (SystemCoreClock / 1000000) / 3;
00183 
00184     while (us--);
00185 }
00186 
00187 /**************************************************************************//**
00188  *
00189  * @brief Simple lookup of best MSEL and NSEL values for wanted frequency
00190  *
00191  * Not optimized.
00192  *
00193  * @param [in]  wantedFreq  The wanted PLL1 frequency
00194  * @param [out] pMsel       The best MSEL value for the PLL1_CTRL register
00195  * @param [out] pNsel       The best NSEL value for the PLL1_CTRL register
00196  *
00197  *****************************************************************************/
00198 static void cgu_findMN(uint32_t wantedFreq, uint32_t *pMsel, uint32_t *pNsel)
00199 {
00200     uint32_t besterr = wantedFreq;
00201     uint32_t m, n, f, tmp, err;
00202 #define ABSDIFF(__a, __b) ( ((__a) < (__b)) ? ((__b) - (__a)) : ((__a) - (__b)) )
00203 
00204     for (n = 1; n <= 4; n++) {
00205         f = 12000000 / n;
00206         tmp = 0;
00207 
00208         for (m = 1; m <= 256; m++) {
00209             tmp += f;
00210             err = ABSDIFF(tmp, wantedFreq);
00211 
00212             if (err == 0) {
00213                 // found perfect match
00214                 *pMsel = m - 1;
00215                 *pNsel = n - 1;
00216                 return;
00217 
00218             } else if (err < besterr) {
00219                 *pMsel = m - 1;
00220                 *pNsel = n - 1;
00221                 besterr = err;
00222             }
00223 
00224             if (tmp > wantedFreq) {
00225                 // no point in continuing to increase tmp as value is too high already
00226                 break;
00227             }
00228         }
00229     }
00230 }
00231 
00232 /*********************************************************************//**
00233  * @brief       Initialize default clock for LPC4300 Eval board
00234  * @param[in]   None
00235  * @return      Initialize status, could be:
00236  *                  - CGU_ERROR_SUCCESS: successful
00237  *                  - Other: error
00238  **********************************************************************/
00239 uint32_t    CGU_Init(uint32_t wantedFreq)
00240 {
00241     uint32_t msel = 0;
00242     uint32_t nsel = 0;
00243     uint32_t tmp;
00244     // Setup PLL1 to 204MHz
00245     // 0. Select IRC as BASE_M4_CLK source
00246     CGU_EntityConnect(CGU_CLKSRC_IRC, CGU_BASE_M4);
00247     SystemCoreClock = 96000000;
00248     // 1. Enable the crystal oscillator
00249     CGU_SetXTALOSC(12000000);
00250     CGU_EnableEntity(CGU_CLKSRC_XTAL_OSC, ENABLE);
00251     // 2. Wait 250us
00252     cgu_WaitUS(250);
00253     // 3. Reconfigure PLL1 as follows:
00254     //    - Select the M and N divider values to produce the final desired
00255     //      PLL1 output frequency (204MHz => M=17,N=1 => msel=16,nsel=0)
00256     //    - Select the crystal oscillator as clock source for PLL1
00257     cgu_findMN(wantedFreq, &msel, &nsel);
00258     tmp = LPC_CGU->PLL1_CTRL & ~((0xFF << 16) | (0x03 << 12));
00259     LPC_CGU->PLL1_CTRL = tmp | (msel << 16) | (nsel << 12);
00260     CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL1);
00261 
00262     // 4. Wait for the PLL1 to lock
00263     while ((LPC_CGU->PLL1_STAT & 1) == 0x0);
00264 
00265     // 5. Set PLL1 P-divider to divide by 2 (DIRECT=0 and PSEL=0)
00266     LPC_CGU->PLL1_CTRL &= ~((0x03 << 8) | CGU_PLL1_DIRECT_MASK);
00267     // 6. Select PLL1 as BASE_M4_CLK source. The BASE_M4_CLK now operates at
00268     //    the mid frequency range
00269     CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_M4);
00270     SystemCoreClock = (12000000 * (msel + 1)) / ((nsel + 1) * 2);
00271     // 7. Wait 20us
00272     cgu_WaitUS(20);
00273     // 8. Set PLL P-divider to direct output mode (DIRECT=1)
00274     LPC_CGU->PLL1_CTRL |= CGU_PLL1_DIRECT_MASK;
00275     // The BASE_M4_CLK now operates in the high frequency range
00276     CGU_UpdateClock();
00277     SystemCoreClock = (12000000 * (msel + 1)) / (nsel + 1);
00278     return 0;
00279 }
00280 
00281 /*********************************************************************//**
00282  * @brief       Configure power for individual peripheral
00283  * @param[in]   PPType  peripheral type, should be:
00284  *                  - CGU_PERIPHERAL_ADC0       :ADC0
00285  *                  - CGU_PERIPHERAL_ADC1       :ADC1
00286  *                  - CGU_PERIPHERAL_AES        :AES
00287  *                  - CGU_PERIPHERAL_APB1_BUS   :APB1 bus
00288  *                  - CGU_PERIPHERAL_APB3_BUS   :APB3 bus
00289  *                  - CGU_PERIPHERAL_CAN        :CAN
00290  *                  - CGU_PERIPHERAL_CREG       :CREG
00291  *                  - CGU_PERIPHERAL_DAC        :DAC
00292  *                  - CGU_PERIPHERAL_DMA        :DMA
00293  *                  - CGU_PERIPHERAL_EMC        :EMC
00294  *                  - CGU_PERIPHERAL_ETHERNET   :ETHERNET
00295  *                  - CGU_PERIPHERAL_GPIO       :GPIO
00296  *                  - CGU_PERIPHERAL_I2C0       :I2C0
00297  *                  - CGU_PERIPHERAL_I2C1       :I2C1
00298  *                  - CGU_PERIPHERAL_I2S        :I2S
00299  *                  - CGU_PERIPHERAL_LCD        :LCD
00300  *                  - CGU_PERIPHERAL_M3CORE     :M3 core
00301  *                  - CGU_PERIPHERAL_M3_BUS     :M3 bus
00302  *                  - CGU_PERIPHERAL_MOTOCON    :Motor control
00303  *                  - CGU_PERIPHERAL_QEI        :QEI
00304  *                  - CGU_PERIPHERAL_RITIMER    :RIT timer
00305  *                  - CGU_PERIPHERAL_SCT        :SCT
00306  *                  - CGU_PERIPHERAL_SCU        :SCU
00307  *                  - CGU_PERIPHERAL_SDIO       :SDIO
00308  *                  - CGU_PERIPHERAL_SPIFI      :SPIFI
00309  *                  - CGU_PERIPHERAL_SSP0       :SSP0
00310  *                  - CGU_PERIPHERAL_SSP1       :SSP1
00311  *                  - CGU_PERIPHERAL_TIMER0     :TIMER0
00312  *                  - CGU_PERIPHERAL_TIMER1     :TIMER1
00313  *                  - CGU_PERIPHERAL_TIMER2     :TIMER2
00314  *                  - CGU_PERIPHERAL_TIMER3     :TIMER3
00315  *                  - CGU_PERIPHERAL_UART0      :UART0
00316  *                  - CGU_PERIPHERAL_UART1      :UART1
00317  *                  - CGU_PERIPHERAL_UART2      :UART2
00318  *                  - CGU_PERIPHERAL_UART3      :UART3
00319  *                  - CGU_PERIPHERAL_USB0       :USB0
00320  *                  - CGU_PERIPHERAL_USB1       :USB1
00321  *                  - CGU_PERIPHERAL_WWDT       :WWDT
00322  * @param[in]   en status, should be:
00323  *                  - ENABLE: Enable power
00324  *                  - DISABLE: Disable power
00325  * @return      Configure status, could be:
00326  *                  - CGU_ERROR_SUCCESS: successful
00327  *                  - Other: error
00328  **********************************************************************/
00329 uint32_t CGU_ConfigPWR(CGU_PERIPHERAL_T  PPType,  FunctionalState en)
00330 {
00331     if (PPType >= CGU_PERIPHERAL_WWDT && PPType <= CGU_PERIPHERAL_ADC0) {
00332         return CGU_ERROR_INVALID_PARAM;
00333     }
00334 
00335     if (en == DISABLE) { /* Going to disable clock */
00336         /*Get Reg branch status */
00337         if (CGU_PERIPHERAL_Info[PPType].RegBranchOffset != 0 &&
00338                 CGU_REG_BRANCH_STATUS(PPType) & 1) {
00339             CGU_REG_BRANCH_CTRL(PPType) &= ~1; /* Disable branch clock */
00340 
00341             while (CGU_REG_BRANCH_STATUS(PPType) & 1);
00342         }
00343 
00344         /* GetBase Status*/
00345         if ((CGU_PERIPHERAL_Info[PPType].RegBaseEntity != CGU_ENTITY_NONE) &&
00346                 CGU_GetBaseStatus((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity) == 0) {
00347             /* Disable Base */
00348             CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity, 0);
00349         }
00350 
00351         /* Same for Peripheral */
00352         if ((CGU_PERIPHERAL_Info[PPType].PerBranchOffset != 0) && (CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)) {
00353             CGU_PER_BRANCH_CTRL(PPType) &= ~1; /* Disable branch clock */
00354 
00355             while (CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK);
00356         }
00357 
00358         /* GetBase Status*/
00359         if ((CGU_PERIPHERAL_Info[PPType].PerBaseEntity != CGU_ENTITY_NONE) &&
00360                 CGU_GetBaseStatus((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity) == 0) {
00361             /* Disable Base */
00362             CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity, 0);
00363         }
00364 
00365     } else {
00366         /* enable */
00367         /* GetBase Status*/
00368         if ((CGU_PERIPHERAL_Info[PPType].RegBaseEntity != CGU_ENTITY_NONE) && CGU_REG_BASE_CTRL(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK) {
00369             /* Enable Base */
00370             CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].RegBaseEntity, 1);
00371         }
00372 
00373         /*Get Reg branch status */
00374         if ((CGU_PERIPHERAL_Info[PPType].RegBranchOffset != 0) && !(CGU_REG_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)) {
00375             CGU_REG_BRANCH_CTRL(PPType) |= 1; /* Enable branch clock */
00376 
00377             while (!(CGU_REG_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK));
00378         }
00379 
00380         /* Same for Peripheral */
00381         /* GetBase Status*/
00382         if ((CGU_PERIPHERAL_Info[PPType].PerBaseEntity != CGU_ENTITY_NONE) &&
00383                 (CGU_PER_BASE_CTRL(PPType) & 1)) {
00384             /* Enable Base */
00385             CGU_EnableEntity((CGU_ENTITY_T)CGU_PERIPHERAL_Info[PPType].PerBaseEntity, 1);
00386         }
00387 
00388         /*Get Reg branch status */
00389         if ((CGU_PERIPHERAL_Info[PPType].PerBranchOffset != 0) && !(CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK)) {
00390             CGU_PER_BRANCH_CTRL(PPType) |= 1; /* Enable branch clock */
00391 
00392             while (!(CGU_PER_BRANCH_STATUS(PPType) & CGU_BRANCH_STATUS_ENABLE_MASK));
00393         }
00394     }
00395 
00396     if (CGU_PERIPHERAL_Info[PPType].next) {
00397         return CGU_ConfigPWR((CGU_PERIPHERAL_T )CGU_PERIPHERAL_Info[PPType].next, en);
00398     }
00399 
00400     return CGU_ERROR_SUCCESS;
00401 }
00402 
00403 
00404 /*********************************************************************//**
00405  * @brief       Get peripheral clock frequency
00406  * @param[in]   Clock   Peripheral type, should be:
00407  *                  - CGU_PERIPHERAL_ADC0       :ADC0
00408  *                  - CGU_PERIPHERAL_ADC1       :ADC1
00409  *                  - CGU_PERIPHERAL_AES        :AES
00410  *                  - CGU_PERIPHERAL_APB1_BUS   :APB1 bus
00411  *                  - CGU_PERIPHERAL_APB3_BUS   :APB3 bus
00412  *                  - CGU_PERIPHERAL_CAN        :CAN
00413  *                  - CGU_PERIPHERAL_CREG       :CREG
00414  *                  - CGU_PERIPHERAL_DAC        :DAC
00415  *                  - CGU_PERIPHERAL_DMA        :DMA
00416  *                  - CGU_PERIPHERAL_EMC        :EMC
00417  *                  - CGU_PERIPHERAL_ETHERNET   :ETHERNET
00418  *                  - CGU_PERIPHERAL_GPIO       :GPIO
00419  *                  - CGU_PERIPHERAL_I2C0       :I2C0
00420  *                  - CGU_PERIPHERAL_I2C1       :I2C1
00421  *                  - CGU_PERIPHERAL_I2S        :I2S
00422  *                  - CGU_PERIPHERAL_LCD        :LCD
00423  *                  - CGU_PERIPHERAL_M3CORE     :M3 core
00424  *                  - CGU_PERIPHERAL_M3_BUS     :M3 bus
00425  *                  - CGU_PERIPHERAL_MOTOCON    :Motor control
00426  *                  - CGU_PERIPHERAL_QEI        :QEI
00427  *                  - CGU_PERIPHERAL_RITIMER    :RIT timer
00428  *                  - CGU_PERIPHERAL_SCT        :SCT
00429  *                  - CGU_PERIPHERAL_SCU        :SCU
00430  *                  - CGU_PERIPHERAL_SDIO       :SDIO
00431  *                  - CGU_PERIPHERAL_SPIFI      :SPIFI
00432  *                  - CGU_PERIPHERAL_SSP0       :SSP0
00433  *                  - CGU_PERIPHERAL_SSP1       :SSP1
00434  *                  - CGU_PERIPHERAL_TIMER0     :TIMER0
00435  *                  - CGU_PERIPHERAL_TIMER1     :TIMER1
00436  *                  - CGU_PERIPHERAL_TIMER2     :TIMER2
00437  *                  - CGU_PERIPHERAL_TIMER3     :TIMER3
00438  *                  - CGU_PERIPHERAL_UART0      :UART0
00439  *                  - CGU_PERIPHERAL_UART1      :UART1
00440  *                  - CGU_PERIPHERAL_UART2      :UART2
00441  *                  - CGU_PERIPHERAL_UART3      :UART3
00442  *                  - CGU_PERIPHERAL_USB0       :USB0
00443  *                  - CGU_PERIPHERAL_USB1       :USB1
00444  *                  - CGU_PERIPHERAL_WWDT       :WWDT
00445  * @return      Return frequently value
00446  **********************************************************************/
00447 uint32_t CGU_GetPCLKFrequency(CGU_PERIPHERAL_T  Clock)
00448 {
00449     uint32_t ClkSrc;
00450 
00451     if (Clock >= CGU_PERIPHERAL_WWDT && Clock <= CGU_PERIPHERAL_ADC0) {
00452         return CGU_ERROR_INVALID_PARAM;
00453     }
00454 
00455     if (CGU_PERIPHERAL_Info[Clock].PerBaseEntity != CGU_ENTITY_NONE) {
00456         /* Get Base Clock Source */
00457         ClkSrc = (CGU_PER_BASE_CTRL(Clock) & CGU_CTRL_SRC_MASK) >> 24;
00458 
00459         /* GetBase Status*/
00460         if (CGU_PER_BASE_CTRL(Clock) & 1) {
00461             return 0;
00462         }
00463 
00464         /* check Branch if it is enabled */
00465         if ((CGU_PERIPHERAL_Info[Clock].PerBranchOffset != 0) && !(CGU_PER_BRANCH_STATUS(Clock) & CGU_BRANCH_STATUS_ENABLE_MASK)) {
00466             return 0;
00467         }
00468 
00469     } else {
00470         if (CGU_REG_BASE_CTRL(Clock) & 1)   {
00471             return 0;
00472         }
00473 
00474         ClkSrc = (CGU_REG_BASE_CTRL(Clock) & CGU_CTRL_SRC_MASK) >> 24;
00475 
00476         /* check Branch if it is enabled */
00477         if ((CGU_PERIPHERAL_Info[Clock].RegBranchOffset != 0) && !(CGU_REG_BRANCH_STATUS(Clock) & CGU_BRANCH_STATUS_ENABLE_MASK)) {
00478             return 0;
00479         }
00480     }
00481 
00482     return CGU_ClockSourceFrequency[ClkSrc];
00483 }
00484 
00485 
00486 /*********************************************************************//**
00487  * @brief       Update clock
00488  * @param[in]   None
00489  * @return      None
00490  **********************************************************************/
00491 void CGU_UpdateClock(void)
00492 {
00493     uint32_t ClkSrc;
00494     uint32_t div;
00495     uint32_t divisor;
00496     int32_t RegOffset;
00497 
00498     /* 32OSC */
00499     if (ISBITSET(LPC_CREG->CREG0, 1) && ISBITCLR(LPC_CREG->CREG0, 3)) {
00500         CGU_ClockSourceFrequency[CGU_CLKSRC_32KHZ_OSC] = 32768;
00501 
00502     } else {
00503         CGU_ClockSourceFrequency[CGU_CLKSRC_32KHZ_OSC] = 0;
00504     }
00505 
00506     /*PLL0*/
00507     /* PLL1 */
00508     if (ISBITCLR(LPC_CGU->PLL1_CTRL, 0) /* Enabled */ /* EA ANDLI: Original code tested bit 1 which is BYPASS, not PD */
00509             && (LPC_CGU->PLL1_STAT & 1)) { /* Locked? */
00510         ClkSrc = (LPC_CGU->PLL1_CTRL & CGU_CTRL_SRC_MASK) >> 24;
00511         CGU_ClockSourceFrequency[CGU_CLKSRC_PLL1] = CGU_ClockSourceFrequency[ClkSrc] *
00512                 (((LPC_CGU->PLL1_CTRL >> 16) & 0xFF) + 1);
00513 
00514     } else {
00515         CGU_ClockSourceFrequency[CGU_CLKSRC_PLL1] = 0;
00516     }
00517 
00518     /* DIV */
00519     for (div = CGU_CLKSRC_IDIVA; div <= CGU_CLKSRC_IDIVE; div++) {
00520         RegOffset = CGU_Entity_ControlReg_Offset[div];
00521 
00522         if (ISBITCLR(CGU_ADDRESS32(LPC_CGU, RegOffset), 1)) {
00523             ClkSrc = (CGU_ADDRESS32(LPC_CGU, RegOffset) & CGU_CTRL_SRC_MASK) >> 24;
00524             divisor = (CGU_ADDRESS32(LPC_CGU, RegOffset) >> 2) & 0xFF;
00525             divisor ++;
00526             CGU_ClockSourceFrequency[div] = CGU_ClockSourceFrequency[ClkSrc] / divisor;
00527 
00528         } else {
00529             CGU_ClockSourceFrequency[div] = 0;
00530         }
00531     }
00532 }
00533 
00534 /*********************************************************************//**
00535  * @brief       Set XTAL oscillator value
00536  * @param[in]   ClockFrequency  XTAL Frequency value
00537  * @return      Setting status, could be:
00538  *                  - CGU_ERROR_SUCCESS: successful
00539  *                  - CGU_ERROR_FREQ_OUTOF_RANGE: XTAL value set is out of range
00540  **********************************************************************/
00541 uint32_t    CGU_SetXTALOSC(uint32_t ClockFrequency)
00542 {
00543     if (ClockFrequency < 15000000) {
00544         LPC_CGU->XTAL_OSC_CTRL &= ~(1 << 2);
00545 
00546     } else if (ClockFrequency < 25000000) {
00547         LPC_CGU->XTAL_OSC_CTRL |= (1 << 2);
00548 
00549     } else {
00550         return CGU_ERROR_FREQ_OUTOF_RANGE;
00551     }
00552 
00553     CGU_ClockSourceFrequency[CGU_CLKSRC_XTAL_OSC] = ClockFrequency;
00554     return CGU_ERROR_SUCCESS;
00555 }
00556 
00557 
00558 /*********************************************************************//**
00559  * @brief       Set clock divider
00560  * @param[in]   SelectDivider   Clock source, should be:
00561  *                  - CGU_CLKSRC_IDIVA  :Integer divider register A
00562  *                  - CGU_CLKSRC_IDIVB  :Integer divider register B
00563  *                  - CGU_CLKSRC_IDIVC  :Integer divider register C
00564  *                  - CGU_CLKSRC_IDIVD  :Integer divider register D
00565  *                  - CGU_CLKSRC_IDIVE  :Integer divider register E
00566  * @param[in]   divisor Divisor value, should be: 0..255
00567  * @return      Setting status, could be:
00568  *                  - CGU_ERROR_SUCCESS: successful
00569  *                  - CGU_ERROR_INVALID_ENTITY: Invalid entity
00570  **********************************************************************/
00571 /* divisor number must >=1*/
00572 uint32_t    CGU_SetDIV(CGU_ENTITY_T SelectDivider, uint32_t divisor)
00573 {
00574     int32_t RegOffset;
00575     uint32_t tempReg;
00576 
00577     if (SelectDivider >= CGU_CLKSRC_IDIVA && SelectDivider <= CGU_CLKSRC_IDIVE) {
00578         RegOffset = CGU_Entity_ControlReg_Offset[SelectDivider];
00579 
00580         if (RegOffset == -1) {
00581             return CGU_ERROR_INVALID_ENTITY;
00582         }
00583 
00584         tempReg = CGU_ADDRESS32(LPC_CGU, RegOffset);
00585         tempReg &= ~(0xFF << 2);
00586         tempReg |= ((divisor - 1) & 0xFF) << 2;
00587         CGU_ADDRESS32(LPC_CGU, RegOffset) = tempReg;
00588         return CGU_ERROR_SUCCESS;
00589     }
00590 
00591     return CGU_ERROR_INVALID_ENTITY;
00592 }
00593 
00594 /*********************************************************************//**
00595  * @brief       Enable clock entity
00596  * @param[in]   ClockEntity Clock entity, should be:
00597  *                  - CGU_CLKSRC_32KHZ_OSC      :32Khz oscillator
00598  *                  - CGU_CLKSRC_IRC            :IRC clock
00599  *                  - CGU_CLKSRC_ENET_RX_CLK    :Ethernet receive clock
00600  *                  - CGU_CLKSRC_ENET_TX_CLK    :Ethernet transmit clock
00601  *                  - CGU_CLKSRC_GP_CLKIN       :General purpose input clock
00602  *                  - CGU_CLKSRC_XTAL_OSC       :Crystal oscillator
00603  *                  - CGU_CLKSRC_PLL0           :PLL0 clock
00604  *                  - CGU_CLKSRC_PLL1           :PLL1 clock
00605  *                  - CGU_CLKSRC_IDIVA          :Integer divider register A
00606  *                  - CGU_CLKSRC_IDIVB          :Integer divider register B
00607  *                  - CGU_CLKSRC_IDIVC          :Integer divider register C
00608  *                  - CGU_CLKSRC_IDIVD          :Integer divider register D
00609  *                  - CGU_CLKSRC_IDIVE          :Integer divider register E
00610  *                  - CGU_BASE_SAFE             :Base safe clock (always on)for WDT
00611  *                  - CGU_BASE_USB0             :Base clock for USB0
00612  *                  - CGU_BASE_PERIPH           :Base clock for Peripheral bus
00613  *                  - CGU_BASE_USB1             :Base clock for USB1
00614  *                  - CGU_BASE_M4               :System base clock for ARM Cortex-M3 core
00615  *                                               and APB peripheral blocks #0 and #2
00616  *                  - CGU_BASE_SPIFI            :Base clock for SPIFI
00617  *                  - CGU_BASE_PHY_RX           :Base clock for Ethernet PHY Rx
00618  *                  - CGU_BASE_PHY_TX           :Base clock for Ethernet PHY Tx
00619  *                  - CGU_BASE_APB1             :Base clock for APB peripheral block #1
00620  *                  - CGU_BASE_APB3             :Base clock for APB peripheral block #3
00621  *                  - CGU_BASE_LCD              :Base clock for LCD
00622  *                  - CGU_BASE_SDIO             :Base clock for SDIO card reader
00623  *                  - CGU_BASE_SSP0             :Base clock for SSP0
00624  *                  - CGU_BASE_SSP1             :Base clock for SSP1
00625  *                  - CGU_BASE_UART0            :Base clock for UART0
00626  *                  - CGU_BASE_UART1            :Base clock for UART1
00627  *                  - CGU_BASE_UART2            :Base clock for UART2
00628  *                  - CGU_BASE_UART3            :Base clock for UART3
00629  *                  - CGU_BASE_CLKOUT           :Base clock for CLKOUT pin
00630  * @param[in]   en status, should be:
00631  *                  - ENABLE: Enable power
00632  *                  - DISABLE: Disable power
00633  * @return      Setting status, could be:
00634  *                  - CGU_ERROR_SUCCESS: successful
00635  *                  - CGU_ERROR_INVALID_ENTITY: Invalid entity
00636  **********************************************************************/
00637 uint32_t CGU_EnableEntity(CGU_ENTITY_T ClockEntity, uint32_t en)
00638 {
00639     int32_t RegOffset;
00640     int32_t i;
00641 
00642     if (ClockEntity == CGU_CLKSRC_32KHZ_OSC) {
00643         if (en) {
00644             LPC_CREG->CREG0 &= ~((1 << 3) | (1 << 2));
00645             LPC_CREG->CREG0 |= (1 << 1) | (1 << 0);
00646 
00647         } else {
00648             LPC_CREG->CREG0 &= ~((1 << 1) | (1 << 0));
00649             LPC_CREG->CREG0 |= (1 << 3);
00650         }
00651 
00652         for (i = 0; i < 1000000; i++);
00653 
00654     } else if (ClockEntity == CGU_CLKSRC_ENET_RX_CLK) {
00655         scu_pinmux(0xC , 0 , MD_PLN, FUNC3);
00656 
00657     } else if (ClockEntity == CGU_CLKSRC_ENET_TX_CLK) {
00658         scu_pinmux(0x1 , 19 , MD_PLN, FUNC0);
00659 
00660     } else if (ClockEntity == CGU_CLKSRC_GP_CLKIN) {
00661     } else if (ClockEntity == CGU_CLKSRC_TCK) {
00662     } else if (ClockEntity == CGU_CLKSRC_XTAL_OSC) {
00663         if (!en) {
00664             LPC_CGU->XTAL_OSC_CTRL |= CGU_CTRL_EN_MASK;
00665 
00666         } else {
00667             LPC_CGU->XTAL_OSC_CTRL &= ~CGU_CTRL_EN_MASK;
00668         }
00669 
00670         /*Delay for stable clock*/
00671         for (i = 0; i < 1000000; i++);
00672 
00673     } else {
00674         RegOffset = CGU_Entity_ControlReg_Offset[ClockEntity];
00675 
00676         if (RegOffset == -1) {
00677             return CGU_ERROR_INVALID_ENTITY;
00678         }
00679 
00680         if (!en) {
00681             CGU_ADDRESS32(CGU_CGU_ADDR, RegOffset) |= CGU_CTRL_EN_MASK;
00682 
00683         } else {
00684             CGU_ADDRESS32(CGU_CGU_ADDR, RegOffset) &= ~CGU_CTRL_EN_MASK;
00685 
00686             /*if PLL is selected check if it is locked */
00687             if (ClockEntity == CGU_CLKSRC_PLL0) {
00688                 while ((LPC_CGU->PLL0USB_STAT & 1) == 0x0);
00689             }
00690 
00691             if (ClockEntity == CGU_CLKSRC_PLL0_AUDIO) {
00692                 while ((LPC_CGU->PLL0AUDIO_STAT & 1) == 0x0);
00693             }
00694 
00695             if (ClockEntity == CGU_CLKSRC_PLL1) {
00696                 while ((LPC_CGU->PLL1_STAT & 1) == 0x0);
00697 
00698                 /*post check lock status */
00699                 if (!(LPC_CGU->PLL1_STAT & 1))
00700                     while (1);
00701             }
00702         }
00703     }
00704 
00705     return CGU_ERROR_SUCCESS;
00706 }
00707 
00708 /*********************************************************************//**
00709  * @brief       Connect entity clock source
00710  * @param[in]   ClockSource Clock source, should be:
00711  *                  - CGU_CLKSRC_32KHZ_OSC      :32Khz oscillator
00712  *                  - CGU_CLKSRC_IRC            :IRC clock
00713  *                  - CGU_CLKSRC_ENET_RX_CLK    :Ethernet receive clock
00714  *                  - CGU_CLKSRC_ENET_TX_CLK    :Ethernet transmit clock
00715  *                  - CGU_CLKSRC_GP_CLKIN       :General purpose input clock
00716  *                  - CGU_CLKSRC_XTAL_OSC       :Crystal oscillator
00717  *                  - CGU_CLKSRC_PLL0           :PLL0 clock
00718  *                  - CGU_CLKSRC_PLL1           :PLL1 clock
00719  *                  - CGU_CLKSRC_IDIVA          :Integer divider register A
00720  *                  - CGU_CLKSRC_IDIVB          :Integer divider register B
00721  *                  - CGU_CLKSRC_IDIVC          :Integer divider register C
00722  *                  - CGU_CLKSRC_IDIVD          :Integer divider register D
00723  *                  - CGU_CLKSRC_IDIVE          :Integer divider register E
00724  * @param[in]   ClockEntity Clock entity, should be:
00725  *                  - CGU_CLKSRC_PLL0           :PLL0 clock
00726  *                  - CGU_CLKSRC_PLL1           :PLL1 clock
00727  *                  - CGU_CLKSRC_IDIVA          :Integer divider register A
00728  *                  - CGU_CLKSRC_IDIVB          :Integer divider register B
00729  *                  - CGU_CLKSRC_IDIVC          :Integer divider register C
00730  *                  - CGU_CLKSRC_IDIVD          :Integer divider register D
00731  *                  - CGU_CLKSRC_IDIVE          :Integer divider register E
00732  *                  - CGU_BASE_SAFE             :Base safe clock (always on)for WDT
00733  *                  - CGU_BASE_USB0             :Base clock for USB0
00734  *                  - CGU_BASE_USB1             :Base clock for USB1
00735  *                  - CGU_BASE_M4               :System base clock for ARM Cortex-M3 core
00736  *                                               and APB peripheral blocks #0 and #2
00737  *                  - CGU_BASE_SPIFI            :Base clock for SPIFI
00738  *                  - CGU_BASE_PHY_RX           :Base clock for Ethernet PHY Rx
00739  *                  - CGU_BASE_PHY_TX           :Base clock for Ethernet PHY Tx
00740  *                  - CGU_BASE_APB1             :Base clock for APB peripheral block #1
00741  *                  - CGU_BASE_APB3             :Base clock for APB peripheral block #3
00742  *                  - CGU_BASE_LCD              :Base clock for LCD
00743  *                  - CGU_BASE_SDIO             :Base clock for SDIO card reader
00744  *                  - CGU_BASE_SSP0             :Base clock for SSP0
00745  *                  - CGU_BASE_SSP1             :Base clock for SSP1
00746  *                  - CGU_BASE_UART0            :Base clock for UART0
00747  *                  - CGU_BASE_UART1            :Base clock for UART1
00748  *                  - CGU_BASE_UART2            :Base clock for UART2
00749  *                  - CGU_BASE_UART3            :Base clock for UART3
00750  *                  - CGU_BASE_CLKOUT           :Base clock for CLKOUT pin
00751  * @return      Setting status, could be:
00752  *                  - CGU_ERROR_SUCCESS: successful
00753  *                  - CGU_ERROR_CONNECT_TOGETHER: Error when 2 clock source connect together
00754  *                  - CGU_ERROR_INVALID_CLOCK_SOURCE: Invalid clock source error
00755  *                  - CGU_ERROR_INVALID_ENTITY: Invalid entity error
00756  **********************************************************************/
00757 /* Connect one entity into clock source */
00758 uint32_t CGU_EntityConnect(CGU_ENTITY_T ClockSource, CGU_ENTITY_T ClockEntity)
00759 {
00760     int32_t RegOffset;
00761     uint32_t tempReg;
00762 
00763     if (ClockSource > CGU_CLKSRC_IDIVE) {
00764         return CGU_ERROR_INVALID_CLOCK_SOURCE;
00765     }
00766 
00767     if (ClockEntity >= CGU_CLKSRC_PLL0 && ClockEntity <= CGU_BASE_CLKOUT) {
00768         if (CGU_ConnectAlloc_Tbl[ClockSource][ClockEntity]) {
00769             RegOffset = CGU_Entity_ControlReg_Offset[ClockSource];
00770 
00771             if (RegOffset != -1) {
00772                 if (ClockEntity <= CGU_CLKSRC_IDIVE &&
00773                         ClockEntity >= CGU_CLKSRC_PLL0) {
00774                     //RegOffset = (CGU_ADDRESS32(LPC_CGU,RegOffset)>>24)&0xF;
00775                     if (((CGU_ADDRESS32(LPC_CGU, RegOffset) >> 24) & 0xF) == ClockEntity) {
00776                         return CGU_ERROR_CONNECT_TOGETHER;
00777                     }
00778                 }
00779             }
00780 
00781             RegOffset = CGU_Entity_ControlReg_Offset[ClockEntity];
00782 
00783             if (RegOffset == -1) {
00784                 return CGU_ERROR_INVALID_ENTITY;
00785             }
00786 
00787             tempReg = CGU_ADDRESS32(LPC_CGU, RegOffset);
00788             tempReg &= ~CGU_CTRL_SRC_MASK;
00789             tempReg |= ClockSource << 24 | CGU_CTRL_AUTOBLOCK_MASK;
00790             CGU_ADDRESS32(LPC_CGU, RegOffset) = tempReg;
00791             return CGU_ERROR_SUCCESS;
00792 
00793         } else {
00794             return CGU_ERROR_INVALID_CLOCK_SOURCE;
00795         }
00796 
00797     } else {
00798         return CGU_ERROR_INVALID_ENTITY;
00799     }
00800 }
00801 
00802 
00803 /*********************************************************************//**
00804  * @brief       Get current USB PLL clock from XTAL
00805  * @param[in]   None
00806  * @return      Returned clock value
00807  **********************************************************************/
00808 uint32_t CGU_SetPLL0(void)
00809 {
00810     // Setup PLL550 to generate 480MHz from 12 MHz crystal
00811     LPC_CGU->PLL0USB_CTRL |= 1;     // Power down PLL
00812     //  P           N
00813     LPC_CGU->PLL0USB_NP_DIV = (98 << 0) | (514 << 12);
00814     //  SELP    SELI    SELR    MDEC
00815     LPC_CGU->PLL0USB_MDIV = (0xB << 17) | (0x10 << 22) | (0 << 28) | (0x7FFA << 0);
00816     LPC_CGU->PLL0USB_CTRL = (CGU_CLKSRC_XTAL_OSC << 24) | (0x3 << 2) | (1 << 4);
00817     return CGU_ERROR_SUCCESS;
00818 }
00819 
00820 
00821 
00822 /*********************************************************************//**
00823  * @brief       Get current Audio PLL clock from XTAL
00824  * @param[in]   None
00825  * @return      Returned clock value
00826  **********************************************************************/
00827 uint32_t CGU_SetPLL0audio(void)
00828 {
00829     /* disable clock, disable skew enable, power down pll,
00830     * (dis/en)able post divider, (dis/en)able pre-divider,
00831     * disable free running mode, disable bandsel,
00832     * enable up limmiter, disable bypass
00833     */
00834     LPC_CGU->PLL0AUDIO_CTRL = (6 << 24)   /* source = XTAL OSC 12 MHz */
00835                               | _BIT(0); /* power down */
00836     /* PLL should be set to 512fs rate 512 * 48000 =  24576000 Hz */
00837     /* set mdec register */
00838 #if 1       // results from gcc program
00839     LPC_CGU->PLL0AUDIO_MDIV = 0x23e34d3;
00840     LPC_CGU->PLL0AUDIO_NP_DIV = 0x3f00e;
00841     LPC_CGU->PLL0AUDIO_CTRL = (6 << 24)   /* source = XTAL OSC 12 MHz */
00842                               | (6 << 12)        // fractional divider off and bypassed
00843                               | _BIT(4);   /* CLKEN */
00844 #else
00845     LPC_CGU->PLL0AUDIO_MDIV = (0 << 28)  /* SELR */
00846                               | (40 << 22)   /* SELI */
00847                               | (31 << 17)   /* SELP */
00848                               | 11372;       /* MDEC */
00849     /* set ndec, pdec register */
00850     LPC_CGU->PLL0AUDIO_NP_DIV = (22 << 12)       /* ndec */
00851                                 | (10);               /* pdec */
00852     /* set fraction divider register. [21:15] = m, [14:0] = fractional value */
00853     LPC_CGU->PLL0AUDIO_FRAC = (86 << 15) | 0x1B7;
00854     LPC_CGU->PLL0AUDIO_CTRL = (6 << 24)   /* source = XTAL OSC 12 MHz */
00855                               | _BIT(12)   /* enable SD modulator to update mdec*/
00856                               | _BIT(4);   /* CLKEN */
00857 #endif
00858 
00859     /* wait for lock */
00860     while (!(LPC_CGU->PLL0AUDIO_STAT & 1));
00861 
00862     return CGU_ERROR_SUCCESS;
00863 }
00864 
00865 
00866 /*********************************************************************//**
00867  * @brief       Setting PLL1
00868  * @param[in]   mult    Multiple value
00869  * @return      Setting status, could be:
00870  *                  - CGU_ERROR_SUCCESS: successful
00871  *                  - CGU_ERROR_INVALID_PARAM: Invalid parameter error
00872  **********************************************************************/
00873 uint32_t    CGU_SetPLL1(uint32_t mult)
00874 {
00875     uint32_t msel = 0, nsel = 0, psel = 0, pval = 1;
00876     uint32_t freq;
00877     uint32_t ClkSrc = (LPC_CGU->PLL1_CTRL & CGU_CTRL_SRC_MASK) >> 24;
00878     freq = CGU_ClockSourceFrequency[ClkSrc];
00879     freq *= mult;
00880     msel = mult - 1;
00881     LPC_CGU->PLL1_CTRL &= ~(CGU_PLL1_FBSEL_MASK |
00882                             CGU_PLL1_BYPASS_MASK |
00883                             CGU_PLL1_DIRECT_MASK |
00884                             (0x03 << 8) | (0xFF << 16) | (0x03 << 12));
00885 
00886     if (freq < 156000000) {
00887         //psel is encoded such that 0=1, 1=2, 2=4, 3=8
00888         while (2 * (pval)*freq < 156000000) {
00889             psel++;
00890             pval *= 2;
00891         }
00892 
00893 //      if(2*(pval)*freq > 320000000) {
00894 //          //THIS IS OUT OF RANGE!!!
00895 //          //HOW DO WE ASSERT IN SAMPLE CODE?
00896 //          //__breakpoint(0);
00897 //          return CGU_ERROR_INVALID_PARAM;
00898 //      }
00899         LPC_CGU->PLL1_CTRL |= (msel << 16) | (nsel << 12) | (psel << 8) | CGU_PLL1_FBSEL_MASK;
00900 
00901     } else if (freq < 320000000) {
00902         LPC_CGU->PLL1_CTRL |= (msel << 16) | (nsel << 12) | (psel << 8) | CGU_PLL1_DIRECT_MASK | CGU_PLL1_FBSEL_MASK;
00903 
00904     } else {
00905         return CGU_ERROR_INVALID_PARAM;
00906     }
00907 
00908     return CGU_ERROR_SUCCESS;
00909 }
00910 
00911 
00912 /*********************************************************************//**
00913  * @brief       Get current base status
00914  * @param[in]   Base    Base type, should be:
00915  *                  - CGU_BASE_USB0             :Base clock for USB0
00916  *                  - CGU_BASE_USB1             :Base clock for USB1
00917  *                  - CGU_BASE_M4               :System base clock for ARM Cortex-M3 core
00918  *                                               and APB peripheral blocks #0 and #2
00919  *                  - CGU_BASE_SPIFI            :Base clock for SPIFI
00920  *                  - CGU_BASE_APB1             :Base clock for APB peripheral block #1
00921  *                  - CGU_BASE_APB3             :Base clock for APB peripheral block #3
00922  *                  - CGU_BASE_SDIO             :Base clock for SDIO card reader
00923  *                  - CGU_BASE_SSP0             :Base clock for SSP0
00924  *                  - CGU_BASE_SSP1             :Base clock for SSP1
00925  *                  - CGU_BASE_UART0            :Base clock for UART0
00926  *                  - CGU_BASE_UART1            :Base clock for UART1
00927  *                  - CGU_BASE_UART2            :Base clock for UART2
00928  *                  - CGU_BASE_UART3            :Base clock for UART3
00929  * @return      Always return 0
00930  **********************************************************************/
00931 uint32_t    CGU_GetBaseStatus(CGU_ENTITY_T Base)
00932 {
00933     switch (Base) {
00934         /*CCU1*/
00935         case CGU_BASE_APB3:
00936             return LPC_CCU1->BASE_STAT & 1;
00937 
00938         case CGU_BASE_APB1:
00939             return (LPC_CCU1->BASE_STAT >> 1) & 1;
00940 
00941         case CGU_BASE_SPIFI:
00942             return (LPC_CCU1->BASE_STAT >> 2) & 1;
00943 
00944         case CGU_BASE_M4:
00945             return (LPC_CCU1->BASE_STAT >> 3) & 1;
00946 
00947         case CGU_BASE_USB0:
00948             return (LPC_CCU1->BASE_STAT >> 7) & 1;
00949 
00950         case CGU_BASE_USB1:
00951             return (LPC_CCU1->BASE_STAT >> 8) & 1;
00952 
00953         /*CCU2*/
00954         case CGU_BASE_UART3:
00955             return (LPC_CCU2->BASE_STAT >> 1) & 1;
00956 
00957         case CGU_BASE_UART2:
00958             return (LPC_CCU2->BASE_STAT >> 2) & 1;
00959 
00960         case CGU_BASE_UART1:
00961             return (LPC_CCU2->BASE_STAT >> 3) & 1;
00962 
00963         case CGU_BASE_UART0:
00964             return (LPC_CCU2->BASE_STAT >> 4) & 1;
00965 
00966         case CGU_BASE_SSP1:
00967             return (LPC_CCU2->BASE_STAT >> 5) & 1;
00968 
00969         case CGU_BASE_SSP0:
00970             return (LPC_CCU2->BASE_STAT >> 6) & 1;
00971 
00972         case CGU_BASE_SDIO:
00973             return (LPC_CCU2->BASE_STAT >> 7) & 1;
00974 
00975         /*BASE SAFE is used by WWDT and RGU*/
00976         case CGU_BASE_SAFE:
00977             break;
00978 
00979         default:
00980             break;
00981     }
00982 
00983     return 0;
00984 }
00985 
00986 
00987 /*********************************************************************//**
00988  * @brief       Compare one source clock to IRC clock
00989  * @param[in]   Clock   Clock entity that will be compared to IRC, should be:
00990  *                  - CGU_CLKSRC_32KHZ_OSC      :32Khz crystal oscillator
00991  *                  - CGU_CLKSRC_ENET_RX_CLK    :Ethernet receive clock
00992  *                  - CGU_CLKSRC_ENET_TX_CLK    :Ethernet transmit clock
00993  *                  - CGU_CLKSRC_GP_CLKIN       :General purpose input clock
00994  *                  - CGU_CLKSRC_XTAL_OSC       :Crystal oscillator
00995  *                  - CGU_CLKSRC_PLL0           :PLL0 clock
00996  *                  - CGU_CLKSRC_PLL1           :PLL1 clock
00997  *                  - CGU_CLKSRC_IDIVA          :Integer divider register A
00998  *                  - CGU_CLKSRC_IDIVB          :Integer divider register B
00999  *                  - CGU_CLKSRC_IDIVC          :Integer divider register C
01000  *                  - CGU_CLKSRC_IDIVD          :Integer divider register D
01001  *                  - CGU_CLKSRC_IDIVE          :Integer divider register E
01002  *                  - CGU_BASE_SAFE             :Base safe clock (always on)for WDT
01003  *                  - CGU_BASE_USB0             :Base clock for USB0
01004  *                  - CGU_BASE_USB1             :Base clock for USB1
01005  *                  - CGU_BASE_M4               :System base clock for ARM Cortex-M3 core
01006  *                                               and APB peripheral blocks #0 and #2
01007  *                  - CGU_BASE_SPIFI            :Base clock for SPIFI
01008  *                  - CGU_BASE_PHY_RX           :Base clock for Ethernet PHY Rx
01009  *                  - CGU_BASE_PHY_TX           :Base clock for Ethernet PHY Tx
01010  *                  - CGU_BASE_APB1             :Base clock for APB peripheral block #1
01011  *                  - CGU_BASE_APB3             :Base clock for APB peripheral block #3
01012  *                  - CGU_BASE_LCD              :Base clock for LCD
01013  *                  - CGU_BASE_SDIO             :Base clock for SDIO card reader
01014  *                  - CGU_BASE_SSP0             :Base clock for SSP0
01015  *                  - CGU_BASE_SSP1             :Base clock for SSP1
01016  *                  - CGU_BASE_UART0            :Base clock for UART0
01017  *                  - CGU_BASE_UART1            :Base clock for UART1
01018  *                  - CGU_BASE_UART2            :Base clock for UART2
01019  *                  - CGU_BASE_UART3            :Base clock for UART3
01020  *                  - CGU_BASE_CLKOUT           :Base clock for CLKOUT pin
01021  * @param[in]   m   Multiple value pointer
01022  * @param[in]   d   Divider value pointer
01023  * @return      Compare status, could be:
01024  *                  - (-1): fail
01025  *                  - 0: successful
01026  * @note        Formula used to compare:
01027  *              FClock = F_IRC* m / d
01028  **********************************************************************/
01029 int CGU_FrequencyMonitor(CGU_ENTITY_T Clock, uint32_t *m, uint32_t *d)
01030 {
01031     uint32_t n, c, temp;
01032     int i;
01033     /* Maximum allow RCOUNT number */
01034     c = 511;
01035     /* Check Source Clock Freq is larger or smaller */
01036     LPC_CGU->FREQ_MON = (Clock << 24) | 1 << 23 | c;
01037 
01038     while (LPC_CGU->FREQ_MON & (1 << 23));
01039 
01040     for (i = 0; i < 10000; i++);
01041 
01042     temp = (LPC_CGU->FREQ_MON >> 9) & 0x3FFF;
01043 
01044     if (temp == 0) { /* too low F < 12000000/511*/
01045         return -1;
01046     }
01047 
01048     if (temp > 511) { /* larger */
01049         c = 511 - (LPC_CGU->FREQ_MON & 0x1FF);
01050 
01051     } else {
01052         do {
01053             c--;
01054             LPC_CGU->FREQ_MON = (Clock << 24) | 1 << 23 | c;
01055 
01056             while (LPC_CGU->FREQ_MON & (1 << 23));
01057 
01058             for (i = 0; i < 10000; i++);
01059 
01060             n = (LPC_CGU->FREQ_MON >> 9) & 0x3FFF;
01061         } while (n == temp);
01062 
01063         c++;
01064     }
01065 
01066     *m = temp;
01067     *d = c;
01068     return 0;
01069 }
01070 
01071 /*********************************************************************//**
01072  * @brief       Compare one source clock to another source clock
01073  * @param[in]   Clock   Clock entity that will be compared to second source, should be:
01074  *                  - CGU_CLKSRC_32KHZ_OSC      :32Khz crystal oscillator
01075  *                  - CGU_CLKSRC_ENET_RX_CLK    :Ethernet receive clock
01076  *                  - CGU_CLKSRC_ENET_TX_CLK    :Ethernet transmit clock
01077  *                  - CGU_CLKSRC_GP_CLKIN       :General purpose input clock
01078  *                  - CGU_CLKSRC_XTAL_OSC       :Crystal oscillator
01079  *                  - CGU_CLKSRC_PLL0           :PLL0 clock
01080  *                  - CGU_CLKSRC_PLL1           :PLL1 clock
01081  *                  - CGU_CLKSRC_IDIVA          :Integer divider register A
01082  *                  - CGU_CLKSRC_IDIVB          :Integer divider register B
01083  *                  - CGU_CLKSRC_IDIVC          :Integer divider register C
01084  *                  - CGU_CLKSRC_IDIVD          :Integer divider register D
01085  *                  - CGU_CLKSRC_IDIVE          :Integer divider register E
01086  *                  - CGU_BASE_SAFE             :Base safe clock (always on)for WDT
01087  *                  - CGU_BASE_USB0             :Base clock for USB0
01088  *                  - CGU_BASE_USB1             :Base clock for USB1
01089  *                  - CGU_BASE_M4               :System base clock for ARM Cortex-M3 core
01090  *                                               and APB peripheral blocks #0 and #2
01091  *                  - CGU_BASE_SPIFI            :Base clock for SPIFI
01092  *                  - CGU_BASE_PHY_RX           :Base clock for Ethernet PHY Rx
01093  *                  - CGU_BASE_PHY_TX           :Base clock for Ethernet PHY Tx
01094  *                  - CGU_BASE_APB1             :Base clock for APB peripheral block #1
01095  *                  - CGU_BASE_APB3             :Base clock for APB peripheral block #3
01096  *                  - CGU_BASE_LCD              :Base clock for LCD
01097  *                  - CGU_BASE_SDIO             :Base clock for SDIO card reader
01098  *                  - CGU_BASE_SSP0             :Base clock for SSP0
01099  *                  - CGU_BASE_SSP1             :Base clock for SSP1
01100  *                  - CGU_BASE_UART0            :Base clock for UART0
01101  *                  - CGU_BASE_UART1            :Base clock for UART1
01102  *                  - CGU_BASE_UART2            :Base clock for UART2
01103  *                  - CGU_BASE_UART3            :Base clock for UART3
01104  *                  - CGU_BASE_CLKOUT           :Base clock for CLKOUT pin
01105  * @param[in]   CompareToClock  Clock source that to be compared to first source, should be different
01106  *              to first source.
01107  * @param[in]   m   Multiple value pointer
01108  * @param[in]   d   Divider value pointer
01109  * @return      Compare status, could be:
01110  *                  - (-1): fail
01111  *                  - 0: successful
01112  * @note        Formula used to compare:
01113  *              FClock = m*FCompareToClock/d
01114  **********************************************************************/
01115 uint32_t CGU_RealFrequencyCompare(CGU_ENTITY_T Clock, CGU_ENTITY_T CompareToClock, uint32_t *m, uint32_t *d)
01116 {
01117     uint32_t m1, m2, d1, d2;
01118 
01119     /* Check Parameter */
01120     if ((Clock > CGU_CLKSRC_IDIVE) || (CompareToClock > CGU_CLKSRC_IDIVE)) {
01121         return CGU_ERROR_INVALID_PARAM;
01122     }
01123 
01124     /* Check for Clock Enable - Not yet implement
01125      * The Comparator will hang if Clock has not been set*/
01126     CGU_FrequencyMonitor(Clock, &m1, &d1);
01127     CGU_FrequencyMonitor(CompareToClock, &m2, &d2);
01128     *m = m1 * d2;
01129     *d = d1 * m2;
01130     return 0;
01131 }
01132