zephyr/soc/arc/quark_se_c1000_ss/power.c

106 lines
2.4 KiB
C
Raw Normal View History

/*
* Copyright (c) 2016 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <sys_io.h>
#include <misc/__assert.h>
#include <power.h>
#include <soc_power.h>
#include <init.h>
#include <kernel_structs.h>
quark_se: PM: Add multicore support This patch changes Quark SE power drivers to support multicore scenarios e.g. both LMT and ARC core are enabled and manage power. Handling LPS states in multicore scenarios are dead simple because LPS states are core-specific states. It means that putting the LMT core in LPS doesn't affect the ARC core, and vice-versa. DEEP_SLEEP state, on the other hand, affects both cores since it turns power off from the SoC and both cores are shutdown. It means that if LMT puts the system in DEEP_SLEEP, ARC core is shutdown even if it is busy handling some task. In order to support the multicore scenario, this patch introduces the SYS_POWER_STATE_DEEP_SLEEP_2 state to both ARC and x86 power drivers. On ARC, this state works as following: 1) Save ARC execution context; 2) Raise a flag to inform the x86 core that ARC is ready to enter in DEEP_SLEEP; 3) Enter in the lowest core-specific power state, which in this case is LPSS. On x86, DEEP_SLEEP_2 is very similar to DEEP_SLEEP. The difference relies in the post_ops() which calls _arc_init() in order to start ARC core so it can restore its context. This patch also adds the test/power/multicore/ directory which provides sample application to x86 and ARC cores in order to easily verify the multicore support. In test/power/multicore/README.rst you can find more details regarding the applications. Jira: ZEP-1103 Change-Id: Ie28ba6d193ea0e58fca69d38f8d3c38ca259a9ef Signed-off-by: Andre Guedes <andre.guedes@intel.com>
2016-12-22 05:26:17 +08:00
#include <soc.h>
#include "power_states.h"
#include "ss_power_states.h"
#include "vreg.h"
#if (defined(CONFIG_SYS_POWER_DEEP_SLEEP))
extern void _power_soc_sleep(void);
extern void _power_soc_deep_sleep(void);
extern void _power_soc_lpss_mode(void);
static void _deep_sleep(enum power_states state)
{
qm_power_soc_set_ss_restore_flag();
switch (state) {
case SYS_POWER_STATE_DEEP_SLEEP_1:
_power_soc_sleep();
break;
case SYS_POWER_STATE_DEEP_SLEEP_2:
_power_soc_deep_sleep();
break;
default:
break;
}
}
#endif
void _sys_soc_set_power_state(enum power_states state)
{
switch (state) {
case SYS_POWER_STATE_CPU_LPS:
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;
#if (defined(CONFIG_SYS_POWER_DEEP_SLEEP))
case SYS_POWER_STATE_DEEP_SLEEP:
qm_ss_power_soc_lpss_enable();
qm_power_soc_set_ss_restore_flag();
_power_soc_lpss_mode();
break;
case SYS_POWER_STATE_DEEP_SLEEP_1:
case SYS_POWER_STATE_DEEP_SLEEP_2:
_deep_sleep(state);
quark_se: PM: Add multicore support This patch changes Quark SE power drivers to support multicore scenarios e.g. both LMT and ARC core are enabled and manage power. Handling LPS states in multicore scenarios are dead simple because LPS states are core-specific states. It means that putting the LMT core in LPS doesn't affect the ARC core, and vice-versa. DEEP_SLEEP state, on the other hand, affects both cores since it turns power off from the SoC and both cores are shutdown. It means that if LMT puts the system in DEEP_SLEEP, ARC core is shutdown even if it is busy handling some task. In order to support the multicore scenario, this patch introduces the SYS_POWER_STATE_DEEP_SLEEP_2 state to both ARC and x86 power drivers. On ARC, this state works as following: 1) Save ARC execution context; 2) Raise a flag to inform the x86 core that ARC is ready to enter in DEEP_SLEEP; 3) Enter in the lowest core-specific power state, which in this case is LPSS. On x86, DEEP_SLEEP_2 is very similar to DEEP_SLEEP. The difference relies in the post_ops() which calls _arc_init() in order to start ARC core so it can restore its context. This patch also adds the test/power/multicore/ directory which provides sample application to x86 and ARC cores in order to easily verify the multicore support. In test/power/multicore/README.rst you can find more details regarding the applications. Jira: ZEP-1103 Change-Id: Ie28ba6d193ea0e58fca69d38f8d3c38ca259a9ef Signed-off-by: Andre Guedes <andre.guedes@intel.com>
2016-12-22 05:26:17 +08:00
break;
#endif
default:
break;
}
}
void _sys_soc_power_state_post_ops(enum power_states state)
{
u32_t limit;
switch (state) {
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);
case SYS_POWER_STATE_CPU_LPS:
__builtin_arc_seti(0);
break;
case SYS_POWER_STATE_DEEP_SLEEP:
qm_ss_power_soc_lpss_disable();
quark_se: PM: Add multicore support This patch changes Quark SE power drivers to support multicore scenarios e.g. both LMT and ARC core are enabled and manage power. Handling LPS states in multicore scenarios are dead simple because LPS states are core-specific states. It means that putting the LMT core in LPS doesn't affect the ARC core, and vice-versa. DEEP_SLEEP state, on the other hand, affects both cores since it turns power off from the SoC and both cores are shutdown. It means that if LMT puts the system in DEEP_SLEEP, ARC core is shutdown even if it is busy handling some task. In order to support the multicore scenario, this patch introduces the SYS_POWER_STATE_DEEP_SLEEP_2 state to both ARC and x86 power drivers. On ARC, this state works as following: 1) Save ARC execution context; 2) Raise a flag to inform the x86 core that ARC is ready to enter in DEEP_SLEEP; 3) Enter in the lowest core-specific power state, which in this case is LPSS. On x86, DEEP_SLEEP_2 is very similar to DEEP_SLEEP. The difference relies in the post_ops() which calls _arc_init() in order to start ARC core so it can restore its context. This patch also adds the test/power/multicore/ directory which provides sample application to x86 and ARC cores in order to easily verify the multicore support. In test/power/multicore/README.rst you can find more details regarding the applications. Jira: ZEP-1103 Change-Id: Ie28ba6d193ea0e58fca69d38f8d3c38ca259a9ef Signed-off-by: Andre Guedes <andre.guedes@intel.com>
2016-12-22 05:26:17 +08:00
/* If flag is cleared it means the system entered in
* sleep state while we were in LPS. In that case, we
* must set ARC_READY flag so x86 core can continue
* its execution.
*/
if ((QM_SCSS_GP->gp0 & GP0_BIT_SLEEP_READY) == 0) {
_quark_se_ss_ready();
__builtin_arc_seti(0);
} else {
QM_SCSS_GP->gp0 &= ~GP0_BIT_SLEEP_READY;
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;
}
}