123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /*
- * @brief LPC5410X PLL driver
- *
- * @note
- * Copyright(C) NXP Semiconductors, 2014
- * All rights reserved.
- *
- * @par
- * Software that is described herein is for illustrative purposes only
- * which provides customers with programming information regarding the
- * LPC products. This software is supplied "AS IS" without any warranties of
- * any kind, and NXP Semiconductors and its licenser disclaim any and
- * all warranties, express or implied, including all implied warranties of
- * merchantability, fitness for a particular purpose and non-infringement of
- * intellectual property rights. NXP Semiconductors assumes no responsibility
- * or liability for the use of the software, conveys no license or rights under any
- * patent, copyright, mask work right, or any other intellectual property rights in
- * or to any products. NXP Semiconductors reserves the right to make changes
- * in the software without notification. NXP Semiconductors also makes no
- * representation or warranty that such application will be suitable for the
- * specified use without further testing or modification.
- *
- * @par
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, under NXP Semiconductors' and its
- * licensor's relevant copyrights in the software, without fee, provided that it
- * is used in conjunction with NXP Semiconductors microcontrollers. This
- * copyright, permission, and disclaimer notice must appear in all copies of
- * this code.
- */
- #ifndef __PLL_5410X_H_
- #define __PLL_5410X_H_
- #ifdef __cplusplus
- extern "C" {
- #endif
- /** @defgroup PLL_5410X CHIP: LPC5410X PLL Driver
- * @ingroup CHIP_5410X_DRIVERS
- * The PLL in the LPC5410x is flexible, but can be complex to use. This driver
- * provides functions to help setup and use the PLL in it's various supported
- * modes.<br>
- *
- * This driver does not alter PLL clock source or system clocks outside the
- * PLL (like the main clock source) that may be referenced from the PLL. It
- * may optionally setup system voltages, wait for PLL lock, and power cycle
- * the PLL during setup based on setup flags.
- *
- * The driver works by first generating a PLL setup structure from a desired
- * PLL configuration structure. The PLL setup structure is then passed to the
- * PLL setup function to setup the PLL. In a user spplication, the PLL setup
- * structure can be pre-populated with PLL setup data to avoid using the PLL
- * configuration structure (or multiple PLL setup structures can be used to
- * more dynamically control PLL output rate).
- *
- * <b>How to use this driver</b><br>
- @verbatim
- // Setup PLL configuration
- PLL_CONFIG_T pllConfig = {
- 75000000, // desiredRate = 75MHz
- 0, // InputRate = 0Hz (not used)
- 0 // No flags, function will determine best setup to get closest rate
- };
- // Get closest PLL setup to get the desired configuration
- PLL_SETUP_T pllSetup;
- uint32_t actualPllRate;
- PLL_ERROR_T pllError;
- pllError = Chip_Clock_SetupPLLData(&pllConfig, &pllSetup, &actualPllRate);
- if (pllError != PLL_ERROR_SUCCESS) {
- printf("PLL setup error #%x\r\n", (uint32_t) pllError);
- while (1);
- }
- else {
- printf("PLL config successful, actual config rate = %uHz\r\n", actualPllRate);
- }
- // Make sure main system clock is not using PLL, as the PLL setup
- // function will power off and optionally power on the PLL
- Chip_Clock_SetMainClockSource(SYSCON_MAINCLKSRC_IRC);
- // Setup PLL source
- Chip_Clock_SetSystemPLLSource(SYSCON_PLLCLKSRC_IRC);
- // Now to apply the configuration to the PLL
- pllSetup.flags = PLL_SETUPFLAG_WAITLOCK;
- Chip_Clock_SetupSystemPLLPrec(&pllSetup);
- // Switch main system clock to PLL
- Chip_Clock_SetMainClockSource(SYSCON_MAINCLKSRC_PLLOUT);
- @endverbatim
- *
- * @{
- */
- /**
- * Clock sources for system PLLs
- */
- typedef enum CHIP_SYSCON_PLLCLKSRC {
- SYSCON_PLLCLKSRC_IRC = 0, /*!< Internal oscillator */
- SYSCON_PLLCLKSRC_CLKIN, /*!< External clock input pin */
- SYSCON_PLLCLKSRC_WDTOSC, /*!< WDT oscillator */
- SYSCON_PLLCLKSRC_RTC, /*!< RTC 32KHz oscillator */
- } CHIP_SYSCON_PLLCLKSRC_T;
- /**
- * @brief Set System PLL clock source
- * @param src : Clock source for system PLL
- * @return Nothing
- * @note The PLL should be pwoered down prior to changing the source.
- */
- STATIC INLINE void Chip_Clock_SetSystemPLLSource(CHIP_SYSCON_PLLCLKSRC_T src)
- {
- LPC_SYSCON->SYSPLLCLKSEL = (uint32_t) src;
- }
- /**
- * @brief Return System PLL input clock rate
- * @return System PLL input clock rate
- */
- uint32_t Chip_Clock_GetSystemPLLInClockRate(void);
- /**
- * @brief Return System PLL output clock rate
- * @param recompute : Forces a PLL rate recomputation if true
- * @return System PLL output clock rate
- * @note The PLL rate is cached in the driver in a variable as
- * the rate computation function can take some time to perform. It
- * is recommended to use 'false' with the 'recompute' parameter.
- */
- uint32_t Chip_Clock_GetSystemPLLOutClockRate(bool recompute);
- /**
- * @brief Enables and disables PLL bypass mode
- * @brief bypass : true to bypass PLL (PLL output = PLL input, false to disable bypass
- * @return System PLL output clock rate
- */
- void Chip_Clock_SetBypassPLL(bool bypass);
- /**
- * @brief Check if PLL is locked or not
- * @return true if the PLL is locked, false if not locked
- */
- STATIC INLINE bool Chip_Clock_IsSystemPLLLocked(void)
- {
- return (bool) ((LPC_SYSCON->SYSPLLSTAT & 1) != 0);
- }
- /** @brief PLL configuration structure flags for 'flags' field
- * These flags control how the PLL configuration function sets up the PLL setup structure.<br>
- *
- * When the PLL_CONFIGFLAG_USEINRATE flag is selected, the 'InputRate' field in the
- * configuration structure must be assigned with the expected PLL frequency. If the
- * PLL_CONFIGFLAG_USEINRATE is not used, 'InputRate' is ignored in the configuration
- * function and the driver will determine the PLL rate from the currently selected
- * PLL source. This flag might be used to configure the PLL input clock more accurately
- * when using the WDT oscillator or a more dyanmic CLKIN source.<br>
- *
- * When the PLL_CONFIGFLAG_FORCENOFRACT flag is selected, the PLL hardware for the
- * automatic bandwidth selection, Spread Spectrum (SS) support, and fractional M-divider
- * are not used.<br>
- */
- #define PLL_CONFIGFLAG_USEINRATE (1 << 0) /*!< Flag to use InputRate in PLL configuration structure for setup */
- #define PLL_CONFIGFLAG_FORCENOFRACT (1 << 2) /*!< Force non-fractional output mode, PLL output will not use the fractional, automatic bandwidth, or SS hardware */
- /** @brief PLL Spread Spectrum (SS) Programmable modulation frequency
- * See (MF) field in the SYSPLLSSCTRL1 register in the UM.
- */
- typedef enum {
- SS_MF_512 = (0 << 20), /*!< Nss = 512 (fm ˜ 3.9 - 7.8 kHz) */
- SS_MF_384 = (1 << 20), /*!< Nss ˜= 384 (fm ˜ 5.2 - 10.4 kHz) */
- SS_MF_256 = (2 << 20), /*!< Nss = 256 (fm ˜ 7.8 - 15.6 kHz) */
- SS_MF_128 = (3 << 20), /*!< Nss = 128 (fm ˜ 15.6 - 31.3 kHz) */
- SS_MF_64 = (4 << 20), /*!< Nss = 64 (fm ˜ 32.3 - 64.5 kHz) */
- SS_MF_32 = (5 << 20), /*!< Nss = 32 (fm ˜ 62.5- 125 kHz) */
- SS_MF_24 = (6 << 20), /*!< Nss ˜= 24 (fm ˜ 83.3- 166.6 kHz) */
- SS_MF_16 = (7 << 20) /*!< Nss = 16 (fm ˜ 125- 250 kHz) */
- } SS_PROGMODFM_T;
- /** @brief PLL Spread Spectrum (SS) Programmable frequency modulation depth
- * See (MR) field in the SYSPLLSSCTRL1 register in the UM.
- */
- typedef enum {
- SS_MR_K0 = (0 << 23), /*!< k = 0 (no spread spectrum) */
- SS_MR_K1 = (1 << 23), /*!< k = 1 */
- SS_MR_K1_5 = (2 << 23), /*!< k = 1.5 */
- SS_MR_K2 = (3 << 23), /*!< k = 2 */
- SS_MR_K3 = (4 << 23), /*!< k = 3 */
- SS_MR_K4 = (5 << 23), /*!< k = 4 */
- SS_MR_K6 = (6 << 23), /*!< k = 6 */
- SS_MR_K8 = (7 << 23) /*!< k = 8 */
- } SS_PROGMODDP_T;
- /** @brief PLL Spread Spectrum (SS) Modulation waveform control
- * See (MC) field in the SYSPLLSSCTRL1 register in the UM.<br>
- * Compensation for low pass filtering of the PLL to get a triangular
- * modulation at the output of the PLL, giving a flat frequency spectrum.
- */
- typedef enum {
- SS_MC_NOC = (0 << 26), /*!< no compensation */
- SS_MC_RECC = (2 << 26), /*!< recommended setting */
- SS_MC_MAXC = (3 << 26), /*!< max. compensation */
- } SS_MODWVCTRL_T;
- /** @brief PLL configuration structure
- * This structure can be used to configure the settings for a PLL
- * setup structure. Fill in the desired configuration for the PLL
- * and call the PLL setup function to fill in a PLL setup structure.
- */
- typedef struct {
- uint32_t desiredRate; /*!< Desired PLL rate in Hz */
- uint32_t InputRate; /*!< PLL input clock in Hz, only used if PLL_CONFIGFLAG_USEINRATE flag is set */
- uint32_t flags; /*!< PLL configuration flags, Or'ed value of PLL_CONFIGFLAG_* definitions */
- SS_PROGMODFM_T ss_mf; /*!< SS Programmable modulation frequency, only applicable when not using PLL_CONFIGFLAG_FORCENOFRACT flag */
- SS_PROGMODDP_T ss_mr; /*!< SS Programmable frequency modulation depth, only applicable when not using PLL_CONFIGFLAG_FORCENOFRACT flag */
- SS_MODWVCTRL_T ss_mc; /*!< SS Modulation waveform control, only applicable when not using PLL_CONFIGFLAG_FORCENOFRACT flag */
- bool mfDither; /*!< false for fixed modulation frequency or true for dithering, only applicable when not using PLL_CONFIGFLAG_FORCENOFRACT flag */
- } PLL_CONFIG_T;
- /** @brief PLL setup structure flags for 'flags' field
- * These flags control how the PLL setup function sets up the PLL
- */
- #define PLL_SETUPFLAG_POWERUP (1 << 0) /*!< Setup will power on the PLL after setup */
- #define PLL_SETUPFLAG_WAITLOCK (1 << 1) /*!< Setup will wait for PLL lock, implies the PLL will be pwoered on */
- #define PLL_SETUPFLAG_ADGVOLT (1 << 2) /*!< Optimize system voltage for the new PLL rate */
- /** @brief PLL setup structure
- * This structure can be used to pre-build a PLL setup configuration
- * at run-time and quickly set the PLL to the configuration. It can be
- * populated with the PLL setup function. If powering up or waiting
- * for PLL lock, the PLL input clock source should be configured prior
- * to PLL setup.
- */
- typedef struct {
- uint32_t flags; /*!< PLL setup flags, Or'ed value of PLL_SETUPFLAG_* definitions */
- uint32_t SYSPLLCTRL; /*!< PLL control register */
- uint32_t SYSPLLNDEC; /*!< PLL NDEC register */
- uint32_t SYSPLLPDEC; /*!< PLL PDEC register */
- uint32_t SYSPLLSSCTRL[2]; /*!< PLL SSCTL registers */
- } PLL_SETUP_T;
- /** @brief PLL status definitions
- */
- typedef enum {
- PLL_ERROR_SUCCESS = 0, /*!< PLL operation was successful */
- PLL_ERROR_OUTPUT_TOO_LOW, /*!< PLL output rate request was too low */
- PLL_ERROR_OUTPUT_TOO_HIGH, /*!< PLL output rate request was too high */
- PLL_ERROR_INPUT_TOO_LOW, /*!< PLL input rate is too low */
- PLL_ERROR_INPUT_TOO_HIGH, /*!< PLL input rate is too high */
- PLL_ERROR_OUTSIDE_INTLIMIT /*!< Requested output rate isn't possible */
- } PLL_ERROR_T;
- /**
- * @brief Return System PLL output clock rate from setup structure
- * @param pSetup : Pointer to a PLL setup structure
- * @return System PLL output clock rate the setup structure will generate
- */
- uint32_t Chip_Clock_GetSystemPLLOutFromSetup(PLL_SETUP_T *pSetup);
- /**
- * @brief Set PLL output based on the passed PLL setup data
- * @param pControl : Pointer to populated PLL control structure to generate setup with
- * @param pSetup : Pointer to PLL setup structure to be filled
- * @return PLL_ERROR_SUCCESS on success, or PLL setup error code
- * @note Actual frequency for setup may vary from the desired frequency based on the
- * accuracy of input clocks, rounding, non-fractional PLL mode, etc.
- */
- PLL_ERROR_T Chip_Clock_SetupPLLData(PLL_CONFIG_T *pControl, PLL_SETUP_T *pSetup);
- /**
- * @brief Set PLL output from PLL setup structure (precise frequency)
- * @param pSetup : Pointer to populated PLL setup structure
- * @return PLL_ERROR_SUCCESS on success, or PLL setup error code
- * @note This function will power off the PLL, setup the PLL with the
- * new setup data, and then optionally powerup the PLL, wait for PLL lock,
- * and adjust system voltages to the new PLL rate. The function will not
- * alter any source clocks (ie, main systen clock) that may use the PLL,
- * so these should be setup prior to and after exiting the function.
- */
- PLL_ERROR_T Chip_Clock_SetupSystemPLLPrec(PLL_SETUP_T *pSetup);
- /**
- * @brief Set PLL output based on the multiplier and input frequency
- * @param multiply_by : multiplier
- * @param input_freq : Clock input frequency of the PLL
- * @return Nothing
- * @note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this
- * function does not disable or enable PLL power, wait for PLL lock,
- * or adjust system voltages. These must be done in the application.
- * The function will not alter any source clocks (ie, main systen clock)
- * that may use the PLL, so these should be setup prior to and after
- * exiting the function.
- */
- void Chip_Clock_SetupSystemPLL(uint32_t multiply_by, uint32_t input_freq);
- /**
- * @}
- */
- #ifdef __cplusplus
- }
- #endif
- #endif /* __PLL_5410X_H_ */
|