Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * Copyright (c) 2017, Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the Intel Corporation nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __QM_SS_POWER_STATES_H__
#define __QM_SS_POWER_STATES_H__

#include "qm_common.h"
#include "qm_sensor_regs.h"

/**
 * SS Power mode control for Quark SE Microcontrollers.
 *
 * @defgroup groupSSPower SS Power states
 * @{
 */

/**
 * Sensor Subsystem SS1 Timers mode type.
 */
typedef enum {
	QM_SS_POWER_CPU_SS1_TIMER_OFF = 0, /**< Disable SS Timers in SS1. */
	QM_SS_POWER_CPU_SS1_TIMER_ON /**< Keep SS Timers enabled in SS1. */
} qm_ss_power_cpu_ss1_mode_t;

/**
 * Enable LPSS state entry.
 *
 * Put the SoC into LPSS on next C2/C2LP and SS2 state combination.<BR>
 * This function needs to be called on the Sensor Core to
 * Clock Gate ADC, I2C0, I2C1, SPI0 and SPI1 sensor peripherals.<BR>
 * Clock Gating sensor peripherals is a requirement to enter LPSS state.<BR>
 * After LPSS, qm_ss_power_soc_lpss_disable needs to be called to
 * restore clock gating.<BR>
 *
 * This needs to be called before any transition to C2/C2LP and SS2
 * in order to enter LPSS.<BR>
 * SoC Hybrid Clock is gated in this state.<BR>
 * Core Well Clocks are gated.<BR>
 * RTC is the only clock running.
 *
 * Possible SoC wake events are:
 * 	- Low Power Comparator Interrupt
 * 	- AON GPIO Interrupt
 * 	- AON Timer Interrupt
 * 	- RTC Interrupt
 */
void qm_ss_power_soc_lpss_enable(void);

#if (ENABLE_RESTORE_CONTEXT)
/**
 * Enter SoC sleep state and restore after wake up.
 *
 * Put the ARC core into sleep state until next SoC wake event
 * and continue execution after wake up where the application stopped.
 *
 * If the library is built with ENABLE_RESTORE_CONTEXT=1, then this function
 * will use the arc_restore_addr to save restore trap address which brings back
 * the ARC CPU to the point where this function was called.
 * This means that applications should refrain from using them.
 *
 * This function calls qm_ss_save_context and qm_ss_restore_context
 * in order to restore execution where it stopped.
 * All power management transitions are done by qm_power_soc_sleep().
 */
void qm_ss_power_soc_sleep_restore(void);
/**
 * Enter SoC sleep state and restore after wake up.
 *
 * Put the ARC core into sleep state until next SoC wake event
 * and continue execution after wake up where the application stopped.
 *
 * If the library is built with ENABLE_RESTORE_CONTEXT=1, then this function
 * will use the arc_restore_addr to save restore trap address which brings back
 * the ARC CPU to the point where this function was called.
 * This means that applications should refrain from using them.
 *
 * This function calls qm_ss_save_context and qm_ss_restore_context
 * in order to restore execution where it stopped.
 * All power management transitions are done by power_qm_soc_deep_sleep().
 */
void qm_ss_power_soc_deep_sleep_restore(void);

/**
 * Save context, enter ARC SS1 power save state and restore after wake up.
 *
 * This routine is same as qm_ss_power_soc_sleep_restore(), just instead of
 * going to sleep it will go to SS1 power save state.
 * Note: this function has a while(1) which will spin until we enter
 * (and exit) sleep and the power state change will be managed by the other
 * core.
 */
void qm_ss_power_sleep_wait(void);

/**
 * Enable the SENSOR startup restore flag.
 */
void qm_power_soc_set_ss_restore_flag(void);

#endif /* ENABLE_RESTORE_CONTEXT */

/**
 * Disable LPSS state entry.
 *
 * Clear LPSS enable flag.<BR>
 * Disable Clock Gating of ADC, I2C0, I2C1, SPI0 and SPI1 sensor
 * peripherals.<BR>
 * This will prevent entry in LPSS when cores are in C2/C2LP and SS2 states.
 */
