diff --git a/arch/arc/core/Makefile b/arch/arc/core/Makefile index 0ca3634f4f0..0fe47d0f623 100644 --- a/arch/arc/core/Makefile +++ b/arch/arc/core/Makefile @@ -4,7 +4,7 @@ ccflags-y +=-I$(srctree)/arch/$(ARCH)/include obj-y += thread.o thread_entry_wrapper.o \ cpu_idle.o fast_irq.o fatal.o fault.o \ fault_s.o irq_manage.o cache.o \ - isr_wrapper.o regular_irq.o swap_macros.h swap.o \ + isr_wrapper.o regular_irq.o swap.o \ sys_fatal_error_handler.o obj-y += prep_c.o \ diff --git a/arch/arc/core/fast_irq.S b/arch/arc/core/fast_irq.S index 5d1db9d575e..6ef3b4456e7 100644 --- a/arch/arc/core/fast_irq.S +++ b/arch/arc/core/fast_irq.S @@ -29,7 +29,7 @@ #include #include #include -#include "swap_macros.h" +#include GTEXT(_firq_enter) GTEXT(_firq_exit) diff --git a/arch/arc/core/fault_s.S b/arch/arc/core/fault_s.S index 1dddca13b5e..ee12ea08473 100644 --- a/arch/arc/core/fault_s.S +++ b/arch/arc/core/fault_s.S @@ -26,7 +26,7 @@ #include #include #include -#include "swap_macros.h" +#include GTEXT(_Fault) diff --git a/arch/arc/core/regular_irq.S b/arch/arc/core/regular_irq.S index 81860c752c7..216365d3966 100644 --- a/arch/arc/core/regular_irq.S +++ b/arch/arc/core/regular_irq.S @@ -30,7 +30,7 @@ #include #include #include -#include "swap_macros.h" +#include GTEXT(_rirq_enter) GTEXT(_rirq_exit) diff --git a/arch/arc/core/reset.S b/arch/arc/core/reset.S index 21511ec5269..dd31a7825e6 100644 --- a/arch/arc/core/reset.S +++ b/arch/arc/core/reset.S @@ -99,6 +99,11 @@ invalidate_dcache: done_cache_invalidate: +#if defined(CONFIG_SYS_POWER_DEEP_SLEEP) && \ + !defined(CONFIG_BOOTLOADER_CONTEXT_RESTORE) + jl @_sys_soc_resume_from_deep_sleep +#endif + #ifdef CONFIG_INIT_STACKS /* * use the main stack to call memset on the interrupt stack and the diff --git a/arch/arc/core/swap.S b/arch/arc/core/swap.S index 90732209e49..2176437918e 100644 --- a/arch/arc/core/swap.S +++ b/arch/arc/core/swap.S @@ -31,7 +31,7 @@ #include #include #include -#include "swap_macros.h" +#include GTEXT(_Swap) GTEXT(_get_next_ready_thread) diff --git a/arch/arc/core/swap_macros.h b/arch/arc/include/swap_macros.h similarity index 99% rename from arch/arc/core/swap_macros.h rename to arch/arc/include/swap_macros.h index 348e0c27884..7a732eb7ceb 100644 --- a/arch/arc/core/swap_macros.h +++ b/arch/arc/include/swap_macros.h @@ -155,8 +155,8 @@ extern "C" { * * The pc and status32 values will still be on the stack. We cannot * pop them yet because the callers of _pop_irq_stack_frame must reload - * status32 differently depending on the execution context they are running - * in (_Swap(), firq or exception). + * status32 differently depending on the execution context they are + * running in (_Swap(), firq or exception). */ add_s sp, sp, ___isf_t_SIZEOF diff --git a/arch/arc/soc/quark_se_c1000_ss/Kbuild b/arch/arc/soc/quark_se_c1000_ss/Kbuild index 93d860445ed..5ae78ce56c3 100644 --- a/arch/arc/soc/quark_se_c1000_ss/Kbuild +++ b/arch/arc/soc/quark_se_c1000_ss/Kbuild @@ -6,4 +6,4 @@ ccflags-$(CONFIG_ADC) +=-I$(srctree)/drivers/adc asflags-y := ${ccflags-y} -obj-y = soc.o soc_config.o power.o +obj-y = soc.o soc_config.o soc_power.o power.o diff --git a/arch/arc/soc/quark_se_c1000_ss/Kconfig.soc b/arch/arc/soc/quark_se_c1000_ss/Kconfig.soc index 75ba6fabaa6..15429a68df6 100644 --- a/arch/arc/soc/quark_se_c1000_ss/Kconfig.soc +++ b/arch/arc/soc/quark_se_c1000_ss/Kconfig.soc @@ -2,4 +2,5 @@ config SOC_QUARK_SE_C1000_SS bool "Intel Quark SE C1000- Sensor Sub System" select SYS_POWER_LOW_POWER_STATE_SUPPORTED + select SYS_POWER_DEEP_SLEEP_SUPPORTED select HAS_QMSI diff --git a/arch/arc/soc/quark_se_c1000_ss/power.c b/arch/arc/soc/quark_se_c1000_ss/power.c index 7ae4e0d0a8e..d3284862a2b 100644 --- a/arch/arc/soc/quark_se_c1000_ss/power.c +++ b/arch/arc/soc/quark_se_c1000_ss/power.c @@ -22,7 +22,30 @@ #include #include +#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); + +static void _deep_sleep(enum power_states state) +{ + 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: + _power_soc_deep_sleep(); + break; + default: + break; + } +} +#endif #define SLEEP_MODE_CORE_OFF (0x0) #define SLEEP_MODE_CORE_TIMERS_RTC_OFF (0x60) @@ -57,10 +80,12 @@ void _sys_soc_set_power_state(enum power_states state) case SYS_POWER_STATE_CPU_LPS_2: enter_arc_state(ARC_SS1); break; +#if (defined(CONFIG_SYS_POWER_DEEP_SLEEP)) case SYS_POWER_STATE_DEEP_SLEEP: case SYS_POWER_STATE_DEEP_SLEEP_1: - /* Sleep states are not yet supported for ARC. */ + _deep_sleep(state); break; +#endif default: break; } @@ -78,6 +103,10 @@ void _sys_soc_power_state_post_ops(enum power_states state) 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: + __builtin_arc_seti(0); + break; default: break; } diff --git a/arch/arc/soc/quark_se_c1000_ss/soc_power.S b/arch/arc/soc/quark_se_c1000_ss/soc_power.S new file mode 100644 index 00000000000..36c2d1f4b48 --- /dev/null +++ b/arch/arc/soc/quark_se_c1000_ss/soc_power.S @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _ASMLANGUAGE + +#include +#include +#include + +#ifdef CONFIG_SYS_POWER_DEEP_SLEEP +GDATA(_pm_arc_context) + +GTEXT(_sys_soc_resume_from_deep_sleep) +GTEXT(_power_restore_cpu_context) +GTEXT(_power_soc_sleep) +GTEXT(_power_soc_deep_sleep) + +#define GPS0_REGISTER 0xb0800100 +#define RESTORE_SS_BIT 2 + +SECTION_FUNC(TEXT, _sys_soc_resume_from_deep_sleep) + /* Check is this wakeup after sleep event. */ + ld r0,[GPS0_REGISTER] + bbit1 r0,RESTORE_SS_BIT,restore + j_s [blink] /* Jump to context of BLINK register. */ + +restore: + bclr_s r0,r0,RESTORE_SS_BIT + st r0,[GPS0_REGISTER] + + /* Enable I-Cache */ + sr 1, [_ARC_V2_IC_CTRL] + + j @_sys_soc_restore_cpu_context + +SECTION_FUNC(TEXT, save_cpu_context) + mov_s r1, _kernel + ld_s r2, [r1, _kernel_offset_to_current] + + _save_callee_saved_regs + + j_s [blink] /* Jump to context of BLINK register. */ + +SECTION_FUNC(TEXT, _power_soc_sleep) + /* + * Save the return address. + * The restore function will pop this and jump + * back to the caller. + */ + push_s blink + + /* Do not link to preserve blink */ + jl @save_cpu_context + j @power_soc_sleep + /* Does not return */ + +SECTION_FUNC(TEXT, _power_soc_deep_sleep) + /* + * Save the return address. + * The restore function will pop this and jump + * back to the caller. + */ + push_s blink + + /* Do not link to preserve blink */ + jl @save_cpu_context + j @power_soc_deep_sleep + /* Does not return */ + +SECTION_FUNC(TEXT, _sys_soc_restore_cpu_context) + mov_s r1, _kernel + ld_s r2, [r1, _kernel_offset_to_current] + + _load_callee_saved_regs + + /* Restore return address */ + pop_s blink + + j_s [blink] /* Jump to context of BLINK register. */ +#endif diff --git a/ext/hal/qmsi/Kbuild b/ext/hal/qmsi/Kbuild index 92c9d7f2725..abab9c7438f 100644 --- a/ext/hal/qmsi/Kbuild +++ b/ext/hal/qmsi/Kbuild @@ -1,6 +1,7 @@ obj-$(CONFIG_QMSI_BUILTIN) += drivers/flash/qm_flash.o -ifeq ($(CONFIG_ARC),y) +ifeq ($(CONFIG_SOC_QUARK_SE_C1000_SS),y) obj-$(CONFIG_QMSI_BUILTIN) += drivers/clk/ss_clk.o +obj-$(CONFIG_QMSI_BUILTIN) += soc/quark_se/drivers/vreg.o obj-$(CONFIG_QMSI_BUILTIN) += soc/quark_se/drivers/ss_power_states.o endif obj-$(CONFIG_QMSI_BUILTIN) += soc/$(patsubst %_ss,%,$(SOC_SERIES))/drivers/power_states.o @@ -25,4 +26,4 @@ obj-$(CONFIG_SPI_QMSI_SS) += drivers/spi/qm_ss_spi.o obj-$(CONFIG_GPIO_QMSI_SS) += drivers/gpio/qm_ss_gpio.o obj-$(CONFIG_I2C_QMSI_SS) += drivers/i2c/qm_ss_i2c.o obj-$(CONFIG_ADC_QMSI_SS) += drivers/adc/qm_ss_adc.o -obj-$(CONFIG_SOC_WATCH) += drivers/soc_watch.o \ No newline at end of file +obj-$(CONFIG_SOC_WATCH) += drivers/soc_watch.o diff --git a/tests/power/power_states/src/main.c b/tests/power/power_states/src/main.c index 5c411b85943..f5e5618972c 100644 --- a/tests/power/power_states/src/main.c +++ b/tests/power/power_states/src/main.c @@ -351,6 +351,7 @@ static void build_suspend_device_list(void) return; } +#if (CONFIG_X86) suspend_device_count = 3; for (i = 0; i < devcount; i++) { if (!strcmp(devices[i].config->name, "loapic")) { @@ -364,6 +365,18 @@ static void build_suspend_device_list(void) suspend_devices[suspend_device_count++] = &devices[i]; } } +#elif (CONFIG_ARC) + suspend_device_count = 2; + for (i = 0; i < devcount; i++) { + if (!strcmp(devices[i].config->name, "arc_v2_irq_unit")) { + suspend_devices[0] = &devices[i]; + } else if (!strcmp(devices[i].config->name, "sys_clock")) { + suspend_devices[1] = &devices[i]; + } else { + suspend_devices[suspend_device_count++] = &devices[i]; + } + } +#endif } void main(void)