zephyr/arch/x86/soc/intel_quark/quark_se/power.c

113 lines
2.5 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>
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"
#define _REG_TIMER_ICR ((volatile u32_t *) \
(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_TIMER_ICR))
/* Variables used to save CPU state */
u64_t _pm_save_gdtr;
u64_t _pm_save_idtr;
u32_t _pm_save_esp;
extern void _power_soc_sleep(void);
extern void _power_restore_cpu_context(void);
extern void _power_soc_deep_sleep(void);
#if (defined(CONFIG_SYS_POWER_DEEP_SLEEP))
static u32_t *__x86_restore_info =
(u32_t *)CONFIG_BSP_SHARED_RESTORE_INFO_RAM_ADDR;
static void _deep_sleep(enum power_states state)
{
/*
* Setting resume vector inside the restore_cpu_context
* function since we have nothing to do before cpu context
* is restored. If necessary, it is possible to set the
* resume vector to a location where additional processing
* can be done before cpu context is restored and control
* transferred to _sys_soc_suspend.
*/
qm_x86_set_resume_vector(_power_restore_cpu_context,
*__x86_restore_info);
qm_power_soc_set_x86_restore_flag();
switch (state) {
case SYS_POWER_STATE_DEEP_SLEEP_1:
_power_soc_sleep();
break;
case SYS_POWER_STATE_DEEP_SLEEP:
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
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_power_cpu_c2lp();
break;
case SYS_POWER_STATE_CPU_LPS_1:
qm_power_cpu_c2();
break;
case SYS_POWER_STATE_CPU_LPS_2:
qm_power_cpu_c1();
break;
#if (defined(CONFIG_SYS_POWER_DEEP_SLEEP))
case SYS_POWER_STATE_DEEP_SLEEP:
case SYS_POWER_STATE_DEEP_SLEEP_1:
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
case SYS_POWER_STATE_DEEP_SLEEP_2:
_deep_sleep(state);
break;
#endif
default:
break;
}
}
void _sys_soc_power_state_post_ops(enum power_states state)
{
switch (state) {
case SYS_POWER_STATE_CPU_LPS:
*_REG_TIMER_ICR = 1;
case SYS_POWER_STATE_CPU_LPS_1:
__asm__ volatile("sti");
break;
#if (defined(CONFIG_SYS_POWER_DEEP_SLEEP))
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
case SYS_POWER_STATE_DEEP_SLEEP_2:
#ifdef CONFIG_ARC_INIT
_arc_init(NULL);
#endif /* CONFIG_ARC_INIT */
/* Fallthrough */
case SYS_POWER_STATE_DEEP_SLEEP:
case SYS_POWER_STATE_DEEP_SLEEP_1:
__asm__ volatile("sti");
break;
#endif
default:
break;
}
}
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
bool _sys_soc_power_state_is_arc_ready(void)
{
return QM_SCSS_GP->gp0 & GP0_BIT_SLEEP_READY ? true : false;
}