Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
lpc43xx_cgu.c
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
Generated on Tue Jul 12 2022 15:37:19 by
1.7.2