Ejemplo n.º 1
0
STATIC bool setup_timer_lpds_wake (void) {
    uint64_t t_match, t_curr;
    int64_t t_remaining;

    // get the time remaining for the RTC timer to expire
    t_match = MAP_PRCMSlowClkCtrMatchGet();
    t_curr  = MAP_PRCMSlowClkCtrGet();

    // get the time remaining in terms of slow clocks
    t_remaining = (t_match - t_curr);
    if (t_remaining > WAKEUP_TIME_LPDS) {
        // subtract the time it takes to wakeup from lpds
        t_remaining -= WAKEUP_TIME_LPDS;
        t_remaining = (t_remaining > 0xFFFFFFFF) ? 0xFFFFFFFF: t_remaining;
        // setup the LPDS wake time
        MAP_PRCMLPDSIntervalSet((uint32_t)t_remaining);
        // enable the wake source
        MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER);
        return true;
    }

    // disable the timer as wake source
    MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);

    uint32_t f_seconds;
    uint16_t f_mseconds;
    // setup a timer interrupt immediately
    pyb_rtc_calc_future_time (FORCED_TIMER_INTERRUPT_MS, &f_seconds, &f_mseconds);
    MAP_PRCMRTCMatchSet(f_seconds, f_mseconds);
    // LPDS wake by timer was not possible, force an interrupt in active mode instead
    MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);

    return false;
}
Ejemplo n.º 2
0
//****************************************************************************
//
//! \brief  Setting various wake sources for the device
//!
//! \param  target is the lowest power mode that the deveice will exercise
//!
//! \return 0 if success, -1 in case of error
//
//****************************************************************************
int set_wkup_srcs(enum soc_pm target)
{
	int iRetVal = -1;
	switch(target) {
			case e_pm_S0:
			case e_pm_S1:
			case e_pm_S2:
				/* These handle the cases of run, sleep, deepsleep.
				   Wake source is configured outside this scope in
				   individual peripherals */
				break;
			case e_pm_S3:
				if(lpds_wk_info.wk_type &  WK_RTC)
				{
						/* Setup the LPDS wake time */
						MAP_PRCMLPDSIntervalSet(lpds_wk_info.timer_interval * 32768);
						/* Enable the wake source to be timer */
						MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER);
						iRetVal = 0;
				}
				if(lpds_wk_info.wk_type &  WK_GPIO)
				{
						MAP_PRCMLPDSWakeUpGPIOSelect(lpds_wk_info.wk_gpio_pin,lpds_wk_info.trigger_type);
						MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_GPIO);
						iRetVal = 0;
				}
				if(lpds_wk_info.wk_type &  WK_HOST_IRQ)
				{
						/* Set LPDS Wakeup source as NWP request */
						MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_HOST_IRQ);
						iRetVal = 0;
				}
				if(lpds_wk_info.is_periodic == false)
				{
						lpds_wk_info.wk_type &= (~WK_RTC);
				}
				break;
			case e_pm_S4:
				if(hib_wk_info.wk_type &  WK_RTC)
				{
					/* Setup the LPDS wake time */
					MAP_PRCMHibernateIntervalSet(hib_wk_info.timer_interval * 32768);
					/* Enable the wake source to be timer */
					MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
					iRetVal = 0;
				}
				if(hib_wk_info.wk_type &  WK_GPIO)
				{
						MAP_PRCMHibernateWakeUpGPIOSelect(hib_wk_info.wk_gpio_pin,hib_wk_info.trigger_type);
						MAP_PRCMHibernateWakeupSourceEnable(hib_wk_info.wk_gpio_pin);
						iRetVal = 0;
				}
				break;
			default:
				return -1;
	}
	return iRetVal;
}
Ejemplo n.º 3
0
/* Sets up wake-up sources for indicated power mode */
i32 cc_set_up_wkup_srcs(enum soc_pm target)
{
        i32 nw_ret = -1, gpio_ret = -1, timer_ret = -1;
        switch(target) {
                case e_pm_S0:
                case e_pm_S1:
                case e_pm_S2:
                        /* These handle the cases of run, sleep, deepsleep.
                           Wake source is configured outside this scope in 
                           individual peripherals */
                        break;
                case e_pm_S3:
                        /* Low power deep sleep condition */
                        /* Network (Host IRQ) based wakeup is always enabled */
                        nw_ret = setup_S3_wakeup_from_nw(); 
                        /* Check and enable GPIO based wakeup */
                        gpio_ret = check_n_setup_S3_wakeup_from_gpio();
                        /* Check and enable LRT based wakeup */
                        timer_ret = check_n_setup_S3_wakeup_from_timer();
                        break;
                case e_pm_S4:
                        /* Hibernate condition */
                        /* Check and enable GPIO based wakeup */
                        gpio_ret = check_n_setup_S4_wakeup_from_gpio();
                        /* Check and enable LRT based wakeup */
                        timer_ret = check_n_setup_S4_wakeup_from_timer();
                        break;
                default:
                        break;
        }

        if(ERR_TIMER_TO_WAKE == timer_ret) {
                return -1;
        }
        if((nw_ret < 0) && (gpio_ret < 0) && (timer_ret < 0)) {
                return -1;
        }
        else if((gpio_ret < 0) && (timer_ret < 0)) {
				/* Setup the LPDS wake time */
				MAP_PRCMLPDSIntervalSet(LPDS_WDOG_TIME);
				/* Enable the wake source to be timer */
				MAP_PRCMLPDSWakeupSourceEnable(
						PRCM_LPDS_TIMER);
        }
        return 0;
}
Ejemplo n.º 4
0
/* Timer based wakeup from S3 (LPDS) */
static i32 check_n_setup_S3_wakeup_from_timer()
{
        u64 scc_match, scc_curr, scc_remaining;

        /* Check if there is an alarm set */
        if(cc_rtc_has_alarm()) {
                /* Get the time remaining for the RTC timer to expire */
                scc_match = MAP_PRCMSlowClkCtrMatchGet();
                scc_curr = MAP_PRCMSlowClkCtrGet();
                
                if(scc_match > scc_curr) {
                        /* Get the time remaining in terms of slow clocks */
                        scc_remaining = (scc_match - scc_curr);
                        if(scc_remaining > WAKEUP_TIME_LPDS) {
                                /* Subtract the time it takes for wakeup 
                                   from S3 (LPDS) */
                                scc_remaining -= WAKEUP_TIME_LPDS;
                                scc_remaining = (scc_remaining > 0xFFFFFFFF)?
                                        0xFFFFFFFF: scc_remaining;
                                /* Setup the LPDS wake time */
                                MAP_PRCMLPDSIntervalSet(
                                        (u32)scc_remaining);
                                /* Enable the wake source to be timer */
                                MAP_PRCMLPDSWakeupSourceEnable(
                                        PRCM_LPDS_TIMER);
                        } else {
                                /* Cannot enter LPDS */
                                return ERR_TIMER_TO_WAKE;
                        }
                } else {
                       return ERR_TIMER_TO_WAKE;
                }
        } else {
                /* Disable timer as the wake source  */
                MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
                return -1;
        }

        return 0;
}
/*
 *  ======== PowerCC3200_sleepPolicy ========
 */