void qm_ss_power_soc_lpss_disable(void);

/**
 * Enter Sensor SS1 state.
 *
 * Put the Sensor Subsystem into SS1.<BR>
 * Processor Clock is gated in this state.
 *
 * A wake event causes the Sensor Subsystem to transition to SS0.<BR>
 * A wake event is a sensor subsystem interrupt.
 *
 * According to the mode selected, Sensor Subsystem Timers can be disabled.
 *
 * @param[in] mode Mode selection for SS1 state.
 */
void qm_ss_power_cpu_ss1(const qm_ss_power_cpu_ss1_mode_t mode);

/**
 * Enter Sensor SS2 state or SoC LPSS state.
 *
 * Put the Sensor Subsystem into SS2.<BR>
 * Sensor Complex Clock is gated in this state.<BR>
 * Sensor Peripherals are gated in this state.<BR>
 *
 * This enables entry in LPSS if:
 *  - Sensor Subsystem is in SS2
 *  - Lakemont is in C2 or C2LP
 *  - LPSS entry is enabled
 *
 * A wake event causes the Sensor Subsystem to transition to SS0.<BR>
 * There are two kinds of wake event depending on the Sensor Subsystem
 * and SoC state:
 *  - SS2: a wake event is a Sensor Subsystem interrupt
 *  - LPSS: a wake event is a Sensor Subsystem interrupt or a Lakemont interrupt
 *
 * LPSS wake events apply if LPSS is entered.
 * If Host wakes the SoC from LPSS,
 * Sensor also transitions back to SS0.
 */
void qm_ss_power_cpu_ss2(void);

#if (ENABLE_RESTORE_CONTEXT) && (!UNIT_TEST)
/**
 * Save resume vector.
 *
 * Saves the resume vector in the global "arc_restore_addr" location.
 * The ARC will jump to the resume vector once a wake up event is
 * triggered and x86 resumes the ARC.
 */
#define qm_ss_set_resume_vector(_restore_label, arc_restore_addr)              \
	__asm__ __volatile__("mov r0, @arc_restore_addr\n\t"                   \
			     "st " #_restore_label ", [r0]\n\t"                \
			     : /* Output operands. */                          \
			     : /* Input operands. */                           \
			     : /* Clobbered registers list. */                 \
			     "r0")

/* Save execution context.
 *
 * This routine saves CPU registers onto cpu_context,
 * array.
 *
 */
#define qm_ss_save_context(cpu_context)                                        \
	__asm__ __volatile__("push_s r0\n\t"                                   \
			     "mov r0, @cpu_context\n\t"                        \
			     "st r1, [r0, 4]\n\t"                              \
			     "st r2, [r0, 8]\n\t"                              \
			     "st r3, [r0, 12]\n\t"                             \
			     "st r4, [r0, 16]\n\t"                             \
			     "st r5, [r0, 20]\n\t"                             \
			     "st r6, [r0, 24]\n\t"                             \
			     "st r7, [r0, 28]\n\t"                             \
			     "st r8, [r0, 32]\n\t"                             \
			     "st r9, [r0, 36]\n\t"                             \
			     "st r10, [r0, 40]\n\t"                            \
			     "st r11, [r0, 44]\n\t"                            \
			     "st r12, [r0, 48]\n\t"                            \
			     "st r13, [r0, 52]\n\t"                            \
			     "st r14, [r0, 56]\n\t"                            \
			     "st r15, [r0, 60]\n\t"                            \
			     "st r16, [r0, 64]\n\t"                            \
			     "st r17, [r0, 68]\n\t"                            \
			     "st r18, [r0, 72]\n\t"                            \
			     "st r19, [r0, 76]\n\t"                            \
			     "st r20, [r0, 80]\n\t"                            \
			     "st r21, [r0, 84]\n\t"                            \
			     "st r22, [r0, 88]\n\t"                            \
			     "st r23, [r0, 92]\n\t"                            \
			     "st r24, [r0, 96]\n\t"                            \
			     "st r25, [r0, 100]\n\t"                           \
			     "st r26, [r0, 104]\n\t"                           \
			     "st r27, [r0, 108]\n\t"                           \
			     "st r28, [r0, 112]\n\t"                           \
			     "st r29, [r0, 116]\n\t"                           \
			     "st r30, [r0, 120]\n\t"                           \
			     "st r31, [r0, 124]\n\t"                           \
			     "lr r31, [ic_ctrl]\n\t"                           \
			     "st r31, [r0, 128]\n\t"                           \
			     : /* Output operands. */                          \
			     : /* Input operands. */                           \
			     [ic_ctrl] "i"(QM_SS_AUX_IC_CTRL)                  \
			     : /* Clobbered registers list. */                 \
			     "r0")

