diff --git a/src/ArduinoLowPower.h b/src/ArduinoLowPower.h
index 9228f69..66c280c 100644
--- a/src/ArduinoLowPower.h
+++ b/src/ArduinoLowPower.h
@@ -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;
diff --git a/src/ArduinoLowPowerARC32.cpp b/src/ArduinoLowPowerARC32.cpp
new file mode 100644
index 0000000..7b81d03
--- /dev/null
+++ b/src/ArduinoLowPowerARC32.cpp
@@ -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
\ No newline at end of file
diff --git a/src/include/arc32/power_states.h b/src/include/arc32/power_states.h
new file mode 100644
index 0000000..eb5fecf
--- /dev/null
+++ b/src/include/arc32/power_states.h
@@ -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__ */
diff --git a/src/include/arc32/qm_sensor_regs.h b/src/include/arc32/qm_sensor_regs.h
new file mode 100644
index 0000000..324d001
--- /dev/null
+++ b/src/include/arc32/qm_sensor_regs.h
@@ -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__ */
diff --git a/src/include/arc32/ss_power_states.h b/src/include/arc32/ss_power_states.h
new file mode 100644
index 0000000..f4dd80b
--- /dev/null
+++ b/src/include/arc32/ss_power_states.h
@@ -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.
+ * This function needs to be called on the Sensor Core to
+ * Clock Gate ADC, I2C0, I2C1, SPI0 and SPI1 sensor peripherals.
+ * Clock Gating sensor peripherals is a requirement to enter LPSS state.
+ * After LPSS, ss_power_soc_lpss_disable needs to be called to
+ * restore clock gating.
+ *
+ * This needs to be called before any transition to C2/C2LP and SS2
+ * in order to enter LPSS.
+ * SoC Hybrid Clock is gated in this state.
+ * Core Well Clocks are gated.
+ * 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.
+ * Disable Clock Gating of ADC, I2C0, I2C1, SPI0 and SPI1 sensor
+ * peripherals.
+ * 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.
+ * Processor Clock is gated in this state.
+ *
+ * A wake event causes the Sensor Subsystem to transition to SS0.
+ * 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.
+ * Sensor Complex Clock is gated in this state.
+ * Sensor Peripherals are gated in this state.
+ *
+ * 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.
+ * 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__ */