Commit fe48f743 authored by Ramakrishna Pallala's avatar Ramakrishna Pallala Committed by Anas Nashif
Browse files

arch: arc: Fix Deep Sleep hang issue on Quark SE(ARC)



Fixed the RTC interrupt masking issue on Deep Sleep entry by
explicitly unmasking it on Deep Sleep exit sequence.

Re-oredered the SoC power states such that SYS_POWER_STATE_CPU_LPS is
the lowest possible Low Power State(LPS) and SYS_POWER_STATE_CPU_LPS_2
is the highest possible Low Power State(LPS). This is need to maintain
the LPS state consistency across different architectures.

Also re-mapped the Low Power States and Deep Sleep States as per
Quark SE C1000 data sheet document under Power Management section.

Signed-off-by: default avatarRamakrishna Pallala <ramakrishna.pallala@intel.com>
parent 2e615181
Loading
Loading
Loading
Loading
+17 −18
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
#if (defined(CONFIG_SYS_POWER_DEEP_SLEEP))
extern void _power_soc_sleep(void);
extern void _power_soc_deep_sleep(void);
extern void _power_soc_deep_sleep_2(void);
extern void _power_soc_lpss_mode(void);

static void _deep_sleep(enum power_states state)
{
@@ -30,7 +30,7 @@ static void _deep_sleep(enum power_states state)
	case SYS_POWER_STATE_DEEP_SLEEP_1:
		_power_soc_sleep();
		break;
	case SYS_POWER_STATE_DEEP_SLEEP:
	case SYS_POWER_STATE_DEEP_SLEEP_2:
		_power_soc_deep_sleep();
		break;
	default:
@@ -43,24 +43,20 @@ void _sys_soc_set_power_state(enum power_states state)
{
	switch (state) {
	case SYS_POWER_STATE_CPU_LPS:
		qm_ss_power_soc_lpss_enable();
		qm_ss_power_cpu_ss2();
		qm_ss_power_cpu_ss1(QM_SS_POWER_CPU_SS1_TIMER_ON);
		break;
	case SYS_POWER_STATE_CPU_LPS_1:
		qm_ss_power_cpu_ss2();
		break;
	case SYS_POWER_STATE_CPU_LPS_2:
		qm_ss_power_cpu_ss1(QM_SS_POWER_CPU_SS1_TIMER_ON);
		break;
#if (defined(CONFIG_SYS_POWER_DEEP_SLEEP))
	case SYS_POWER_STATE_DEEP_SLEEP:
	case SYS_POWER_STATE_DEEP_SLEEP_1:
		_deep_sleep(state);
		break;
	case SYS_POWER_STATE_DEEP_SLEEP_2:
		qm_ss_power_soc_lpss_enable();
		qm_power_soc_set_ss_restore_flag();
		_power_soc_deep_sleep_2();
		_power_soc_lpss_mode();
		break;
	case SYS_POWER_STATE_DEEP_SLEEP_1:
	case SYS_POWER_STATE_DEEP_SLEEP_2:
		_deep_sleep(state);
		break;
#endif
	default:
@@ -73,18 +69,14 @@ void _sys_soc_power_state_post_ops(enum power_states state)
	u32_t limit;

	switch (state) {
	case SYS_POWER_STATE_CPU_LPS:
		qm_ss_power_soc_lpss_disable();
	case SYS_POWER_STATE_CPU_LPS_1:
		/* Expire the timer as it is disabled in SS2. */
		limit = _arc_v2_aux_reg_read(_ARC_V2_TMR0_LIMIT);
		_arc_v2_aux_reg_write(_ARC_V2_TMR0_COUNT, limit - 1);
		break;
	case SYS_POWER_STATE_DEEP_SLEEP:
	case SYS_POWER_STATE_DEEP_SLEEP_1:
	case SYS_POWER_STATE_CPU_LPS:
		__builtin_arc_seti(0);
		break;
	case SYS_POWER_STATE_DEEP_SLEEP_2:
	case SYS_POWER_STATE_DEEP_SLEEP:
		qm_ss_power_soc_lpss_disable();

		/* If flag is cleared it means the system entered in
@@ -100,6 +92,13 @@ void _sys_soc_power_state_post_ops(enum power_states state)
			QM_SCSS_GP->gps0 &= ~QM_GPS0_BIT_SENSOR_WAKEUP;
		}
		break;
	case SYS_POWER_STATE_DEEP_SLEEP_1:
	case SYS_POWER_STATE_DEEP_SLEEP_2:
		/* Route RTC interrupt to the current core */
		QM_IR_UNMASK_INTERRUPTS(QM_INTERRUPT_ROUTER->rtc_0_int_mask);
		__builtin_arc_seti(0);
		break;
		break;
	default:
		break;
	}
+2 −2
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ GTEXT(_sys_soc_resume_from_deep_sleep)
GTEXT(_power_restore_cpu_context)
GTEXT(_power_soc_sleep)
GTEXT(_power_soc_deep_sleep)
GTEXT(_power_soc_deep_sleep_2)
GTEXT(_power_soc_lpss_mode)

#define GPS0_REGISTER  0xb0800100
#define GP0_REGISTER 0xb0800114
@@ -73,7 +73,7 @@ SECTION_FUNC(TEXT, _power_soc_deep_sleep)
	j @qm_power_soc_deep_sleep
	/* Does not return */

SECTION_FUNC(TEXT, _power_soc_deep_sleep_2)
SECTION_FUNC(TEXT, _power_soc_lpss_mode)
	/*
	 * Setup 'sleep' instruction operand.
	 */
+6 −9
Original line number Diff line number Diff line
@@ -20,15 +20,12 @@ extern "C" {
#define GP0_BIT_SLEEP_READY BIT(0)

enum power_states {
	SYS_POWER_STATE_CPU_LPS,       /* SS2 with LPSS enabled state */
	SYS_POWER_STATE_CPU_LPS,       /* SS1 state with Timer ON */
	SYS_POWER_STATE_CPU_LPS_1,     /* SS2 state */
	SYS_POWER_STATE_CPU_LPS_2,     /* SS1 state with Timer ON */
	SYS_POWER_STATE_DEEP_SLEEP,    /* DEEP SLEEP state */
	SYS_POWER_STATE_DEEP_SLEEP,    /* SS2 with LPSS enabled state */
	SYS_POWER_STATE_DEEP_SLEEP_1,  /* SLEEP state */
	SYS_POWER_STATE_DEEP_SLEEP_2,  /* Multicore DEEP SLEEP state.
					* Execution context is saved
					* and core enters in LPS state.
					*/
	SYS_POWER_STATE_DEEP_SLEEP_2,  /* SLEEP state with LPMODE enabled */

	SYS_POWER_STATE_MAX
};

@@ -41,12 +38,12 @@ enum power_states {
 * Wake up considerations:
 * -----------------------
 *
 * SYS_POWER_STATE_CPU_LPS_2: Any interrupt works as wake event.
 * SYS_POWER_STATE_CPU_LPS: Any interrupt works as wake event.
 *
 * SYS_POWER_STATE_CPU_LPS_1: Any interrupt works as wake event except
 * the ARC TIMER which is disabled.
 *
 * SYS_POWER_STATE_CPU_LPS: SYS_POWER_STATE_DEEP_SLEEP wake events applies.
 * SYS_POWER_STATE_CPU_LPS_2: SYS_POWER_STATE_DEEP_SLEEP wake events applies.
 *
 * SYS_POWER_STATE_DEEP_SLEEP: Only Always-On peripherals can wake up
 * the SoC. This consists of the Counter, RTC, GPIO 1 and AIO Comparator.