/* Restore execution context.
 *
 * This routine restores CPU registers from cpu_context,
 * array.
 *
 * This routine is called from the bootloader to restore the execution context
 * from before entering in sleep mode.
 */
#define qm_ss_restore_context(_restore_label, cpu_context)                     \
	__asm__ __volatile__(                                                  \
	    #_restore_label                                                    \
	    ":\n\t"                                                            \
	    "mov r0, @cpu_context\n\t"                                         \
	    "ld r1, [r0, 4]\n\t"                                               \
	    "ld r2, [r0, 8]\n\t"                                               \
	    "ld r3, [r0, 12]\n\t"                                              \
	    "ld r4, [r0, 16]\n\t"                                              \
	    "ld r5, [r0, 20]\n\t"                                              \
	    "ld r6, [r0, 24]\n\t"                                              \
	    "ld r7, [r0, 28]\n\t"                                              \
	    "ld r8, [r0, 32]\n\t"                                              \
	    "ld r9, [r0, 36]\n\t"                                              \
	    "ld r10, [r0, 40]\n\t"                                             \
	    "ld r11, [r0, 44]\n\t"                                             \
	    "ld r12, [r0, 48]\n\t"                                             \
	    "ld r13, [r0, 52]\n\t"                                             \
	    "ld r14, [r0, 56]\n\t"                                             \
	    "ld r15, [r0, 60]\n\t"                                             \
	    "ld r16, [r0, 64]\n\t"                                             \
	    "ld r17, [r0, 68]\n\t"                                             \
	    "ld r18, [r0, 72]\n\t"                                             \
	    "ld r19, [r0, 76]\n\t"                                             \
	    "ld r20, [r0, 80]\n\t"                                             \
	    "ld r21, [r0, 84]\n\t"                                             \
	    "ld r22, [r0, 88]\n\t"                                             \
	    "ld r23, [r0, 92]\n\t"                                             \
	    "ld r24, [r0, 96]\n\t"                                             \
	    "ld r25, [r0, 100]\n\t"                                            \
	    "ld r26, [r0, 104]\n\t"                                            \
	    "ld r27, [r0, 108]\n\t"                                            \
	    "ld r28, [r0, 112]\n\t"                                            \
	    "ld r29, [r0, 116]\n\t"                                            \
	    "ld r30, [r0, 120]\n\t"                                            \
	    "ld r31, [r0, 124]\n\t"                                            \
	    "ld r0, [r0, 128]\n\t"                                             \
	    "sr r0, [ic_ctrl]\n\t"                                             \
	    "pop_s r0\n\t"                                                     \
	    "sr 0,[0x101]\n\t" /* Setup Sensor Subsystem TimeStamp Counter */  \
	    "sr 0,[0x100]\n\t"                                                 \
	    "sr -1,[0x102]\n\t"                                                \
	    : /* Output operands. */                                           \
	    : /* Input operands. */                                            \
	    [ic_ctrl] "i"(QM_SS_AUX_IC_CTRL)                                   \
	    : /* Clobbered registers list. */                                  \
	    "r0")
#else
#define qm_ss_set_resume_vector(_restore_label, arc_restore_addr)
#define qm_ss_save_context(cpu_context)
#define qm_ss_restore_context(_restore_label, cpu_context)
#endif

/**
 * @}
 */

#endif /* __QM_SS_POWER_STATES_H__ */