1
0
mirror of https://github.com/arduino-libraries/ArduinoLowPower.git synced 2025-04-19 11:42:14 +03:00

Initial ARC32 implementation

The includes and relevant (non wrapper) functions are borrowed from Zephyr 1.5.0

The implementation is still broken:
- an RTC driver is still missing, so no timed wakeup possible
- only the AON pins configured as LEVEL can wakeup the processor
  on Arduino101, the only AON broken out is RESET button
  Changing the main loop in CODK-A allows operating the button without triggering a reboot. However, the board doesn't wakeup from deep sleep (am I missing something maybe?)
This commit is contained in:
Martino Facchin 2016-11-11 16:20:30 +01:00
parent 63b24bed79
commit e99fcefe8b
5 changed files with 1447 additions and 0 deletions

View File

@ -7,6 +7,13 @@
#error The library is not compatible with AVR boards
#endif
#ifdef ARDUINO_ARCH_ARC32
#include "include/arc32/power_states.h"
#include "include/arc32/ss_power_states.h"
#include "include/arc32/qm_sensor_regs.h"
#include "include/arc32/qm_soc_regs.h"
#endif
#ifdef ARDUINO_ARCH_SAMD
#include "RTCZero.h"
#endif
@ -32,6 +39,23 @@ class ArduinoLowPowerClass {
RTCZero rtc;
#define RTC_ALARM_WAKEUP 0xFF
#endif
#ifdef ARDUINO_ARCH_ARC32
void ss_power_soc_lpss_enable();
void ss_power_soc_lpss_disable();
void ss_power_cpu_ss1(const ss_power_cpu_ss1_mode_t mode);
void ss_power_cpu_ss2();
void ss_power_soc_sleep_restore();
void ss_power_soc_deep_sleep_restore();
void ss_power_sleep_wait();
void power_soc_set_ss_restore_flag();
void power_soc_sleep();
void power_soc_deep_sleep();
void setAlarmIn(uint32_t millis);
#define RTC_ALARM_WAKEUP 0xFF
#define RESET_BUTTON_WAKEUP 0xFE
#endif
};
extern ArduinoLowPowerClass LowPower;

View File

