Newer
Older
mbed-os / targets / TARGET_Maxim / TARGET_MAX32660 / Libraries / PeriphDrivers / Source / LP / lp_me11.c
@Sadik.Ozer Sadik.Ozer on 30 Sep 2021 10 KB Add MAX32660EVSYS
/**
 * @file    lp.c
 * @brief   Low power functions
 */

/* ****************************************************************************
 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the name of Maxim Integrated
 * Products, Inc. shall not be used except as stated in the Maxim Integrated
 * Products, Inc. Branding Policy.
 *
 * The mere transfer of this software does not imply any licenses
 * of trade secrets, proprietary technology, copyrights, patents,
 * trademarks, maskwork rights, or any other form of intellectual
 * property whatsoever. Maxim Integrated Products, Inc. retains all
 * ownership rights.
 *
 *
 *************************************************************************** */


/***** Includes *****/
#include "lp.h"
#include "pwrseq_regs.h"
#include "mxc_errors.h"
#include "gcr_regs.h"
#include "mxc_device.h"
#include "mxc_errors.h"
#include "mxc_pins.h"
#include "mxc_sys.h"
#include "flc.h"
#include "mxc_delay.h"

/***** Functions *****/
void MXC_LP_ClearWakeStatus(void)
{
    MXC_PWRSEQ->lp_wakefl = 0xFFFFFFFF;

    /* These flags are slow to clear, so block until they do */
    while(MXC_PWRSEQ->lp_wakefl & (MXC_PWRSEQ->lpwk_en));
}

void MXC_LP_EnableSRAM3(void)
{
    MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF;
}

void MXC_LP_DisableSRAM3(void)
{
    MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF;
}

void MXC_LP_EnableSRAM2(void)
{
    MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF;
}

void MXC_LP_DisableSRAM2(void)
{
    MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF;
}

void MXC_LP_EnableSRAM1(void)
{
    MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF;
}

void MXC_LP_DisableSRAM1(void)
{
    MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF;
}

void MXC_LP_EnableSRAM0(void)
{
    MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF;
}

void MXC_LP_DisableSRAM0(void)
{
    MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF;
}

void MXC_LP_EnableICacheLightSleep(void)
{
    MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_ICACHE_RET);
}

void MXC_LP_DisableICacheLightSleep(void)
{
    MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_ICACHE_RET);
}

void MXC_LP_EnableSysRAM3LightSleep(void)
{
    MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_RAM3_LS);
}

void MXC_LP_DisableSysRAM3LightSleep(void)
{
    MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_RAM3_LS);
}

void MXC_LP_EnableSysRAM2LightSleep(void)
{
    MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_RAM2_LS);
}

void MXC_LP_DisableSysRAM2LightSleep(void)
{
    MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_RAM2_LS);
}

void MXC_LP_EnableSysRAM1LightSleep(void)
{
    MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_RAM1_LS);
}

void MXC_LP_DisableSysRAM1LightSleep(void)
{
    MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_RAM1_LS);
}

void MXC_LP_EnableSysRAM0LightSleep(void)
{
    MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_RAM0_LS);
}

void MXC_LP_DisableSysRAM0LightSleep(void)
{
    MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_RAM0_LS);
}

void MXC_LP_EnableRTCAlarmWakeup(void)
{
    MXC_GCR->pm |= MXC_F_GCR_PM_RTCWK_EN;
}
    
void MXC_LP_DisableRTCAlarmWakeup(void)
{
    MXC_GCR->pm &= ~MXC_F_GCR_PM_RTCWK_EN;
}

void MXC_LP_EnableGPIOWakeup(unsigned int port, unsigned int mask)
{
    MXC_GCR->pm |= MXC_F_GCR_PM_GPIOWK_EN;
    //switch(port)
    //{
      /*case 0:*/ MXC_PWRSEQ->lpwk_en |= mask; //break;
    //}
}

void MXC_LP_DisableGPIOWakeup(unsigned int port, unsigned int mask)
{
    //switch(port)
    //{
    /*  case 0:*/ MXC_PWRSEQ->lpwk_en &= ~mask; //break;
    //}
    
    if(MXC_PWRSEQ->lpwk_en == 0)
    {
        MXC_GCR->pm &= ~MXC_F_GCR_PM_GPIOWK_EN;
    }
}

void MXC_LP_EnterSleepMode(void)
{    
    // Clear SLEEPDEEP bit 
    SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;

    // Go into Sleep mode and wait for an interrupt to wake the processor 
    __WFI();
}

void MXC_LP_EnterDeepSleepMode(void)
{    
    // Set SLEEPDEEP bit 
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    // Auto-powerdown 96 MHz oscillator when in deep sleep 
    MXC_GCR->pm |= MXC_F_GCR_PM_HFIOPD;
    // Go into Deepsleep mode and wait for an interrupt to wake the processor 
    __WFI();
}

