diff options
Diffstat (limited to 'c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pmc.c')
-rw-r--r-- | c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pmc.c | 597 |
1 files changed, 0 insertions, 597 deletions
diff --git a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pmc.c b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pmc.c deleted file mode 100644 index 08df61ef8a..0000000000 --- a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pmc.c +++ /dev/null @@ -1,597 +0,0 @@ -/* ---------------------------------------------------------------------------- */ -/* Atmel Microcontroller Software Support */ -/* SAM Software Package License */ -/* ---------------------------------------------------------------------------- */ -/* Copyright (c) 2015, Atmel Corporation */ -/* */ -/* All rights reserved. */ -/* */ -/* Redistribution and use in source and binary forms, with or without */ -/* modification, are permitted provided that the following condition is met: */ -/* */ -/* - Redistributions of source code must retain the above copyright notice, */ -/* this list of conditions and the disclaimer below. */ -/* */ -/* Atmel's name may not be used to endorse or promote products derived from */ -/* this software without specific prior written permission. */ -/* */ -/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ -/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ -/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ -/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ -/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ -/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ -/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ -/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ -/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* ---------------------------------------------------------------------------- */ - -/** \addtogroup pmc_module Working with PMC - * The PMC driver provides the Interface to configure the Power Management - * Controller (PMC). - * - * \section Usage - * <ul> - * <li> Enables/Disable the clock of a peripheral by using - * PMC_EnablePeripheral() and PMC_DisablePeripheral().</li> - * <li> Enables/Disable the clock of all peripherals by using - * PMC_EnableAllPeripherals() and PMC_DisableAllPeripherals().</li> - * <li> Get status of a peripheral using PMC_IsPeriphEnabled().</li> - * <li> Manage the clocks using PMC_EnableExtOsc(), PMC_DisableExtOsc(), - * PMC_SelectExtOsc(), PMC_SelectExtBypassOsc(), PMC_EnableIntRC4_8_12MHz(), - * PMC_DisableIntRC4_8_12MHz(), PMC_SetPllaClock(), PMC_SetMckSelection(), - * PMC_DisableAllClocks(), PMC_ConfigureMckWithPlla(), - * PMC_EnableXT32KFME() and PMC_ConfigurePCK2().</li> - * - * </ul> - * For more accurate information, please look at the PMC section of the Datasheet. - * - * Related files :\n - * \ref pmc.c\n - * \ref pmc.h.\n -*/ - -/** -* \file -* -* \section Purpose -* -* Interface for configuring and using Power Management Controller (PMC) -* peripherals. -* -*/ - -/** - * \file - * - * Implementation of Power Management Controller (PMC). - * - */ - -/*---------------------------------------------------------------------------- - * Headers - *----------------------------------------------------------------------------*/ - -#include "chip.h" - -#include <assert.h> - -/*---------------------------------------------------------------------------- - * Local definitions - *----------------------------------------------------------------------------*/ - -#define MASK_STATUS0 0xFFFFFFFC -#define MASK_STATUS1 0xFFFFFFFF - -/*---------------------------------------------------------------------------- - * Local functions - *----------------------------------------------------------------------------*/ -/** - * \brief Switch MCK to PLLA clock. - */ -static void _PMC_SwitchMck2PllaClock(void) - -{ - /* Select PLLA as input clock for MCK */ - PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_PLLA_CLK; - - /* Wait until the master clock is established */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); -} - -/** - * \brief Switch MCK to main clock. - */ -static void _PMC_SwitchMck2MainClock(void) -{ - /* Select Main Oscillator as input clock for MCK */ - PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; - - /* Wait until the master clock is established */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); - - PMC->PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK; - - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); -} - -/** - * \brief Switch MCK to slow clock. - */ -static void _PMC_SwitchMck2SlowClock(void) -{ - /* Select Slow Clock as input clock for MCK */ - PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_SLOW_CLK; - - /* Wait until the master clock is established */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); -} - -/** - * \brief Set prescaler for MCK. - * - * \param prescaler Master Clock prescaler - */ -static void _PMC_SetMckPrescaler(uint32_t prescaler) -{ - /* Change MCK Prescaler divider in PMC_MCKR register */ - PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_PRES_Msk) | prescaler; - - /* Wait until the master clock is established */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); -} -/*---------------------------------------------------------------------------- - * Exported functions - *----------------------------------------------------------------------------*/ - -/** - * \brief Enables the clock of a peripheral. The peripheral ID is used - * to identify which peripheral is targeted. - * - * \note The ID must NOT be shifted (i.e. 1 << ID_xxx). - * - * \param id Peripheral ID (ID_xxx). - */ -void PMC_EnablePeripheral(uint32_t dwId) -{ - assert(dwId < 63); - - if (dwId < 32) { - if ((PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId)) { - TRACE_DEBUG("PMC_EnablePeripheral: clock of peripheral" \ - " %u is already enabled\n\r", (unsigned int)dwId); - } else - PMC->PMC_PCER0 = 1 << dwId; - } else { - dwId -= 32; - - if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId)) { - TRACE_DEBUG("PMC_EnablePeripheral: clock of peripheral" \ - " %u is already enabled\n\r", (unsigned int)(dwId + 32)); - } else - PMC->PMC_PCER1 = 1 << dwId; - } -} - -/** - * \brief Disables the clock of a peripheral. The peripheral ID is used - * to identify which peripheral is targeted. - * - * \note The ID must NOT be shifted (i.e. 1 << ID_xxx). - * - * \param id Peripheral ID (ID_xxx). - */ -void PMC_DisablePeripheral(uint32_t dwId) -{ - assert(dwId < 63); - - if (dwId < 32) { - if ((PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId)) { - TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" \ - " %u is not enabled\n\r", (unsigned int)dwId); - } else - PMC->PMC_PCDR0 = 1 << dwId; - } else { - dwId -= 32; - - if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId)) { - TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" - " %u is not enabled\n\r", (unsigned int)(dwId + 32)); - } else - PMC->PMC_PCDR1 = 1 << dwId; - } -} - -/** - * \brief Enable all the periph clock via PMC. - */ -void PMC_EnableAllPeripherals(void) -{ - PMC->PMC_PCER0 = MASK_STATUS0; - - while ((PMC->PMC_PCSR0 & MASK_STATUS0) != MASK_STATUS0); - - PMC->PMC_PCER1 = MASK_STATUS1; - - while ((PMC->PMC_PCSR1 & MASK_STATUS1) != MASK_STATUS1); - - TRACE_DEBUG("Enable all periph clocks\n\r"); -} - -/** - * \brief Disable all the periph clock via PMC. - */ -void PMC_DisableAllPeripherals(void) -{ - PMC->PMC_PCDR0 = MASK_STATUS0; - - while ((PMC->PMC_PCSR0 & MASK_STATUS0) != 0); - - PMC->PMC_PCDR1 = MASK_STATUS1; - - while ((PMC->PMC_PCSR1 & MASK_STATUS1) != 0); - - TRACE_DEBUG("Disable all periph clocks\n\r"); -} - -/** - * \brief Get Periph Status for the given peripheral ID. - * - * \param id Peripheral ID (ID_xxx). - */ -uint32_t PMC_IsPeriphEnabled(uint32_t dwId) -{ - assert(dwId < ID_PERIPH_COUNT); - - if (dwId < 32) - return (PMC->PMC_PCSR0 & (1 << dwId)); - else - return (PMC->PMC_PCSR1 & (1 << (dwId - 32))); -} - - -/** - * \brief Enable external oscillator as main clock input. - */ -void PMC_EnableExtOsc(void) -{ - uint32_t read_MOR; - - /* Before switching MAIN OSC on external crystal : enable it and don't disable - * at the same time RC OSC in case of if MAIN OSC is still using RC OSC - */ - - read_MOR = PMC->CKGR_MOR; - read_MOR &= ~CKGR_MOR_MOSCRCF_Msk; - /* reset MOSCRCF field in MOR register before select RC 12MHz */ - read_MOR |= (CKGR_MOR_KEY_PASSWD - | CKGR_MOR_MOSCRCF_12_MHz - | CKGR_MOR_MOSCXTEN - | CKGR_MOR_MOSCRCEN - | CKGR_MOR_MOSCXTST(DEFAUTL_MAIN_OSC_COUNT)); - /* enable external crystal - enable RC OSC */ - - PMC->CKGR_MOR = read_MOR; - - while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)); - - /* wait end of RC oscillator stabilization */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); - - read_MOR |= CKGR_MOR_MOSCSEL; - /* select external crystal */ - - PMC->CKGR_MOR = read_MOR; - - while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)); - - /* Wait end of Main Oscillator Selection */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); -} - -/** - * \brief Disable external 12MHz oscillator. - */ -void PMC_DisableExtOsc(void) -{ - uint32_t read_MOR; - - read_MOR = PMC->CKGR_MOR; - read_MOR &= ~CKGR_MOR_MOSCXTEN; /* disable main xtal osc */ - PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | read_MOR; - - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); -} - -/** - * \brief Select external OSC. - */ -void PMC_SelectExtOsc(void) -{ - /* switch from internal RC 12 MHz to external OSC 12 MHz */ - /* wait Main XTAL Oscillator stabilisation*/ - if ((PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) == CKGR_MOR_MOSCSEL) { - PMC_DisableIntRC4_8_12MHz(); - return; - } - - /* enable external OSC 12 MHz */ - PMC->CKGR_MOR |= CKGR_MOR_MOSCXTEN | CKGR_MOR_KEY_PASSWD; - - /* wait Main CLK Ready */ - while (!(PMC->CKGR_MCFR & CKGR_MCFR_MAINFRDY)); - - /* switch MAIN clock to external OSC 12 MHz*/ - PMC->CKGR_MOR |= CKGR_MOR_MOSCSEL | CKGR_MOR_KEY_PASSWD; - - /* wait MAIN clock status change for external OSC 12 MHz selection*/ - while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)); - - /* in case where MCK is running on MAIN CLK */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); - - PMC_DisableIntRC4_8_12MHz(); -} - - -/** - * \brief Select external OSC. - */ -void PMC_SelectExtBypassOsc(void) -{ - volatile uint32_t timeout; - - if ((PMC->CKGR_MOR & CKGR_MOR_MOSCXTBY) != CKGR_MOR_MOSCXTBY) { - PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | - CKGR_MOR_MOSCRCEN | - CKGR_MOR_MOSCXTST(0xFF) | - CKGR_MOR_MOSCXTBY; - PMC->CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCSEL; - - /* wait MAIN clock status change for external OSC 12 MHz selection*/ - while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)); - - // Check if an external clock is provided - for (timeout = 0; timeout < 0xffff; timeout++); - - while (!(PMC->CKGR_MCFR & CKGR_MCFR_MAINFRDY)); - } -} - -/** - * \brief Enable internal 4/8/12MHz fast RC as main clock input. - * - * \param freqSelect fast RC frequency (FAST_RC_4MHZ, FAST_RC_8MHZ, - * FAST_RC_12MHZ). - */ -void PMC_EnableIntRC4_8_12MHz(uint32_t freqSelect) -{ - /* Enable Fast RC oscillator but DO NOT switch to RC now */ - PMC->CKGR_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCEN); - - /* Wait the Fast RC to stabilize */ - while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)); - - /* Change Fast RC oscillator frequency */ - PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) | - CKGR_MOR_KEY_PASSWD | freqSelect; - - /* Wait the Fast RC to stabilize */ - while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)); - - /* Switch to Fast RC */ - PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | - CKGR_MOR_KEY_PASSWD; - - /* wait MAIN clock status change for Fast RC oscillator */ - while (!(PMC->PMC_SR & PMC_SR_MOSCSELS)); - - /* in case where MCK is running on MAIN CLK */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); - -} - -/** - * \brief Disable internal 4/8/12MHz fast RC. - */ -void PMC_DisableIntRC4_8_12MHz(void) -{ - uint32_t read_MOR; - - read_MOR = PMC->CKGR_MOR; - - read_MOR &= ~CKGR_MOR_MOSCRCF_Msk; /* reset MOSCRCF field in MOR register */ - read_MOR &= ~CKGR_MOR_MOSCRCEN; /* disable fast RC */ - PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | read_MOR; - - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); -} - -/** - * \brief Configure PLLA clock by giving MUL and DIV. - * Disable PLLA when 'mul' set to 0. - * - * \param mul PLL multiplier factor. - * \param div PLL divider factor. - */ -void PMC_SetPllaClock(uint32_t mul, uint32_t div) -{ - if (mul != 0) { - /* Init PLL speed */ - PMC->CKGR_PLLAR = CKGR_PLLAR_ONE - | CKGR_PLLAR_PLLACOUNT(DEFAUTL_PLLA_COUNT) - | CKGR_PLLAR_MULA(mul - 1) - | CKGR_PLLAR_DIVA(div); - - /* Wait for PLL stabilization */ - while (!(PMC->PMC_SR & PMC_SR_LOCKA)); - } else { - PMC->CKGR_PLLAR = CKGR_PLLAR_ONE; /* disable PLL A */ - } -} - -/** - * \brief Selection of Master Clock. - * - * \param clockSource Master Clock source. - * \param prescaler Master Clock prescaler. - * - * \note - * The PMC_MCKR register must not be programmed in a single write - * operation (see. Product Data Sheet). - */ -void PMC_SetMckSelection(uint32_t clockSource, uint32_t prescaler) -{ - switch (clockSource) { - case PMC_MCKR_CSS_SLOW_CLK : - _PMC_SwitchMck2SlowClock(); - _PMC_SetMckPrescaler(prescaler); - break; - - case PMC_MCKR_CSS_MAIN_CLK : - _PMC_SwitchMck2MainClock(); - _PMC_SetMckPrescaler(prescaler); - break; - - case PMC_MCKR_CSS_PLLA_CLK : - _PMC_SetMckPrescaler(prescaler); - _PMC_SwitchMck2PllaClock(); - break; - } -} - -/** - * \brief Disable all clocks. - */ -void PMC_DisableAllClocks(void) -{ - uint32_t read_reg; - - PMC->PMC_SCDR = PMC_SCDR_PCK0 | PMC_SCDR_PCK1 | PMC_SCDR_PCK2 | PMC_SCDR_PCK3 | - PMC_SCDR_PCK4 | PMC_SCDR_PCK5 | PMC_SCDR_PCK6; /* disable PCK */ - - _PMC_SwitchMck2MainClock(); - - PMC->CKGR_PLLAR = PMC->CKGR_PLLAR & ~CKGR_PLLAR_MULA_Msk; /* disable PLL A */ - - _PMC_SwitchMck2SlowClock(); - - read_reg = PMC->CKGR_MOR; - read_reg = (read_reg & ~CKGR_MOR_MOSCRCEN) | CKGR_MOR_KEY_PASSWD; - /* disable RC OSC */ - - PMC->CKGR_MOR = read_reg; - - PMC_DisableAllPeripherals(); /* disable all peripheral clocks */ -} - -/** - * \brief Configure PLLA as clock input for MCK. - * - * \param mul PLL multiplier factor (not shifted, don't minus 1). - * \param div PLL divider factor (not shifted). - * \param prescaler Master Clock prescaler (shifted as in register). - */ -void PMC_ConfigureMckWithPlla(uint32_t mul, uint32_t div, uint32_t prescaler) -{ - /* First, select Main OSC as input clock for MCK */ - _PMC_SwitchMck2MainClock(); - - /* Then, Set PLLA clock */ - PMC_SetPllaClock(mul, div); - - /* Wait until the master clock is established for the case we already - turn on the PLL */ - while (!(PMC->PMC_SR & PMC_SR_MCKRDY)); - - /* Finally, select PllA as input clock for MCK */ - PMC_SetMckSelection(PMC_MCKR_CSS_PLLA_CLK, prescaler); -} - - -/** - * \brief Configure PLLA as clock input for MCK. - * - * \param mul PLL multiplier factor (not shifted, don't minus 1). - * \param div PLL divider factor (not shifted). - * \param prescaler Master Clock prescaler (shifted as in register). - */ -void PMC_EnableXT32KFME(void) -{ - - uint32_t read_MOR; - - /* Before switching MAIN OSC on external crystal : enable it and don't - disable at the same time RC OSC in case of if MAIN OSC is still using - RC OSC */ - - read_MOR = PMC->CKGR_MOR; - - read_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_XT32KFME); - /* enable external crystal - enable RC OSC */ - - PMC->CKGR_MOR = read_MOR; - -} - -/** - * \brief Configure PLLA as clock input for MCK. - * - * \param mul PLL multiplier factor (not shifted, don't minus 1). - * \param div PLL divider factor (not shifted). - * \param prescaler Master Clock prescaler (shifted as in register). - */ -void PMC_ConfigurePCK0(uint32_t MasterClk, uint32_t prescaler) -{ - PMC->PMC_SCDR = PMC_SCDR_PCK0; /* disable PCK */ - - while ((PMC->PMC_SCSR)& PMC_SCSR_PCK0); - - PMC->PMC_PCK[0] = MasterClk | prescaler; - PMC->PMC_SCER = PMC_SCER_PCK0; - - while (!((PMC->PMC_SR) & PMC_SR_PCKRDY0)); - -} - - -/** - * \brief Configure PLLA as clock input for MCK. - * - * \param mul PLL multiplier factor (not shifted, don't minus 1). - * \param div PLL divider factor (not shifted). - * \param prescaler Master Clock prescaler (shifted as in register). - */ -void PMC_ConfigurePCK1(uint32_t MasterClk, uint32_t prescaler) -{ - PMC->PMC_SCDR = PMC_SCDR_PCK1; /* disable PCK */ - - while ((PMC->PMC_SCSR)& PMC_SCSR_PCK1); - - PMC->PMC_PCK[1] = MasterClk | prescaler; - PMC->PMC_SCER = PMC_SCER_PCK1; - - while (!((PMC->PMC_SR) & PMC_SR_PCKRDY1)); - -} - -/** - * \brief Configure PLLA as clock input for MCK. - * - * \param mul PLL multiplier factor (not shifted, don't minus 1). - * \param div PLL divider factor (not shifted). - * \param prescaler Master Clock prescaler (shifted as in register). - */ -void PMC_ConfigurePCK2(uint32_t MasterClk, uint32_t prescaler) -{ - PMC->PMC_SCDR = PMC_SCDR_PCK2; /* disable PCK */ - - while ((PMC->PMC_SCSR)& PMC_SCSR_PCK2); - - PMC->PMC_PCK[2] = MasterClk | prescaler; - PMC->PMC_SCER = PMC_SCER_PCK2; - - while (!((PMC->PMC_SR) & PMC_SR_PCKRDY2)); - -} |