@ -0,0 +1,366 @@
/*
* Copyright (c) 2016, 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.
*/
#include "ArduinoLowPower.h"
#ifdef ARDUINO_ARCH_ARC32
#include "WInterrupts.h"
/* Sensor Subsystem sleep operand definition.
* Only a subset applies as internal sensor RTC
* is not available.
*
* OP | Core | Timers | RTC
* 000 | 0 | 1 | 1 <-- used for SS1
* 001 | 0 | 0 | 1
* 010 | 0 | 1 | 0
* 011 | 0 | 0 | 0 <-- used for SS2
* 100 | 0 | 0 | 0
* 101 | 0 | 0 | 0
* 110 | 0 | 0 | 0
* 111 | 0 | 0 | 0
*
* sleep opcode argument:
* - [7:5] : Sleep Operand
* - [4] : Interrupt enable
* - [3:0] : Interrupt threshold value
*/
#define QM_SS_SLEEP_MODE_CORE_OFF (0x0)
#define QM_SS_SLEEP_MODE_CORE_OFF_TIMER_OFF (0x20)
#define QM_SS_SLEEP_MODE_CORE_TIMERS_RTC_OFF (0x60)
void ArduinoLowPowerClass::power_soc_sleep()
{
/* Go to sleep */
QM_SCSS_PMU->slp_cfg &= ~QM_SCSS_SLP_CFG_LPMODE_EN;
QM_SCSS_PMU->pm1c |= QM_SCSS_PM1C_SLPEN;
}
void ArduinoLowPowerClass::power_soc_deep_sleep()
{
/* Switch to linear regulators.
* For low power deep sleep mode, it is a requirement that the platform
* voltage regulators are not in switching mode.
*/
/*
vreg_plat1p8_set_mode(VREG_MODE_LINEAR);
vreg_plat3p3_set_mode(VREG_MODE_LINEAR);
*/
/* Enable low power sleep mode */
QM_SCSS_PMU->slp_cfg |= QM_SCSS_SLP_CFG_LPMODE_EN;
QM_SCSS_PMU->pm1c |= QM_SCSS_PM1C_SLPEN;
}
void ArduinoLowPowerClass::ss_power_soc_lpss_enable()
{
uint32_t creg_mst0_ctrl = 0;
creg_mst0_ctrl = __builtin_arc_lr(QM_SS_CREG_BASE);
/*
* Clock gate the sensor peripherals at CREG level.
* This clock gating is independent of the peripheral-specific clock
* gating provided in ss_clk.h .
*/
creg_mst0_ctrl |= (QM_SS_IO_CREG_MST0_CTRL_ADC_CLK_GATE |
QM_SS_IO_CREG_MST0_CTRL_I2C1_CLK_GATE |
QM_SS_IO_CREG_MST0_CTRL_I2C0_CLK_GATE |
QM_SS_IO_CREG_MST0_CTRL_SPI1_CLK_GATE |
QM_SS_IO_CREG_MST0_CTRL_SPI0_CLK_GATE);
__builtin_arc_sr(creg_mst0_ctrl, QM_SS_CREG_BASE);
QM_SCSS_CCU->ccu_lp_clk_ctl |= QM_SCSS_CCU_SS_LPS_EN;
}
void ArduinoLowPowerClass::ss_power_soc_lpss_disable()
{
uint32_t creg_mst0_ctrl = 0;
creg_mst0_ctrl = __builtin_arc_lr(QM_SS_CREG_BASE);
/*
* Restore clock gate of the sensor peripherals at CREG level.
* CREG is not used anywhere else so we can safely restore
* the configuration to its POR default.
*/
creg_mst0_ctrl &= ~(QM_SS_IO_CREG_MST0_CTRL_ADC_CLK_GATE |
QM_SS_IO_CREG_MST0_CTRL_I2C1_CLK_GATE |
QM_SS_IO_CREG_MST0_CTRL_I2C0_CLK_GATE |
QM_SS_IO_CREG_MST0_CTRL_SPI1_CLK_GATE |
QM_SS_IO_CREG_MST0_CTRL_SPI0_CLK_GATE);
__builtin_arc_sr(creg_mst0_ctrl, QM_SS_CREG_BASE);
QM_SCSS_CCU->ccu_lp_clk_ctl &= ~QM_SCSS_CCU_SS_LPS_EN;
}
/* Enter SS1 :
* SLEEP + sleep operand
* __builtin_arc_sleep is not used here as it does not propagate sleep operand.
*/
void ArduinoLowPowerClass::ss_power_cpu_ss1(const ss_power_cpu_ss1_mode_t mode)
{
/* The sensor cannot be woken up with an edge triggered
* interrupt from the RTC and the AON Counter.
* Switch to Level triggered interrupts and restore
* the setting when waking up.
*/
__builtin_arc_sr(IRQ_RTC_INTR, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_LEVEL_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
__builtin_arc_sr(QM_IRQ_AONPT_0_INT_VECTOR, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_LEVEL_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
/* Enter SS1 */
switch (mode) {
case SS_POWER_CPU_SS1_TIMER_OFF:
__asm__ __volatile__(
"sleep %0"
:
: "i"(QM_SS_SLEEP_MODE_CORE_OFF_TIMER_OFF));
break;
case SS_POWER_CPU_SS1_TIMER_ON:
default:
__asm__ __volatile__("sleep %0"
:
: "i"(QM_SS_SLEEP_MODE_CORE_OFF));
break;
}
/* Restore the RTC and AONC to edge interrupt after when waking up. */
__builtin_arc_sr(QM_IRQ_RTC_0_INT_VECTOR, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_EDGE_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
__builtin_arc_sr(QM_IRQ_AONPT_0_INT_VECTOR, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_EDGE_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
}
/* Enter SS2 :
* SLEEP + sleep operand
* __builtin_arc_sleep is not used here as it does not propagate sleep operand.
*/
void ArduinoLowPowerClass::ss_power_cpu_ss2(void)
{
/* The sensor cannot be woken up with an edge triggered
* interrupt from the RTC and the AON Counter.
* Switch to Level triggered interrupts and restore
* the setting when waking up.
*/
__builtin_arc_sr(QM_IRQ_RTC_0_INT_VECTOR, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_LEVEL_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
__builtin_arc_sr(QM_IRQ_AONPT_0_INT_VECTOR, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_LEVEL_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
/* Enter SS2 */
__asm__ __volatile__("sleep %0"
:
: "i"(QM_SS_SLEEP_MODE_CORE_TIMERS_RTC_OFF));
/* Restore the RTC and AONC to edge interrupt after when waking up. */
__builtin_arc_sr(QM_IRQ_RTC_0_INT_VECTOR, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_EDGE_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
__builtin_arc_sr(QM_IRQ_AONPT_0_INT_VECTOR, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_EDGE_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
}
/* FIXME: use a .global symbol in linker for arc_restore_addr */
uint32_t arc_restore_addr;
uint32_t cpu_context[33];
void ArduinoLowPowerClass::ss_power_soc_sleep_restore(void)
{
/*
* Save sensor restore trap address.
* The first parameter in this macro represents the label defined in
* the qm_ss_restore_context() macro, which is actually the restore
* trap address.
*/
qm_ss_set_resume_vector(sleep_restore_trap, arc_restore_addr);
/* Save ARC execution context. */
qm_ss_save_context(cpu_context);
/* Set restore flags. */
power_soc_set_ss_restore_flag();
/* Enter sleep. */
power_soc_sleep();
/*
* Restore sensor execution context.
* The sensor startup code will jump to this location after waking up
* from sleep. The restore trap address is the label defined in the
* macro and the label is exposed here through the first parameter.
*/
qm_ss_restore_context(sleep_restore_trap, cpu_context);
}
void ArduinoLowPowerClass::ss_power_soc_deep_sleep_restore(void)
{
/*
* Save sensor restore trap address.
* The first parameter in this macro represents the label defined in
* the qm_ss_restore_context() macro, which is actually the restore
* trap address.
*/
qm_ss_set_resume_vector(deep_sleep_restore_trap, arc_restore_addr);
/* Save ARC execution context. */
qm_ss_save_context(cpu_context);
/* Set restore flags. */
power_soc_set_ss_restore_flag();
/* Enter sleep. */
power_soc_deep_sleep();
/*
* Restore sensor execution context.
* The sensor startup code will jump to this location after waking up
* from sleep. The restore trap address is the label defined in the
* macro and the label is exposed here through the first parameter.
*/
qm_ss_restore_context(deep_sleep_restore_trap, cpu_context);
}
void ArduinoLowPowerClass::ss_power_sleep_wait(void)
{
/*
* Save sensor restore trap address.
* The first parameter in this macro represents the label defined in
* the qm_ss_restore_context() macro, which is actually the restore
* trap address.
*/
qm_ss_set_resume_vector(sleep_restore_trap, arc_restore_addr);
/* Save ARC execution context. */
qm_ss_save_context(cpu_context);
/* Set restore flags. */
power_soc_set_ss_restore_flag();
/* Enter SS1 and stay in it until sleep and wake-up. */
while (1) {
ss_power_cpu_ss1(SS_POWER_CPU_SS1_TIMER_ON);
}
/*
* Restore sensor execution context.
* The sensor startup code will jump to this location after waking up
* from sleep. The restore trap address is the label defined in the
* macro and the label is exposed here through the first parameter.
*/
qm_ss_restore_context(sleep_restore_trap, cpu_context);
}
void ArduinoLowPowerClass::power_soc_set_ss_restore_flag(void)
{
QM_SCSS_GP->gps0 |= BIT(QM_GPS0_BIT_SENSOR_WAKEUP);
}
void ArduinoLowPowerClass::idle() {
ss_power_cpu_ss1(SS_POWER_CPU_SS1_TIMER_ON);
}
void ArduinoLowPowerClass::idle(uint32_t millis) {
setAlarmIn(millis);
idle();
}
void ArduinoLowPowerClass::sleep() {
ss_power_soc_lpss_enable();
//ss_power_cpu_ss2();
power_soc_deep_sleep();
ss_power_soc_lpss_disable();
}
void ArduinoLowPowerClass::sleep(uint32_t millis) {
setAlarmIn(millis);
sleep();
}
void ArduinoLowPowerClass::deepSleep() {
sleep();
}
void ArduinoLowPowerClass::deepSleep(uint32_t millis) {
sleep(millis);
}
void ArduinoLowPowerClass::setAlarmIn(uint32_t millis) {
//if (!rtc.isConfigured()) {
// attachInterruptWakeup(RTC_ALARM_WAKEUP, NULL, 0);
//}
//uint32_t now = rtc.getEpoch();
//rtc.setAlarmEpoch(now + millis/1000);
//rtc.enableAlarm(rtc.MATCH_HHMMSS);
}
void ArduinoLowPowerClass::attachInterruptWakeup(uint32_t pin, voidFuncPtr callback, uint32_t mode) {
extern uint32_t sizeof_g_APinDescription;
if (pin > sizeof_g_APinDescription) {
// check for external wakeup sources
// RTC library should call this API to enable the alarm subsystem
switch (pin) {
case RTC_ALARM_WAKEUP:
//rtc.begin();
//rtc.attachInterrupt(callback);
case RESET_BUTTON_WAKEUP:
gpio_cfg_data_t pin_cfg = {
.gpio_type = GPIO_INTERRUPT,
.int_type = LEVEL,
.int_polarity = ACTIVE_LOW,
.int_debounce = DEBOUNCE_OFF,
.int_ls_sync = LS_SYNC_OFF,
.gpio_cb = callback
};
soc_gpio_deconfig(SOC_GPIO_AON, 0);
/* set RESET GPIO button to be an input */
soc_gpio_set_config(SOC_GPIO_AON, 0, &pin_cfg);
}
return;
}
//pinMode(pin, INPUT_PULLUP);
//attachInterrupt(pin, callback, mode);
}
ArduinoLowPowerClass LowPower;
#endif

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2016, 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 __POWER_STATES_H__
#define __POWER_STATES_H__
/**
* SoC Power mode control for Quark SE Microcontrollers.
*
* Available SoC states are:
* - Low Power Sensing Standby (LPSS)
* - Sleep
*
* LPSS can only be enabled from the Sensor core,
* refer to @ref ss_power_soc_lpss_enable for further details.
*
* @defgroup groupSoCPower Quark SE SoC Power states
* @{
*/
/**
* Enter SoC sleep state.
*
* Put the SoC into sleep state until next SoC wake event.
*
* - Core well is turned off
* - Always on well is on
* - Hybrid Clock is off
* - RTC Clock is on
*
* Possible SoC wake events are:
* - Low Power Comparator Interrupt
* - AON GPIO Interrupt
* - AON Timer Interrupt
* - RTC Interrupt
*/
void power_soc_sleep(void);
/**
* Enter SoC deep sleep state.
*
* Put the SoC into deep sleep state until next SoC wake event.
*
* - Core well is turned off
* - Always on well is on
* - Hybrid Clock is off
* - RTC Clock is on
*
* Possible SoC wake events are:
* - Low Power Comparator Interrupt
* - AON GPIO Interrupt
* - AON Timer Interrupt
* - RTC Interrupt
*
* This function puts 1P8V regulators and 3P3V into Linear Mode.
*/
void power_soc_deep_sleep(void);
/**
* @}
*/
#endif /* __POWER_STATES_H__ */

View File

@ -0,0 +1,673 @@
/*
* Copyright (c) 2016, 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 __SENSOR_REGISTERS_H__
#define __SENSOR_REGISTERS_H__
/**
* Quark SE SoC Sensor Subsystem Registers.
*
* For detailed description please read the SOC datasheet.
*
* @defgroup groupSSSEREG SoC Registers (Sensor Subsystem)
* @{
*/
#define BIT(x) (1U << (x))
/* Bitwise OR operation macro for registers in the auxiliary memory space. */
#define QM_SS_REG_AUX_OR(reg, mask) \
(__builtin_arc_sr(__builtin_arc_lr(reg) | (mask), reg))
/* Bitwise NAND operation macro for registers in the auxiliary memory space. */
#define QM_SS_REG_AUX_NAND(reg, mask) \
(__builtin_arc_sr(__builtin_arc_lr(reg) & (~(mask)), reg))
/* Sensor Subsystem status32 register. */
#define QM_SS_AUX_STATUS32 (0xA)
/** Interrupt priority threshold. */
#define QM_SS_STATUS32_E_MASK (0x1E)
/** Interrupt enable. */
#define QM_SS_STATUS32_IE_MASK BIT(31)
/* Sensor Subsystem control register. */
#define QM_SS_AUX_IC_CTRL (0x11)
/* Sensor Subsystem cache invalidate register. */
#define QM_SS_AUX_IC_IVIL (0x19)
/* Sensor Subsystem vector base register. */
#define QM_SS_AUX_INT_VECTOR_BASE (0x25)
/**
* @name SS Interrupt
* @{
*/
#define QM_SS_EXCEPTION_NUM (16) /* Exceptions and traps in ARC EM core. */
#define QM_SS_INT_TIMER_NUM (2) /* Internal interrupts in ARC EM core. */
#define QM_SS_IRQ_SENSOR_NUM (18) /* IRQ's from the Sensor Subsystem. */
#define QM_SS_IRQ_COMMON_NUM (32) /* IRQ's from the common SoC fabric. */
#define QM_SS_INT_VECTOR_NUM \
(QM_SS_EXCEPTION_NUM + QM_SS_INT_TIMER_NUM + QM_SS_IRQ_SENSOR_NUM + \
QM_SS_IRQ_COMMON_NUM)
#define QM_SS_IRQ_NUM (QM_SS_IRQ_SENSOR_NUM + QM_SS_IRQ_COMMON_NUM)
/**
* SS IRQ context type.
*
* Applications should not modify the content.
* This structure is only intended to be used by
* qm_irq_save_context and qm_irq_restore_context functions.
*/
typedef struct {
uint32_t status32_irq_threshold; /**< STATUS32 Interrupt Threshold. */
uint32_t status32_irq_enable; /**< STATUS32 Interrupt Enable. */
uint32_t irq_ctrl; /**< Interrupt Context Saving Control Register. */
/**
* IRQ configuration:
* - IRQ Priority:BIT(6):BIT(2)
* - IRQ Trigger:BIT(1)
* - IRQ Enable:BIT(0)
*/
uint8_t irq_config[QM_SS_INT_VECTOR_NUM - 1];
} qm_irq_context_t;
/** General Purpose register map. */
typedef struct {
volatile uint32_t gps0; /**< General Purpose Sticky Register 0 */
volatile uint32_t gps1; /**< General Purpose Sticky Register 1 */
volatile uint32_t gps2; /**< General Purpose Sticky Register 2 */
volatile uint32_t gps3; /**< General Purpose Sticky Register 3 */
volatile uint32_t reserved;
volatile uint32_t gp0; /**< General Purpose Scratchpad Register 0 */
volatile uint32_t gp1; /**< General Purpose Scratchpad Register 1 */
volatile uint32_t gp2; /**< General Purpose Scratchpad Register 2 */
volatile uint32_t gp3; /**< General Purpose Scratchpad Register 3 */
volatile uint32_t reserved1;
volatile uint32_t id; /**< Identification Register */
volatile uint32_t rev; /**< Revision Register */
volatile uint32_t wo_sp; /**< Write-One-to-Set Scratchpad Register */
volatile uint32_t
wo_st; /**< Write-One-to-Set Sticky Scratchpad Register */
} qm_scss_gp_reg_t;
#define QM_SCSS_GP_BASE (0xB0800100)
#define QM_SCSS_GP ((qm_scss_gp_reg_t *)QM_SCSS_GP_BASE)
/* The GPS0 register usage. */
#define QM_GPS0_BIT_FM (0) /**< Start Firmware Manager. */
#define QM_GPS0_BIT_X86_WAKEUP (1) /**< Lakemont core reset type. */
#define QM_GPS0_BIT_SENSOR_WAKEUP (2) /**< Sensor core reset type. */
/** System Core register map. */
typedef struct {
volatile uint32_t osc0_cfg0; /**< Hybrid Oscillator Configuration 0. */
volatile uint32_t osc0_stat1; /**< Hybrid Oscillator status 1. */
volatile uint32_t osc0_cfg1; /**< Hybrid Oscillator configuration 1. */
volatile uint32_t osc1_stat0; /**< RTC Oscillator status 0. */
volatile uint32_t osc1_cfg0; /**< RTC Oscillator Configuration 0. */
volatile uint32_t usb_pll_cfg0; /**< USB Phase lock look configuration. */
volatile uint32_t
ccu_periph_clk_gate_ctl; /**< Peripheral Clock Gate Control. */
volatile uint32_t
ccu_periph_clk_div_ctl0; /**< Peripheral Clock Divider Control. 0 */
volatile uint32_t
ccu_gpio_db_clk_ctl; /**< Peripheral Clock Divider Control 1. */
volatile uint32_t
ccu_ext_clock_ctl; /**< External Clock Control Register. */
/** Sensor Subsystem peripheral clock gate control. */
volatile uint32_t ccu_ss_periph_clk_gate_ctl;
volatile uint32_t ccu_lp_clk_ctl; /**< System Low Power Clock Control. */
volatile uint32_t reserved;
volatile uint32_t ccu_mlayer_ahb_ctl; /**< AHB Control Register. */
volatile uint32_t ccu_sys_clk_ctl; /**< System Clock Control Register. */
volatile uint32_t osc_lock_0; /**< Clocks Lock Register. */
} qm_scss_ccu_reg_t;
#define QM_SCSS_CCU ((qm_scss_ccu_reg_t *)SCSS_REGISTER_BASE)
/** Power Management register map. */
typedef struct {
volatile uint32_t p_lvl2; /**< Processor level 2 */
volatile uint32_t reserved[4];
volatile uint32_t pm1c; /**< Power management 1 control */
volatile uint32_t reserved1[9];
volatile uint32_t aon_vr; /**< AON Voltage Regulator */
volatile uint32_t plat3p3_vr; /**< Platform 3p3 voltage regulator */
volatile uint32_t plat1p8_vr; /**< Platform 1p8 voltage regulator */
volatile uint32_t host_vr; /**< Host Voltage Regulator */
volatile uint32_t slp_cfg; /**< Sleeping Configuration */
/** Power Management Network (PMNet) Control and Status */
volatile uint32_t pmnetcs;
volatile uint32_t pm_wait; /**< Power Management Wait */
volatile uint32_t reserved2;
volatile uint32_t p_sts; /**< Processor Status */
volatile uint32_t reserved3[3];
volatile uint32_t rstc; /**< Reset Control */
volatile uint32_t rsts; /**< Reset Status */
volatile uint32_t reserved4[6];
volatile uint32_t vr_lock; /**< Voltage regulator lock */
volatile uint32_t pm_lock; /**< Power Management Lock */
} qm_scss_pmu_reg_t;
#define QM_SCSS_PMU_BASE (0xB0800504)
#define QM_SCSS_PMU ((qm_scss_pmu_reg_t *)QM_SCSS_PMU_BASE)
#define QM_SS_CFG_ARC_RUN_REQ_A BIT(24)
#define QM_P_STS_HALT_INTERRUPT_REDIRECTION BIT(26)
#define QM_P_STS_ARC_HALT BIT(14)
#define QM_AON_VR_VSEL_MASK (0xFFE0)
#define QM_AON_VR_VSEL_1V2 (0x8)
#define QM_AON_VR_VSEL_1V35 (0xB)
#define QM_AON_VR_VSEL_1V8 (0x10)
#define QM_AON_VR_EN BIT(7)
#define QM_AON_VR_VSTRB BIT(5)
#define QM_SCSS_SLP_CFG_LPMODE_EN BIT(8)
#define QM_SCSS_SLP_CFG_RTC_DIS BIT(7)
#define QM_SCSS_PM1C_SLPEN BIT(13)
#define QM_SCSS_HOST_VR_EN BIT(7)
#define QM_SCSS_PLAT3P3_VR_EN BIT(7)
#define QM_SCSS_PLAT1P8_VR_EN BIT(7)
#define QM_SCSS_HOST_VR_VREG_SEL BIT(6)
#define QM_SCSS_PLAT3P3_VR_VREG_SEL BIT(6)
#define QM_SCSS_PLAT1P8_VR_VREG_SEL BIT(6)
#define QM_SCSS_VR_ROK BIT(10)
#define QM_SCSS_VR_EN BIT(7)
#define QM_SCSS_VR_VREG_SEL BIT(6)
#define QM_SCSS_CCU_SS_LPS_EN BIT(0)
typedef enum {
QM_SS_IRQ_LEVEL_SENSITIVE = 0,
QM_SS_IRQ_EDGE_SENSITIVE = 1
} qm_ss_irq_trigger_t;
#define QM_SS_AUX_IRQ_CTRL (0xE)
#define QM_SS_AUX_IRQ_HINT (0x201)
#define QM_SS_AUX_IRQ_PRIORITY (0x206)
#define QM_SS_AUX_IRQ_STATUS (0x406)
#define QM_SS_AUX_IRQ_SELECT (0x40B)
#define QM_SS_AUX_IRQ_ENABLE (0x40C)
#define QM_SS_AUX_IRQ_TRIGGER (0x40D)
/** Always-On Timer Interrupt. */
#define QM_IRQ_AONPT_0_INT 28
#define QM_IRQ_AONPT_0_INT_MASK_OFFSET 32
#define QM_IRQ_AONPT_0_INT_VECTOR 64
/** RTC Single Interrupt. */
#define QM_IRQ_RTC_0_INT 11
#define QM_IRQ_RTC_0_INT_MASK_OFFSET 12
#define QM_IRQ_RTC_0_INT_VECTOR 47
/** @} */
/**
* @name SS Timer
* @{
*/
typedef enum {
QM_SS_TIMER_COUNT = 0,
QM_SS_TIMER_CONTROL,
QM_SS_TIMER_LIMIT
} qm_ss_timer_reg_t;
/**
* Sensor Subsystem Timers.
*/
typedef enum { QM_SS_TIMER_0 = 0, QM_SS_TIMER_NUM } qm_ss_timer_t;
/*
* SS TIMER context type.
*
* Application should not modify the content.
* This structure is only intended to be used by the qm_ss_timer_save_context
* and qm_ss_timer_restore_context functions.
*/
typedef struct {
uint32_t timer_count; /**< Timer count. */
uint32_t timer_control; /**< Timer control. */
uint32_t timer_limit; /**< Timer limit. */
} qm_ss_timer_context_t;
#define QM_SS_TIMER_0_BASE (0x21)
#define QM_SS_TIMER_1_BASE (0x100)
#define QM_SS_TSC_BASE QM_SS_TIMER_1_BASE
#define QM_SS_TIMER_CONTROL_INT_EN_OFFSET (0)
#define QM_SS_TIMER_CONTROL_NON_HALTED_OFFSET (1)
#define QM_SS_TIMER_CONTROL_WATCHDOG_OFFSET (2)
#define QM_SS_TIMER_CONTROL_INT_PENDING_OFFSET (3)
/** @} */
/**
* GPIO registers and definitions.
*
* @name SS GPIO
* @{
*/
/** Sensor Subsystem GPIO register block type. */
typedef enum {
QM_SS_GPIO_SWPORTA_DR = 0,
QM_SS_GPIO_SWPORTA_DDR,
QM_SS_GPIO_INTEN = 3,
QM_SS_GPIO_INTMASK,
QM_SS_GPIO_INTTYPE_LEVEL,
QM_SS_GPIO_INT_POLARITY,
QM_SS_GPIO_INTSTATUS,
QM_SS_GPIO_DEBOUNCE,
QM_SS_GPIO_PORTA_EOI,
QM_SS_GPIO_EXT_PORTA,
QM_SS_GPIO_LS_SYNC
} qm_ss_gpio_reg_t;
/**
* SS GPIO context type.
*
* Application should not modify the content.
* This structure is only intended to be used by the qm_ss_gpio_save_context and
* qm_ss_gpio_restore_context functions.
*/
typedef struct {
uint32_t gpio_swporta_dr; /**< Port A Data. */
uint32_t gpio_swporta_ddr; /**< Port A Data Direction. */
uint32_t gpio_inten; /**< Interrupt Enable. */
uint32_t gpio_intmask; /**< Interrupt Mask. */
uint32_t gpio_inttype_level; /**< Interrupt Type. */
uint32_t gpio_int_polarity; /**< Interrupt Polarity. */
uint32_t gpio_debounce; /**< Debounce Enable. */
uint32_t gpio_ls_sync; /**< Synchronization Level. */
} qm_ss_gpio_context_t;
#define QM_SS_GPIO_NUM_PINS (16)
#define QM_SS_GPIO_LS_SYNC_CLK_EN BIT(31)
#define QM_SS_GPIO_LS_SYNC_SYNC_LVL BIT(0)
/** Sensor Subsystem GPIO. */
typedef enum { QM_SS_GPIO_0 = 0, QM_SS_GPIO_1, QM_SS_GPIO_NUM } qm_ss_gpio_t;
#define QM_SS_GPIO_0_BASE (0x80017800)
#define QM_SS_GPIO_1_BASE (0x80017900)
/** @} */
/**
* I2C registers and definitions.
*
* @name SS I2C
* @{
*/
/** Sensor Subsystem I2C register block type. */
typedef enum {
QM_SS_I2C_CON = 0,
QM_SS_I2C_DATA_CMD,
QM_SS_I2C_SS_SCL_CNT,
QM_SS_I2C_FS_SCL_CNT = 0x04,
QM_SS_I2C_INTR_STAT = 0x06,
QM_SS_I2C_INTR_MASK,
QM_SS_I2C_TL,
QM_SS_I2C_INTR_CLR = 0x0A,
QM_SS_I2C_STATUS,
QM_SS_I2C_TXFLR,
QM_SS_I2C_RXFLR,
QM_SS_I2C_SDA_CONFIG,
QM_SS_I2C_TX_ABRT_SOURCE,
QM_SS_I2C_ENABLE_STATUS = 0x11
} qm_ss_i2c_reg_t;
/**
* SS I2C context type.
*
* Application should not modify the content.
* This structure is only intended to be used by the qm_ss_gpio_save_context and
* qm_ss_gpio_restore_context functions.
*/
typedef struct {
uint32_t i2c_con;
uint32_t i2c_ss_scl_cnt;
uint32_t i2c_fs_scl_cnt;
} qm_ss_i2c_context_t;
#define QM_SS_I2C_CON_ENABLE BIT(0)
#define QM_SS_I2C_CON_ABORT BIT(1)
#define QM_SS_I2C_CON_SPEED_SS BIT(3)
#define QM_SS_I2C_CON_SPEED_FS BIT(4)
#define QM_SS_I2C_CON_SPEED_MASK (0x18)
#define QM_SS_I2C_CON_IC_10BITADDR BIT(5)
#define QM_SS_I2C_CON_IC_10BITADDR_OFFSET (5)
#define QM_SS_I2C_CON_IC_10BITADDR_MASK (5)
#define QM_SS_I2C_CON_RESTART_EN BIT(7)
#define QM_SS_I2C_CON_TAR_SAR_OFFSET (9)
#define QM_SS_I2C_CON_TAR_SAR_MASK (0x7FE00)
#define QM_SS_I2C_CON_TAR_SAR_10_BIT_MASK (0x3FF)
#define QM_SS_I2C_CON_SPKLEN_OFFSET (22)
#define QM_SS_I2C_CON_SPKLEN_MASK (0x3FC00000)
#define QM_SS_I2C_CON_CLK_ENA BIT(31)
#define QM_SS_I2C_DATA_CMD_CMD BIT(8)
#define QM_SS_I2C_DATA_CMD_STOP BIT(9)
#define QM_SS_I2C_DATA_CMD_PUSH (0xC0000000)
#define QM_SS_I2C_DATA_CMD_POP (0x80000000)
#define QM_SS_I2C_SS_FS_SCL_CNT_HCNT_OFFSET (16)
#define QM_SS_I2C_SS_FS_SCL_CNT_16BIT_MASK (0xFFFF)
#define QM_SS_I2C_INTR_STAT_RX_UNDER BIT(0)
#define QM_SS_I2C_INTR_STAT_RX_OVER BIT(1)
#define QM_SS_I2C_INTR_STAT_RX_FULL BIT(2)
#define QM_SS_I2C_INTR_STAT_TX_OVER BIT(3)
#define QM_SS_I2C_INTR_STAT_TX_EMPTY BIT(4)
#define QM_SS_I2C_INTR_STAT_TX_ABRT BIT(6)
#define QM_SS_I2C_INTR_MASK_ALL (0x0)
#define QM_SS_I2C_INTR_MASK_RX_UNDER BIT(0)
#define QM_SS_I2C_INTR_MASK_RX_OVER BIT(1)
#define QM_SS_I2C_INTR_MASK_RX_FULL BIT(2)
#define QM_SS_I2C_INTR_MASK_TX_OVER BIT(3)
#define QM_SS_I2C_INTR_MASK_TX_EMPTY BIT(4)
#define QM_SS_I2C_INTR_MASK_TX_ABRT BIT(6)
#define QM_SS_I2C_TL_TX_TL_OFFSET (16)
#define QM_SS_I2C_TL_RX_TL_MASK (0xFF)
#define QM_SS_I2C_TL_TX_TL_MASK (0xFF0000)
#define QM_SS_I2C_INTR_CLR_ALL (0xFF)
#define QM_SS_I2C_INTR_CLR_TX_ABRT BIT(6)
#define QM_SS_I2C_TX_ABRT_SOURCE_NAK_MASK (0x09)
#define QM_SS_I2C_TX_ABRT_SOURCE_ALL_MASK (0x1FFFF)
#define QM_SS_I2C_TX_ABRT_SBYTE_NORSTRT BIT(9)
#define QM_SS_I2C_TX_ABRT_SOURCE_ART_LOST BIT(12)
#define QM_SS_I2C_ENABLE_CONTROLLER_EN BIT(0)
#define QM_SS_I2C_ENABLE_STATUS_IC_EN BIT(0)
#define QM_SS_I2C_STATUS_BUSY_MASK (0x21)
#define QM_SS_I2C_STATUS_RFNE BIT(3)
#define QM_SS_I2C_STATUS_TFE BIT(2)
#define QM_SS_I2C_STATUS_TFNF BIT(1)
#define QM_SS_I2C_IC_LCNT_MAX (65525)
#define QM_SS_I2C_IC_LCNT_MIN (8)
#define QM_SS_I2C_IC_HCNT_MAX (65525)
#define QM_SS_I2C_IC_HCNT_MIN (6)
#define QM_SS_I2C_FIFO_SIZE (8)
/** Sensor Subsystem I2C */
typedef enum { QM_SS_I2C_0 = 0, QM_SS_I2C_1, QM_SS_I2C_NUM } qm_ss_i2c_t;
#define QM_SS_I2C_0_BASE (0x80012000)
#define QM_SS_I2C_1_BASE (0x80012100)
/** @} */
/** Sensor Subsystem ADC @{*/
/** Sensor Subsystem ADC registers */
typedef enum {
QM_SS_ADC_SET = 0, /**< ADC and sequencer settings register. */
QM_SS_ADC_DIVSEQSTAT, /**< ADC clock and sequencer status register. */
QM_SS_ADC_SEQ, /**< ADC sequence entry register. */
QM_SS_ADC_CTRL, /**< ADC control register. */
QM_SS_ADC_INTSTAT, /**< ADC interrupt status register. */
QM_SS_ADC_SAMPLE /**< ADC sample register. */
} qm_ss_adc_reg_t;
/** Sensor Subsystem ADC */
typedef enum {
QM_SS_ADC_0 = 0, /**< ADC first module. */
QM_SS_ADC_NUM
} qm_ss_adc_t;
/**
* SS ADC context type.
*
* The application should not modify the content of this structure.
*
* This structure is intented to be used by qm_ss_adc_save_context and
* qm_ss_adc_restore_context functions only.
*/
typedef struct {
uint32_t adc_set; /**< ADC settings. */
uint32_t adc_divseqstat; /**< ADC clock divider and sequencer status. */
uint32_t adc_seq; /**< ADC sequencer entry. */
uint32_t adc_ctrl; /**< ADC control. */
} qm_ss_adc_context_t;
/* SS ADC register base. */
#define QM_SS_ADC_BASE (0x80015000)
/* For 1MHz, the max divisor is 7. */
#define QM_SS_ADC_DIV_MAX (7)
#define QM_SS_ADC_FIFO_LEN (32)
#define QM_SS_ADC_SET_POP_RX BIT(31)
#define QM_SS_ADC_SET_FLUSH_RX BIT(30)
#define QM_SS_ADC_SET_THRESHOLD_MASK (0x3F000000)
#define QM_SS_ADC_SET_THRESHOLD_OFFSET (24)
#define QM_SS_ADC_SET_SEQ_ENTRIES_MASK (0x3F0000)
#define QM_SS_ADC_SET_SEQ_ENTRIES_OFFSET (16)
#define QM_SS_ADC_SET_SEQ_MODE BIT(13)
#define QM_SS_ADC_SET_SAMPLE_WIDTH_MASK (0x1F)
#define QM_SS_ADC_DIVSEQSTAT_CLK_RATIO_MASK (0x1FFFFF)
#define QM_SS_ADC_CTRL_CLR_SEQERROR BIT(19)
#define QM_SS_ADC_CTRL_CLR_UNDERFLOW BIT(18)
#define QM_SS_ADC_CTRL_CLR_OVERFLOW BIT(17)
#define QM_SS_ADC_CTRL_CLR_DATA_A BIT(16)
#define QM_SS_ADC_CTRL_MSK_SEQERROR BIT(11)
#define QM_SS_ADC_CTRL_MSK_UNDERFLOW BIT(10)
#define QM_SS_ADC_CTRL_MSK_OVERFLOW BIT(9)
#define QM_SS_ADC_CTRL_MSK_DATA_A BIT(8)
#define QM_SS_ADC_CTRL_SEQ_TABLE_RST BIT(6)
#define QM_SS_ADC_CTRL_SEQ_PTR_RST BIT(5)
#define QM_SS_ADC_CTRL_SEQ_START BIT(4)
#define QM_SS_ADC_CTRL_CLK_ENA BIT(2)
#define QM_SS_ADC_CTRL_ADC_ENA BIT(1)
#define QM_SS_ADC_CTRL_MSK_ALL_INT (0xF00)
#define QM_SS_ADC_CTRL_CLR_ALL_INT (0xF0000)
#define QM_SS_ADC_SEQ_DELAYODD_OFFSET (21)
#define QM_SS_ADC_SEQ_MUXODD_OFFSET (16)
#define QM_SS_ADC_SEQ_DELAYEVEN_OFFSET (5)
#define QM_SS_ADC_SEQ_DUMMY (0x480)
#define QM_SS_ADC_INTSTAT_SEQERROR BIT(3)
#define QM_SS_ADC_INTSTAT_UNDERFLOW BIT(2)
#define QM_SS_ADC_INTSTAT_OVERFLOW BIT(1)
#define QM_SS_ADC_INTSTAT_DATA_A BIT(0)
/** End of Sensor Subsystem ADC @}*/
/**
* CREG Registers.
*
* @name SS CREG
* @{
*/
/* Sensor Subsystem CREG */
typedef enum {
QM_SS_IO_CREG_MST0_CTRL = 0x0, /**< Master control register. */
QM_SS_IO_CREG_SLV0_OBSR = 0x80, /**< Slave control register. */
QM_SS_IO_CREG_SLV1_OBSR = 0x180 /**< Slave control register. */
} qm_ss_creg_reg_t;
/* MST0_CTRL fields */
#define QM_SS_IO_CREG_MST0_CTRL_ADC_PWR_MODE_OFFSET (1)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_PWR_MODE_MASK (0x7)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_DELAY_OFFSET (3)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_DELAY_MASK (0xFFF8)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_REQ BIT(16)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_CMD_OFFSET (17)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_CMD_MASK (0xE0000)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_VAL_OFFSET (20)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_VAL_MASK (0x7F00000)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_CAL_VAL_MAX (0x7F)
#define QM_SS_IO_CREG_MST0_CTRL_SPI1_CLK_GATE BIT(27)
#define QM_SS_IO_CREG_MST0_CTRL_SPI0_CLK_GATE BIT(28)
#define QM_SS_IO_CREG_MST0_CTRL_I2C0_CLK_GATE BIT(29)
#define QM_SS_IO_CREG_MST0_CTRL_I2C1_CLK_GATE BIT(30)
#define QM_SS_IO_CREG_MST0_CTRL_ADC_CLK_GATE BIT(31)
/* SLV0_OBSR fields */
#define QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_VAL_OFFSET (5)
#define QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_VAL_MASK (0xFE0)
#define QM_SS_IO_CREG_SLV0_OBSR_ADC_CAL_ACK BIT(4)
#define QM_SS_IO_CREG_SLV0_OBSR_ADC_PWR_MODE_STS BIT(3)
#define SS_CLK_PERIPH_ALL_IN_CREG \
(SS_CLK_PERIPH_ADC | SS_CLK_PERIPH_I2C_1 | SS_CLK_PERIPH_I2C_0 | \
SS_CLK_PERIPH_SPI_1 | SS_CLK_PERIPH_SPI_0)
/* SS CREG base. */
#define QM_SS_CREG_BASE (0x80018000)
/** @} */
/**
* I2C registers and definitions.
*
* @name SS SPI
* @{
*/
/** Sensor Subsystem SPI register map. */
typedef enum {
QM_SS_SPI_CTRL = 0, /**< SPI control register. */
QM_SS_SPI_SPIEN = 2, /**< SPI enable register. */
QM_SS_SPI_TIMING = 4, /**< SPI serial clock divider value. */
QM_SS_SPI_FTLR, /**< Threshold value for TX/RX FIFO. */
QM_SS_SPI_TXFLR = 7, /**< Number of valid data entries in TX FIFO. */
QM_SS_SPI_RXFLR, /**< Number of valid data entries in RX FIFO. */
QM_SS_SPI_SR, /**< SPI status register. */
QM_SS_SPI_INTR_STAT, /**< Interrupt status register. */
QM_SS_SPI_INTR_MASK, /**< Interrupt mask register. */
QM_SS_SPI_CLR_INTR, /**< Interrupt clear register. */
QM_SS_SPI_DR, /**< RW buffer for FIFOs. */
} qm_ss_spi_reg_t;
/**
* Sensor Subsystem SPI context type.
*
* Applications should not modify the content.
* This structure is only intended to be used by
* the qm_ss_spi_save_context and qm_ss_spi_restore_context functions.
*/
typedef struct {
uint32_t spi_ctrl; /**< Control Register. */
uint32_t spi_spien; /**< SPI Enable Register. */
uint32_t spi_timing; /**< Timing Register. */
} qm_ss_spi_context_t;
/** Sensor Subsystem SPI modules. */
typedef enum {
QM_SS_SPI_0 = 0, /**< SPI module 0 */
QM_SS_SPI_1, /**< SPI module 1 */
QM_SS_SPI_NUM
} qm_ss_spi_t;
#define QM_SS_SPI_0_BASE (0x80010000)
#define QM_SS_SPI_1_BASE (0x80010100)
#define QM_SS_SPI_CTRL_DFS_OFFS (0)
#define QM_SS_SPI_CTRL_DFS_MASK (0x0000000F)
#define QM_SS_SPI_CTRL_BMOD_OFFS (6)
#define QM_SS_SPI_CTRL_BMOD_MASK (0x000000C0)
#define QM_SS_SPI_CTRL_SCPH BIT(6)
#define QM_SS_SPI_CTRL_SCPOL BIT(7)
#define QM_SS_SPI_CTRL_TMOD_OFFS (8)
#define QM_SS_SPI_CTRL_TMOD_MASK (0x00000300)
#define QM_SS_SPI_CTRL_SRL BIT(11)
#define QM_SS_SPI_CTRL_CLK_ENA BIT(15)
#define QM_SS_SPI_CTRL_NDF_OFFS (16)
#define QM_SS_SPI_CTRL_NDF_MASK (0xFFFF0000)
#define QM_SS_SPI_SPIEN_EN BIT(0)
#define QM_SS_SPI_SPIEN_SER_OFFS (4)
#define QM_SS_SPI_SPIEN_SER_MASK (0x000000F0)
#define QM_SS_SPI_TIMING_SCKDV_OFFS (0)
#define QM_SS_SPI_TIMING_SCKDV_MASK (0x0000FFFF)
#define QM_SS_SPI_TIMING_RSD_OFFS (16)
#define QM_SS_SPI_TIMING_RSD_MASK (0x00FF0000)
#define QM_SS_SPI_FTLR_RFT_OFFS (0)
#define QM_SS_SPI_FTLR_RFT_MASK (0x0000FFFF)
#define QM_SS_SPI_FTLR_TFT_OFFS (16)
#define QM_SS_SPI_FTLR_TFT_MASK (0xFFFF0000)
#define QM_SS_SPI_SR_BUSY BIT(0)
#define QM_SS_SPI_SR_TFNF BIT(1)
#define QM_SS_SPI_SR_TFE BIT(2)
#define QM_SS_SPI_SR_RFNE BIT(3)
#define QM_SS_SPI_SR_RFF BIT(4)
#define QM_SS_SPI_INTR_TXEI BIT(0)
#define QM_SS_SPI_INTR_TXOI BIT(1)
#define QM_SS_SPI_INTR_RXUI BIT(2)
#define QM_SS_SPI_INTR_RXOI BIT(3)
#define QM_SS_SPI_INTR_RXFI BIT(4)
#define QM_SS_SPI_INTR_ALL (0x0000001F)
#define QM_SS_SPI_INTR_STAT_TXEI QM_SS_SPI_INTR_TXEI
#define QM_SS_SPI_INTR_STAT_TXOI QM_SS_SPI_INTR_TXOI
#define QM_SS_SPI_INTR_STAT_RXUI QM_SS_SPI_INTR_RXUI
#define QM_SS_SPI_INTR_STAT_RXOI QM_SS_SPI_INTR_RXOI
#define QM_SS_SPI_INTR_STAT_RXFI QM_SS_SPI_INTR_RXFI
#define QM_SS_SPI_INTR_MASK_TXEI QM_SS_SPI_INTR_TXEI
#define QM_SS_SPI_INTR_MASK_TXOI QM_SS_SPI_INTR_TXOI
#define QM_SS_SPI_INTR_MASK_RXUI QM_SS_SPI_INTR_RXUI
#define QM_SS_SPI_INTR_MASK_RXOI QM_SS_SPI_INTR_RXOI
#define QM_SS_SPI_INTR_MASK_RXFI QM_SS_SPI_INTR_RXFI
#define QM_SS_SPI_CLR_INTR_TXEI QM_SS_SPI_INTR_TXEI
#define QM_SS_SPI_CLR_INTR_TXOI QM_SS_SPI_INTR_TXOI
#define QM_SS_SPI_CLR_INTR_RXUI QM_SS_SPI_INTR_RXUI
#define QM_SS_SPI_CLR_INTR_RXOI QM_SS_SPI_INTR_RXOI
#define QM_SS_SPI_CLR_INTR_RXFI QM_SS_SPI_INTR_RXFI
#define QM_SS_SPI_DR_DR_OFFS (0)
#define QM_SS_SPI_DR_DR_MASK (0x0000FFFF)
#define QM_SS_SPI_DR_WR BIT(30)
#define QM_SS_SPI_DR_STROBE BIT(31)
#define QM_SS_SPI_DR_W_MASK (0xc0000000)
#define QM_SS_SPI_DR_R_MASK (0x80000000)
/** @} */
/** @} */
#endif /* __SENSOR_REGISTERS_H__ */

View File

@ -0,0 +1,295 @@
/*
* Copyright (c) 2016, 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_sensor_regs.h"
/**
* SS Power mode control for Quark SE Microcontrollers.
*
* @defgroup groupSSPower SS Power states
* @{
*/
/**
* Sensor Subsystem SS1 Timers mode type.
*/
typedef enum {
SS_POWER_CPU_SS1_TIMER_OFF = 0, /**< Disable SS Timers in SS1. */
SS_POWER_CPU_SS1_TIMER_ON /**< Keep SS Timers enabled in SS1. */
} 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, 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 ss_power_soc_lpss_enable(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_soc_sleep().
*/
//void 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_soc_deep_sleep().
*/
//void 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 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 ss_power_sleep_wait(void);
/**
* Enable the SENSOR startup restore flag.
*/
//void power_soc_set_ss_restore_flag(void);
/**
* 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 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 ss_power_cpu_ss1(const 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 ss_power_cpu_ss2(void);
/**
* 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")
/**
* @}
*/
#endif /* __QM_SS_POWER_STATES_H__ */