void MXC_LP_EnterBackupMode(void)
{    
    MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
    MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP;
    while(1);
}

void MXC_LP_EnterShutdownMode(void)
{
    MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
    MXC_GCR->pm |= MXC_S_GCR_PM_MODE_SHUTDOWN;
    while(1);
}

int MXC_LP_SetOperatingVoltage(mxc_lp_ovr_t ovr)
{
    uint32_t current_clock, div;
    int error;

    // Ensure part is operating from internal LDO for core power
    if(MXC_PWRSEQ->lp_ctrl & MXC_F_PWRSEQ_LP_CTRL_LDO_DIS) {
        return E_BAD_STATE;
    }

    // Select the 8KHz nanoring (no guarantee 32KHz is attached) as system clock source
    current_clock = MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_CLKSEL;
    if(current_clock == MXC_SYS_CLOCK_HIRC) {
        error = MXC_SYS_Clock_Select(MXC_SYS_CLOCK_NANORING);
        if(error != E_NO_ERROR) {
            return error;
        }
    }

    // Set flash wait state for any clock so its not to low after clock changes.
    MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) | (0x5UL << MXC_F_GCR_MEM_CTRL_FWS_POS);

    // Set the OVR bits
    MXC_PWRSEQ->lp_ctrl &= ~(MXC_F_PWRSEQ_LP_CTRL_OVR);
    MXC_PWRSEQ->lp_ctrl |= ovr;

    // Set LVE bit
    if(ovr == MXC_LP_OVR_0_9) {
        MXC_FLC->ctrl |= MXC_F_FLC_CTRL_LVE;

    } else {
        MXC_FLC->ctrl &= ~(MXC_F_FLC_CTRL_LVE);
    }

    // Revert the clock to original state if it was HIRC
    if(current_clock == MXC_SYS_CLOCK_HIRC) {
       error = MXC_SYS_Clock_Select(MXC_SYS_CLOCK_HIRC);
       if(error != E_NO_ERROR) {
           return error;
       }
    }

    // Update SystemCoreClock variable
    SystemCoreClockUpdate();

    // Get the clock divider
    div = (MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_PSC) >> MXC_F_GCR_CLK_CTRL_PSC_POS;

    // Set Flash Wait States
    if(ovr == MXC_LP_OVR_0_9) {
        if(div == 0) {
            MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) | (0x2UL << MXC_F_GCR_MEM_CTRL_FWS_POS);

        } else {
            MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) | (0x1UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
        }

    } else if(ovr == MXC_LP_OVR_1_0) {  
        if(div == 0) {
            MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) | (0x2UL << MXC_F_GCR_MEM_CTRL_FWS_POS);

        } else {
            MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) | (0x1UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
        }

    } else {
        if(div == 0) {
            MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) | (0x4UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
        
        } else if(div == 1) {
            MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) | (0x2UL << MXC_F_GCR_MEM_CTRL_FWS_POS);

        } else {
            MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) | (0x1UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
        }
    }

    // Caller must perform peripheral reset

    return E_NO_ERROR;

}

void MXC_LP_EnableSRamRet0(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0;
}
 
void MXC_LP_DisableSRamRet0(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0;
}

void MXC_LP_EnableSRamRet1(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1;
}
 
void MXC_LP_DisableSRamRet1(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1;
}

void MXC_LP_EnableSRamRet2(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2;
}
 
void MXC_LP_DisableSRamRet2(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2;
}

void MXC_LP_EnableSRamRet3(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3;
}
 
void MXC_LP_DisableSRamRet3(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3;
}

void MXC_LP_EnableBlockDetect(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS; 
}

void MXC_LP_DisableBlockDetect(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS; 
}

void MXC_LP_EnableRamRetReg(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RETREG_EN;
}

void MXC_LP_DisableRamRetReg(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RETREG_EN;
}

void MXC_LP_EnableFastWk(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN;
}

void MXC_LP_DisableFastWk(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN;
}

void MXC_LP_EnableBandGap(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_BG_OFF;
}

void MXC_LP_DisableBandGap(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_BG_OFF;
}

void MXC_LP_EnableVCorePORSignal(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS;
}

void MXC_LP_DisableVCorePORSignal(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS;
}

void MXC_LP_EnableLDO(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_LDO_DIS;
}

void MXC_LP_DisableLDO(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_LDO_DIS;
}

void MXC_LP_EnableVCoreSVM(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS;
}

void MXC_LP_DisableVCoreSVM(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS;
}

void MXC_LP_EnableVDDIOPorMonitoF(void){
    MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS;
}

void MXC_LP_DisableVDDIOPorMonitor(void){
    MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS;
}