void PowerCC3200_sleepPolicy()
{
    bool returnFromSleep = FALSE;
    uint32_t constraintMask;
    uint32_t ticks;
    uint64_t time;
    uint64_t match;
    uint64_t curr;
    uint64_t remain;
    uint32_t taskKey;
    uint32_t swiKey;

    /* disable interrupts */
    CPUcpsid();

    /* disable Swi and Task scheduling */
    swiKey = Swi_disable();
    taskKey = Task_disable();

    /* query the declared constraints */
    constraintMask = Power_getConstraintMask();

    /*
     *  Do not go into LPDS if not allowed into DEEPSLEEP.
     *  Check to see if we can go into LPDS (lowest level sleep).
     *  If not allowed, then attempt to go into DEEPSLEEP.
     *  If not allowed in DEEPSLEEP then just SLEEP.
     */

     /* check if we are allowed to go to LPDS */
    if ((constraintMask &
        ((1 << PowerCC3200_DISALLOW_LPDS) |
        (1 << PowerCC3200_DISALLOW_DEEPSLEEP))) == 0) {
        /*
         * Check how many ticks until the next scheduled wakeup.  A value of
         * zero indicates a wakeup will occur as the current Clock tick period
         * expires; a very large value indicates a very large number of Clock
         * tick periods will occur before the next scheduled wakeup.
         */
        /* Get the time remaining for the RTC timer to expire */
        ticks = Clock_getTicksUntilInterrupt();

        /* convert ticks to microseconds */
        time = ticks * Clock_tickPeriod;

        /* check if can go to LPDS */
        if (time > Power_getTransitionLatency(PowerCC3200_LPDS, Power_TOTAL)) {
            /* get the current and match values for RTC */
            match = MAP_PRCMSlowClkCtrMatchGet();
            curr = MAP_PRCMSlowClkCtrGet();
            remain = match - curr -
                (((uint64_t)PowerCC3200_TOTALTIMELPDS * 32768) / 1000000);

            /* set the LPDS wakeup time interval */
            MAP_PRCMLPDSIntervalSet(remain);

            /* enable the wake source to be timer */
            MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER);

            /* go to LPDS mode */
            Power_sleep(PowerCC3200_LPDS);

            /* set 'returnFromSleep' to TRUE*/
            returnFromSleep = TRUE;
        }
    }

    /* check if we are allowed to go to DEEPSLEEP */
    if ((constraintMask & (1 << PowerCC3200_DISALLOW_DEEPSLEEP) == 0) &&
        (!returnFromSleep)) {
        /*
         * Check how many ticks until the next scheduled wakeup.  A value of
         * zero indicates a wakeup will occur as the current Clock tick period
         * expires; a very large value indicates a very large number of Clock
         * tick periods will occur before the next scheduled wakeup.
         */
        ticks = Clock_getTicksUntilInterrupt();

        /* convert ticks to microseconds */
        time = ticks * Clock_tickPeriod;

        /* check if can go to DEEPSLEEP */
        if (time > Power_getTransitionLatency(PowerCC3200_DEEPSLEEP,
            Power_TOTAL)) {
            /* schedule the wakeup event */
            ticks -= PowerCC3200_RESUMETIMEDEEPSLEEP / Clock_tickPeriod;
            Clock_setTimeout(Clock_handle(&clockObj), ticks);
            Clock_start(Clock_handle(&clockObj));

            /* go to DEEPSLEEP mode */
            Power_sleep(PowerCC3200_DEEPSLEEP);
            Clock_stop(Clock_handle(&clockObj));

            /* set 'returnFromSleep' to TRUE so we don't go to sleep (below) */
            returnFromSleep = TRUE;
        }
    }

    /* re-enable interrupts */
    CPUcpsie();

    /* restore Swi scheduling */
    Swi_restore(swiKey);

    /* restore Task scheduling */
    Task_restore(taskKey);

    /* sleep only if we are not returning from one of the sleep modes above */
    if (!(returnFromSleep)) {
        MAP_PRCMSleepEnter();
    }
}