summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorJesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>2016-06-30 17:25:00 -0300
committerKuo-Lang Tseng <kuo-lang.tseng@intel.com>2016-07-01 13:43:02 -0700
commitabd7496225ea4caf6b26e6fe7db998bcf5e539e4 (patch)
treef5abc4e575d32752d48c60d02c27f91bd1f04f51 /ext
parent19fa82ab910071382ca5df08f5c771450b7861f1 (diff)
ext qmsi: Update to QMSI 1.1-Beta
QMSI 1.1 Beta is available on Github: https://github.com/01org/qmsi/releases/tag/v1.1.0-beta Update the QMSI drop we maintain in Zephyr and keep the modification to qm_soc_regs.h introduced on commit 6b88a6b945e8 "ext qmsi: Add USB base and interrupt defines" since that patch hasn't made into the QMSI 1.1-Beta release in time. Also, fix the build where needed: - add hard dependency from qm_i2c to qm_dma - fix spi_qmsi_ss.c due to new parameter naming - fix adc_qmsi.c and adc_qmsi_ss.c due to a new parameter Change-Id: I01388c787f5ee6ee97fece2e42b24a717522207f Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com> Signed-off-by: Kuo-Lang Tseng <kuo-lang.tseng@intel.com>
Diffstat (limited to 'ext')
-rw-r--r--ext/hal/qmsi/README4
-rw-r--r--ext/hal/qmsi/drivers/clk.c28
-rw-r--r--ext/hal/qmsi/drivers/dma.h4
-rw-r--r--ext/hal/qmsi/drivers/include/qm_adc.h4
-rw-r--r--ext/hal/qmsi/drivers/include/qm_flash.h2
-rw-r--r--ext/hal/qmsi/drivers/include/qm_i2c.h43
-rw-r--r--ext/hal/qmsi/drivers/include/qm_interrupt.h2
-rw-r--r--ext/hal/qmsi/drivers/include/qm_isr.h2
-rw-r--r--ext/hal/qmsi/drivers/include/qm_mailbox.h6
-rw-r--r--ext/hal/qmsi/drivers/include/qm_pic_timer.h1
-rw-r--r--ext/hal/qmsi/drivers/include/qm_rtc.h15
-rw-r--r--ext/hal/qmsi/drivers/include/qm_spi.h12
-rw-r--r--ext/hal/qmsi/drivers/include/qm_uart.h10
-rw-r--r--ext/hal/qmsi/drivers/include/soc_watch.h163
-rw-r--r--ext/hal/qmsi/drivers/qm_adc.c41
-rw-r--r--ext/hal/qmsi/drivers/qm_aon_counters.c2
-rw-r--r--ext/hal/qmsi/drivers/qm_dma.c2
-rw-r--r--ext/hal/qmsi/drivers/qm_fpr.c65
-rw-r--r--ext/hal/qmsi/drivers/qm_gpio.c19
-rw-r--r--ext/hal/qmsi/drivers/qm_i2c.c213
-rw-r--r--ext/hal/qmsi/drivers/qm_interrupt.c12
-rw-r--r--ext/hal/qmsi/drivers/qm_mailbox.c13
-rw-r--r--ext/hal/qmsi/drivers/qm_mpr.c68
-rw-r--r--ext/hal/qmsi/drivers/qm_rtc.c27
-rw-r--r--ext/hal/qmsi/drivers/qm_spi.c110
-rw-r--r--ext/hal/qmsi/drivers/qm_uart.c197
-rw-r--r--ext/hal/qmsi/drivers/qm_version.c2
-rw-r--r--ext/hal/qmsi/drivers/qm_wdt.c5
-rw-r--r--ext/hal/qmsi/drivers/sensor/include/qm_ss_adc.h9
-rw-r--r--ext/hal/qmsi/drivers/sensor/include/qm_ss_gpio.h8
-rw-r--r--ext/hal/qmsi/drivers/sensor/include/qm_ss_i2c.h30
-rw-r--r--ext/hal/qmsi/drivers/sensor/include/qm_ss_spi.h16
-rw-r--r--ext/hal/qmsi/drivers/sensor/include/qm_ss_timer.h7
-rw-r--r--ext/hal/qmsi/drivers/sensor/qm_ss_adc.c110
-rw-r--r--ext/hal/qmsi/drivers/sensor/qm_ss_gpio.c2
-rw-r--r--ext/hal/qmsi/drivers/sensor/qm_ss_i2c.c151
-rw-r--r--ext/hal/qmsi/drivers/sensor/qm_ss_spi.c104
-rw-r--r--ext/hal/qmsi/drivers/sensor/sensor.mk44
-rw-r--r--ext/hal/qmsi/drivers/sensor/ss_power_states.c26
-rw-r--r--ext/hal/qmsi/drivers/soc_watch.c355
-rw-r--r--ext/hal/qmsi/include/qm_common.h46
-rw-r--r--ext/hal/qmsi/include/spinlock.h60
-rw-r--r--ext/hal/qmsi/soc/quark_d2000/drivers/power_states.c79
-rw-r--r--ext/hal/qmsi/soc/quark_d2000/include/flash_layout.h72
-rw-r--r--ext/hal/qmsi/soc/quark_d2000/include/power_states.h22
-rw-r--r--ext/hal/qmsi/soc/quark_d2000/include/qm_soc_regs.h520
-rw-r--r--ext/hal/qmsi/soc/quark_se/drivers/power_states.c40
-rw-r--r--ext/hal/qmsi/soc/quark_se/include/flash_layout.h113
-rw-r--r--ext/hal/qmsi/soc/quark_se/include/qm_sensor_regs.h81
-rw-r--r--ext/hal/qmsi/soc/quark_se/include/qm_soc_regs.h819
50 files changed, 2625 insertions, 1161 deletions
diff --git a/ext/hal/qmsi/README b/ext/hal/qmsi/README
index f403146cd..2d692e27e 100644
--- a/ext/hal/qmsi/README
+++ b/ext/hal/qmsi/README
@@ -8,8 +8,8 @@ Microcontroller products. It currently support the following SoCs:
- Intel® Quark™ D2000 Microcontroller
- Intel® Quark™ SE Microcontroller
-The current version supported in Zephyr is QMSI 1.1.0 See
+The current version supported in Zephyr is QMSI 1.1.0-Beta. See:
- https://github.com/01org/qmsi/releases/tag/v1.1.0
+ https://github.com/01org/qmsi/releases/tag/v1.1.0-beta
for more details.
diff --git a/ext/hal/qmsi/drivers/clk.c b/ext/hal/qmsi/drivers/clk.c
index 7af11f0ec..fa93ba763 100644
--- a/ext/hal/qmsi/drivers/clk.c
+++ b/ext/hal/qmsi/drivers/clk.c
@@ -33,6 +33,8 @@
#include <x86intrin.h>
#endif
+#include "soc_watch.h"
+
#if (QM_SENSOR) && (!UNIT_TEST)
/* Timestamp counter for Sensor Subsystem is 32bit. */
#define get_ticks() __builtin_arc_lr(QM_SS_TSC_BASE + QM_SS_TIMER_COUNT)
@@ -51,7 +53,7 @@ static uint32_t ticks_per_us = SYS_TICKS_PER_US_32MHZ;
int clk_sys_set_mode(const clk_sys_mode_t mode, const clk_sys_div_t div)
{
- QM_CHECK(div <= CLK_SYS_DIV_NUM, -EINVAL);
+ QM_CHECK(div < CLK_SYS_DIV_NUM, -EINVAL);
QM_CHECK(mode <= CLK_SYS_CRYSTAL_OSC, -EINVAL);
uint16_t trim = 0;
@@ -158,6 +160,9 @@ int clk_sys_set_mode(const clk_sys_mode_t mode, const clk_sys_div_t div)
QM_SCSS_CCU->ccu_sys_clk_ctl |= QM_CCU_SYS_CLK_DIV_EN;
ticks_per_us = (sys_ticks_per_us > 0 ? sys_ticks_per_us : 1);
+ /* Log any clock changes. */
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_OSC0_CFG1);
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_SYS_CLK_CTL);
return 0;
}
@@ -173,11 +178,26 @@ int clk_trim_read(uint32_t *const value)
int clk_trim_apply(const uint32_t value)
{
+ /* Enable trim mode */
+ QM_SCSS_CCU->osc0_cfg0 |= BIT(1);
+
/* Apply trim code */
QM_SCSS_CCU->osc0_cfg1 &= ~OSC0_CFG1_FTRIMOTP_MASK;
QM_SCSS_CCU->osc0_cfg1 |=
(value << OSC0_CFG1_FTRIMOTP_OFFS) & OSC0_CFG1_FTRIMOTP_MASK;
+ /*
+ * Recommended wait time after setting up the trim code
+ * is 200us. Minimum wait time is 100us.
+ * The delay is running from of the silicon oscillator
+ * which is been trimmed. This induces a lack of precision
+ * in the delay.
+ */
+ clk_sys_udelay(200);
+
+ /* Disable trim mode */
+ QM_SCSS_CCU->osc0_cfg0 &= ~BIT(1);
+
return 0;
}
@@ -270,6 +290,9 @@ int clk_periph_enable(const clk_periph_t clocks)
QM_SCSS_CCU->ccu_periph_clk_gate_ctl |= clocks;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER,
+ SOCW_REG_CCU_PERIPH_CLK_GATE_CTL);
+
return 0;
}
@@ -279,6 +302,9 @@ int clk_periph_disable(const clk_periph_t clocks)
QM_SCSS_CCU->ccu_periph_clk_gate_ctl &= ~clocks;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER,
+ SOCW_REG_CCU_PERIPH_CLK_GATE_CTL);
+
return 0;
}
diff --git a/ext/hal/qmsi/drivers/dma.h b/ext/hal/qmsi/drivers/dma.h
index 3a4acb1a3..bcc7dd8f7 100644
--- a/ext/hal/qmsi/drivers/dma.h
+++ b/ext/hal/qmsi/drivers/dma.h
@@ -159,10 +159,6 @@ static int dma_channel_disable(const qm_dma_t dma,
timeout_us--;
}
- if (!(chan_reg->cfg_low & QM_DMA_CFG_L_FIFO_EMPTY_MASK)) {
- return -EIO;
- }
-
/* Disable the channel and wait to confirm that it has been disabled. */
misc_reg->chan_en_low = (channel_mask << QM_DMA_MISC_CHAN_EN_WE_OFFSET);
diff --git a/ext/hal/qmsi/drivers/include/qm_adc.h b/ext/hal/qmsi/drivers/include/qm_adc.h
index c7011be63..3fb00d4ab 100644
--- a/ext/hal/qmsi/drivers/include/qm_adc.h
+++ b/ext/hal/qmsi/drivers/include/qm_adc.h
@@ -267,12 +267,14 @@ int qm_adc_set_config(const qm_adc_t adc, const qm_adc_config_t *const cfg);
*
* @param[in] adc Which ADC to read.
* @param[in,out] xfer Channel and sample info. This must not be NULL.
+ * @param[out] status Get status of the ADC device.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
-int qm_adc_convert(const qm_adc_t adc, qm_adc_xfer_t *const xfer);
+int qm_adc_convert(const qm_adc_t adc, qm_adc_xfer_t *const xfer,
+ qm_adc_status_t *const status);
/**
* Asynchronously read values from the ADC.
diff --git a/ext/hal/qmsi/drivers/include/qm_flash.h b/ext/hal/qmsi/drivers/include/qm_flash.h
index 255ec2b58..051449f2d 100644
--- a/ext/hal/qmsi/drivers/include/qm_flash.h
+++ b/ext/hal/qmsi/drivers/include/qm_flash.h
@@ -32,7 +32,7 @@
#include "qm_common.h"
#include "qm_soc_regs.h"
-
+#include "qm_interrupt.h"
/**
* Flash controller.
*
diff --git a/ext/hal/qmsi/drivers/include/qm_i2c.h b/ext/hal/qmsi/drivers/include/qm_i2c.h
index 623dafe5c..32549ee1a 100644
--- a/ext/hal/qmsi/drivers/include/qm_i2c.h
+++ b/ext/hal/qmsi/drivers/include/qm_i2c.h
@@ -58,9 +58,9 @@
/**
* QM I2C addressing type.
*/
-typedef enum{
+typedef enum {
QM_I2C_7_BIT = 0, /**< 7-bit mode. */
- QM_I2C_10_BIT /**< 10-bit mode. */
+ QM_I2C_10_BIT /**< 10-bit mode. */
} qm_i2c_addr_t;
/**
@@ -68,7 +68,7 @@ typedef enum{
*/
typedef enum {
QM_I2C_MASTER, /**< Master mode. */
- QM_I2C_SLAVE /**< Slave mode. */
+ QM_I2C_SLAVE /**< Slave mode. */
} qm_i2c_mode_t;
/**
@@ -84,27 +84,27 @@ typedef enum {
* I2C status type.
*/
typedef enum {
- QM_I2C_IDLE = 0, /**< Controller idle. */
+ QM_I2C_IDLE = 0, /**< Controller idle. */
QM_I2C_TX_ABRT_7B_ADDR_NOACK = BIT(0), /**< 7-bit address noack. */
QM_I2C_TX_ABRT_10ADDR1_NOACK = BIT(1), /**< 10-bit address noack. */
QM_I2C_TX_ABRT_10ADDR2_NOACK = BIT(2), /**< 10-bit second address
byte address noack. */
- QM_I2C_TX_ABRT_TXDATA_NOACK = BIT(3), /**< Tx data noack. */
- QM_I2C_TX_ABRT_GCALL_NOACK = BIT(4), /**< General call noack. */
- QM_I2C_TX_ABRT_GCALL_READ = BIT(5), /**< Read after general call. */
- QM_I2C_TX_ABRT_HS_ACKDET = BIT(6), /**< High Speed master ID ACK. */
- QM_I2C_TX_ABRT_SBYTE_ACKDET = BIT(7), /**< Start ACK. */
- QM_I2C_TX_ABRT_HS_NORSTRT = BIT(8), /**< High Speed with restart
- disabled. */
+ QM_I2C_TX_ABRT_TXDATA_NOACK = BIT(3), /**< Tx data noack. */
+ QM_I2C_TX_ABRT_GCALL_NOACK = BIT(4), /**< General call noack. */
+ QM_I2C_TX_ABRT_GCALL_READ = BIT(5), /**< Read after general call. */
+ QM_I2C_TX_ABRT_HS_ACKDET = BIT(6), /**< High Speed master ID ACK. */
+ QM_I2C_TX_ABRT_SBYTE_ACKDET = BIT(7), /**< Start ACK. */
+ QM_I2C_TX_ABRT_HS_NORSTRT = BIT(8), /**< High Speed with restart
+ disabled. */
QM_I2C_TX_ABRT_10B_RD_NORSTRT = BIT(10), /**< 10-bit address read and
restart disabled. */
- QM_I2C_TX_ABRT_MASTER_DIS = BIT(11), /**< Master disabled. */
+ QM_I2C_TX_ABRT_MASTER_DIS = BIT(11), /**< Master disabled. */
QM_I2C_TX_ARB_LOST = BIT(12), /**< Master lost arbitration. */
QM_I2C_TX_ABRT_SLVFLUSH_TXFIFO = BIT(13), /**< Slave flush tx FIFO. */
- QM_I2C_TX_ABRT_SLV_ARBLOST = BIT(14), /**< Slave lost bus. */
- QM_I2C_TX_ABRT_SLVRD_INTX = BIT(15), /**< Slave read completion. */
- QM_I2C_TX_ABRT_USER_ABRT = BIT(16), /**< User abort. */
- QM_I2C_BUSY = BIT(17) /**< Controller busy. */
+ QM_I2C_TX_ABRT_SLV_ARBLOST = BIT(14), /**< Slave lost bus. */
+ QM_I2C_TX_ABRT_SLVRD_INTX = BIT(15), /**< Slave read completion. */
+ QM_I2C_TX_ABRT_USER_ABRT = BIT(16), /**< User abort. */
+ QM_I2C_BUSY = BIT(17) /**< Controller busy. */
} qm_i2c_status_t;
/**
@@ -135,7 +135,7 @@ typedef struct {
bool stop; /**< Generate master STOP. */
void (*callback)(void *data, int rc, qm_i2c_status_t status,
uint32_t len); /**< Callback. */
- void *callback_data; /**< Callback identifier. */
+ void *callback_data; /**< Callback identifier. */
} qm_i2c_transfer_t;
/**
@@ -217,8 +217,8 @@ int qm_i2c_master_write(const qm_i2c_t i2c, const uint16_t slave_addr,
* @retval Negative @ref errno for possible error codes.
*/
int qm_i2c_master_read(const qm_i2c_t i2c, const uint16_t slave_addr,
- uint8_t *const data, uint32_t len,
- const bool stop, qm_i2c_status_t *const status);
+ uint8_t *const data, uint32_t len, const bool stop,
+ qm_i2c_status_t *const status);
/**
* Interrupt based master transfer on I2C.
@@ -228,8 +228,9 @@ int qm_i2c_master_read(const qm_i2c_t i2c, const uint16_t slave_addr,
*
* @param[in] i2c Which I2C to transfer from.
* @param[in] xfer Transfer structure includes write / read buffers, length,
- * user callback function and the callback context. This must
- * not be NULL.
+ * user callback function and the callback context.
+ * The structure must not be NULL and must be kept valid until
+ * the transfer is complete.
* @param[in] slave_addr Address of slave to transfer data with.
*
* @return Standard errno return type for QMSI.
diff --git a/ext/hal/qmsi/drivers/include/qm_interrupt.h b/ext/hal/qmsi/drivers/include/qm_interrupt.h
index ae83be8fa..5e9c3814e 100644
--- a/ext/hal/qmsi/drivers/include/qm_interrupt.h
+++ b/ext/hal/qmsi/drivers/include/qm_interrupt.h
@@ -115,7 +115,7 @@ void _qm_irq_setup(uint32_t irq, uint16_t register_offset);
* @param[in] isr ISR to register to given IRQ.
*/
#if (UNIT_TEST)
-#define qm_int_vector_request(vector, isr)
+void qm_int_vector_request(uint32_t vector, qm_isr_t isr);
#else
#if (__iamcu__)
/*
diff --git a/ext/hal/qmsi/drivers/include/qm_isr.h b/ext/hal/qmsi/drivers/include/qm_isr.h
index d85dbb9f2..2f319861d 100644
--- a/ext/hal/qmsi/drivers/include/qm_isr.h
+++ b/ext/hal/qmsi/drivers/include/qm_isr.h
@@ -69,6 +69,7 @@ QM_ISR_DECLARE(qm_adc_pwr_0_isr);
* @endcode if IRQ based calibration is used.
*/
QM_ISR_DECLARE(qm_ss_adc_0_cal_isr);
+
/**
* ISR for SS ADC 0 mode change interrupt.
*
@@ -79,6 +80,7 @@ QM_ISR_DECLARE(qm_ss_adc_0_cal_isr);
QM_ISR_DECLARE(qm_ss_adc_0_pwr_isr);
#endif /* QUARK_SE */
+
/**
* ISR for Always-on Periodic Timer 0 interrupt.
*
diff --git a/ext/hal/qmsi/drivers/include/qm_mailbox.h b/ext/hal/qmsi/drivers/include/qm_mailbox.h
index 766187f12..98815e0d6 100644
--- a/ext/hal/qmsi/drivers/include/qm_mailbox.h
+++ b/ext/hal/qmsi/drivers/include/qm_mailbox.h
@@ -111,7 +111,7 @@ typedef void (*qm_mbox_callback_t)(void *data);
* @retval Negative @ref errno for possible error codes.
*/
int qm_mbox_ch_set_config(const qm_mbox_ch_t mbox_ch, qm_mbox_callback_t mpr_cb,
- void *cb_data, const bool irq_en);
+ void *cb_data, const bool irq_en);
/**
* Write to a specified mailbox channel.
@@ -125,7 +125,7 @@ int qm_mbox_ch_set_config(const qm_mbox_ch_t mbox_ch, qm_mbox_callback_t mpr_cb,
* @retval Negative @ref errno for possible error codes.
*/
int qm_mbox_ch_write(const qm_mbox_ch_t mbox_ch,
- const qm_mbox_msg_t *const msg);
+ const qm_mbox_msg_t *const msg);
/**
* Read specified mailbox channel.
@@ -151,7 +151,7 @@ int qm_mbox_ch_read(const qm_mbox_ch_t mbox_ch, qm_mbox_msg_t *const msg);
* @retval Negative @ref errno for possible error codes.
*/
int qm_mbox_ch_get_status(const qm_mbox_ch_t mbox_ch,
- qm_mbox_ch_status_t *const status);
+ qm_mbox_ch_status_t *const status);
/**
* Acknowledge the data arrival.
diff --git a/ext/hal/qmsi/drivers/include/qm_pic_timer.h b/ext/hal/qmsi/drivers/include/qm_pic_timer.h
index 0bae6f2d2..a5b2baaa6 100644
--- a/ext/hal/qmsi/drivers/include/qm_pic_timer.h
+++ b/ext/hal/qmsi/drivers/include/qm_pic_timer.h
@@ -54,6 +54,7 @@ typedef enum {
typedef struct {
qm_pic_timer_mode_t mode; /**< Operation mode. */
bool int_en; /**< Interrupt enable. */
+
/**
* User callback.
*
diff --git a/ext/hal/qmsi/drivers/include/qm_rtc.h b/ext/hal/qmsi/drivers/include/qm_rtc.h
index 2a1cb07e7..bdd8eeca8 100644
--- a/ext/hal/qmsi/drivers/include/qm_rtc.h
+++ b/ext/hal/qmsi/drivers/include/qm_rtc.h
@@ -59,6 +59,7 @@ typedef struct {
uint32_t init_val; /**< Initial value in RTC clocks. */
bool alarm_en; /**< Alarm enable. */
uint32_t alarm_val; /**< Alarm value in RTC clocks. */
+
/**
* User callback.
*
@@ -75,6 +76,13 @@ typedef struct {
* an alarm is required. If the alarm is enabled, register an ISR with the user
* defined callback function.
*
+ * The RTC clock resides in a different clock domain
+ * to the system clock.
+ * It takes 3-4 RTC ticks for a system clock write to propagate
+ * to the RTC domain.
+ * If an entry to sleep is initiated without waiting for the
+ * transaction to complete the SOC will not wake from sleep.
+ *
* @param[in] rtc RTC index.
* @param[in] cfg New RTC configuration. This must not be NULL.
*
@@ -90,6 +98,13 @@ int qm_rtc_set_config(const qm_rtc_t rtc, const qm_rtc_config_t *const cfg);
* Set a new RTC alarm value after an alarm, that has been set using the
* qm_rtc_set_config function, has expired and a new alarm value is required.
*
+ * The RTC clock resides in a different clock domain
+ * to the system clock.
+ * It takes 3-4 RTC ticks for a system clock write to propagate
+ * to the RTC domain.
+ * If an entry to sleep is initiated without waiting for the
+ * transaction to complete the SOC will not wake from sleep.
+ *
* @param[in] rtc RTC index.
* @param[in] alarm_val Value to set alarm to.
*
diff --git a/ext/hal/qmsi/drivers/include/qm_spi.h b/ext/hal/qmsi/drivers/include/qm_spi.h
index 1f7baaa85..9bf09d245 100644
--- a/ext/hal/qmsi/drivers/include/qm_spi.h
+++ b/ext/hal/qmsi/drivers/include/qm_spi.h
@@ -99,7 +99,9 @@ typedef enum {
/**
* SPI slave select type.
*
- * QM_SPI_SS_DISABLED prevents the controller from starting a transfer.
+ * Slave selects can combined by logical OR if multiple slaves are selected
+ * during one transfer. Setting only QM_SPI_SS_DISABLED prevents the controller
+ * from starting the transfer.
*/
typedef enum {
QM_SPI_SS_DISABLED = 0, /**< Slave select disable. */
@@ -139,8 +141,8 @@ typedef struct {
*/
typedef struct {
uint8_t *tx; /**< Write data. */
- uint16_t tx_len; /**< Write data Length. */
uint8_t *rx; /**< Read data. */
+ uint16_t tx_len; /**< Write data Length. */
uint16_t rx_len; /**< Read buffer length. */
/**
@@ -152,8 +154,8 @@ typedef struct {
* @param[in] data The callback user data.
* @param[in] error 0 on success.
* Negative @ref errno for possible error codes.
- * @param[in] status SPI driver status.
- * @param[in] len Length of the SPI transfer if successful, 0
+ * @param[in] status SPI driver status.
+ * @param[in] len Length of the SPI transfer if successful, 0
* otherwise.
*/
void (*callback)(void *data, int error, qm_spi_status_t status,
@@ -166,8 +168,8 @@ typedef struct {
*/
typedef struct {
uint8_t *tx; /**< Write Data. */
- uint16_t tx_len; /**< Write Data Length. */
uint8_t *rx; /**< Read Data. */
+ uint16_t tx_len; /**< Write Data Length. */
uint16_t rx_len; /**< Receive Data Length. */
} qm_spi_transfer_t;
diff --git a/ext/hal/qmsi/drivers/include/qm_uart.h b/ext/hal/qmsi/drivers/include/qm_uart.h
index 6655f9c28..fe62c2775 100644
--- a/ext/hal/qmsi/drivers/include/qm_uart.h
+++ b/ext/hal/qmsi/drivers/include/qm_uart.h
@@ -331,7 +331,8 @@ int qm_uart_write_buffer(const qm_uart_t uart, const uint8_t *const data,
* @param[in] uart UART index.
* @param[in] xfer Structure containing pre-allocated
* write buffer and callback functions.
- * This must not be NULL.
+ * The structure must not be NULL and must be kept valid until
+ * the transfer is complete.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
@@ -349,7 +350,8 @@ int qm_uart_irq_write(const qm_uart_t uart,
* @param[in] uart UART index.
* @param[in] xfer Structure containing pre-allocated read
* buffer and callback functions.
- * This must not be NULL.
+ * The structure must not be NULL and must be kept valid until
+ * the transfer is complete.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
@@ -424,6 +426,10 @@ int qm_uart_dma_channel_config(
* QM_DMA_MEMORY_TO_PERIPHERAL to be used on this UART, calling
* qm_uart_dma_channel_config(). The transfer length is limited to 4KB.
*
+ * Note that this function uses the UART TX FIFO empty interrupt and therefore,
+ * in addition to the DMA interrupts, the ISR of the corresponding UART must be
+ * registered before using this function.
+ *
* @param[in] uart UART index.
* @param[in] xfer Structure containing a pre-allocated write buffer
* and callback functions.
diff --git a/ext/hal/qmsi/drivers/include/soc_watch.h b/ext/hal/qmsi/drivers/include/soc_watch.h
new file mode 100644
index 000000000..d24559e48
--- /dev/null
+++ b/ext/hal/qmsi/drivers/include/soc_watch.h
@@ -0,0 +1,163 @@
+/*
+ * 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 __SOC_WATCH_H__
+#define __SOC_WATCH_H__
+
+/* This file relies on the SOC being defined, which comes from qm_soc_regs.h */
+#include "qm_soc_regs.h"
+
+/**
+ * SoC Watch (Energy Analyzer).
+ *
+ * @defgroup group SOC_WATCH
+ * @{
+ */
+
+#include "qm_common.h"
+
+/*
+ * To activate the functionality in this file, compile with
+ * SOC_WATCH_ENABLE=1 on the make command line.
+ *
+ * Accurate timestamping through sleep modes also requires:
+ * + board design: provide an RTC crystal
+ * + application : don't reset or disable the RTC.
+ */
+
+/**
+ * Power profiling events enumeration.
+ *
+ * In order to maintain binary compatibility, only SOCW_EVENT_MAX should
+ * ever be altered: new events should be inserted before SOCW_EVENT_MAX,
+ * and SOCW_EVENT_MAX incremented. Add events, do not replace them.
+ */
+typedef enum {
+ SOCW_EVENT_HALT = 0, /**< CPU Halt. */
+ SOCW_EVENT_INTERRUPT = 1, /**< CPU interrupt generated. */
+ SOCW_EVENT_SLEEP = 2, /**< Sleep mode entered. */
+ SOCW_EVENT_REGISTER = 3, /**< SOC register altered. */
+ SOCW_EVENT_APP = 4, /**< Application-defined event. */
+ SOCW_EVENT_MAX = 5 /**< End of events sentinel. */
+} soc_watch_event_t;
+
+/**
+ * Register ID enumeration.
+ *
+ * The Register Event stores a register ID enumeration instead of a
+ * register address in order to save space. Registers can be added,
+ * but they should not be deleted, in order to preserve compatibility
+ * with different versions of the post-processor.
+ *
+ * Note that most of these names mirror the names used elsewhere in
+ * the QMSI code, although these are upper case, while the register
+ * pointer names are in lower case. That's one clue for identifying
+ * where logging calls should to be added: wherever you see one of the
+ * named registers below being written, you should consider that write
+ * may need a corresponding SoC Watch logging call.
+ */
+#if (QUARK_D2000)
+typedef enum {
+ /* Clock rate registers */
+ SOCW_REG_OSC0_CFG1 = 0, /**< 0x000 OSC0_CFG1 register. */
+ SOCW_REG_CCU_LP_CLK_CTL = 1, /**< 0x02C Clock Control register.*/
+ SOCW_REG_CCU_SYS_CLK_CTL = 2, /**< 0x038 System Clock Control. */
+ /* Clock gating registers. */
+ SOCW_REG_CCU_PERIPH_CLK_GATE_CTL = 3, /**< 0x018 Perip Clock Gate Ctl.*/
+ SOCW_REG_CCU_EXT_CLK_CTL = 4, /**< 0x024 CCU Ext Clock Gate Ctl.*/
+ /* Registers affecting power consumption */
+ SOCW_REG_CMP_PWR = 5, /**< 0x30C Comprtr Power Enable. */
+ SOCW_REG_PMUX_PULLUP = 6, /**< 0x900 Pin Mux Pullup. */
+ SOCW_REG_PMUX_SLEW = 7, /**< 0x910 Pin Mux Slew. */
+ SOCW_REG_PMUX_IN_EN = 8, /**< 0x920 Pin Mux In Enable. */
+ SOCW_REG_MAX, /**< Register enum sentinel. */
+} soc_watch_reg_t;
+
+#elif(QUARK_SE)
+typedef enum {
+ /* Clock rate registers */
+ SOCW_REG_OSC0_CFG1 = 0, /**< 0x000 OSC0_CFG1 register. */
+ SOCW_REG_CCU_LP_CLK_CTL = 1, /**< 0x02C Clock Control register. */
+ SOCW_REG_CCU_SYS_CLK_CTL = 2, /**< 0x038 System Clock Control. */
+ /* Clock gating registers. */
+ SOCW_REG_CCU_PERIPH_CLK_GATE_CTL = 3, /**< 0x018 Perip Clock Gate Ctl.*/
+ SOCW_REG_CCU_SS_PERIPH_CLK_GATE_CTL = 4, /**< 0x0028 SS PCL Gate Ctl.*/
+ SOCW_REG_CCU_EXT_CLK_CTL = 5, /**< 0x024 CCU Ext Clock Gate Ctl.*/
+ /* Registers affecting power consumption */
+ SOCW_REG_CMP_PWR = 6, /**< 0x30C Comparator Power Enable. */
+ SOCW_REG_SLP_CFG = 7, /**< 0x550 Sleep Configuration. */
+ SOCW_REG_PMUX_PULLUP0 = 8, /**< 0x900 Pin Mux Pullup. */
+ SOCW_REG_PMUX_PULLUP1 = 9, /**< 0x904 Pin Mux Pullup. */
+ SOCW_REG_PMUX_PULLUP2 = 10, /**< 0x908 Pin Mux Pullup. */
+ SOCW_REG_PMUX_PULLUP3 = 11, /**< 0x90c Pin Mux Pullup. */
+ SOCW_REG_PMUX_SLEW0 = 12, /**< 0x910 Pin Mux Slew. */
+ SOCW_REG_PMUX_SLEW1 = 13, /**< 0x914 Pin Mux Slew. */
+ SOCW_REG_PMUX_SLEW2 = 14, /**< 0x918 Pin Mux Slew. */
+ SOCW_REG_PMUX_SLEW3 = 15, /**< 0x91c Pin Mux Slew. */
+ SOCW_REG_PMUX_IN_EN0 = 16, /**< 0x920 Pin Mux In Enable. */
+ SOCW_REG_PMUX_IN_EN1 = 17, /**< 0x924 Pin Mux In Enable. */
+ SOCW_REG_PMUX_IN_EN2 = 18, /**< 0x928 Pin Mux In Enable. */
+ SOCW_REG_PMUX_IN_EN3 = 19, /**< 0x92c Pin Mux In Enable. */
+ SOCW_REG_MAX, /**< Register enum sentinel. */
+} soc_watch_reg_t;
+#endif /* QUARK_SE */
+
+/**
+ * Log a power profile event.
+ *
+ * Log an event related to power management. This should be things like
+ * halts, or register reads which cause us to go to low power states, or
+ * register reads that affect the clock rate, or other clock gating.
+ *
+ * @param[in] event_id The Event ID of the profile event.
+ * @param[in] ev_data A parameter to the event ID (if the event needs one).
+ */
+void soc_watch_log_event(soc_watch_event_t event_id, uintptr_t ev_data);
+
+/**
+ * Log an application event via the power profile logger.
+ *
+ * This allows applications layered on top of QMSI to log their own
+ * events. The subtype identifies the type of data for the user, and
+ * 'data' is the actual information being logged.
+ *
+ * @param[in] event_id The Event ID of the profile event.
+ * @param[in] ev_subtype A 1-byte user-defined event_id.
+ * @param[in] ev_data A parameter to the event ID (if the event needs one).
+ *
+ * @returns Nothing.
+ */
+void soc_watch_log_app_event(soc_watch_event_t event_id, uint8_t ev_subtype,
+ uintptr_t ev_data);
+
+/**
+ * @}
+ */
+
+#endif /* __SOC_WATCH_H__ */
diff --git a/ext/hal/qmsi/drivers/qm_adc.c b/ext/hal/qmsi/drivers/qm_adc.c
index c65c4da2a..88195b300 100644
--- a/ext/hal/qmsi/drivers/qm_adc.c
+++ b/ext/hal/qmsi/drivers/qm_adc.c
@@ -50,7 +50,7 @@
static uint8_t sample_window[QM_ADC_NUM];
static qm_adc_resolution_t resolution[QM_ADC_NUM];
-static qm_adc_xfer_t irq_xfer[QM_ADC_NUM];
+static qm_adc_xfer_t *irq_xfer[QM_ADC_NUM];
static uint32_t count[QM_ADC_NUM];
static bool dummy_conversion = false;
@@ -79,10 +79,10 @@ static void qm_adc_isr_handler(const qm_adc_t adc)
/* Disable all interrupts. */
QM_ADC[adc].adc_intr_enable = 0;
/* Call the user callback. */
- if (irq_xfer[adc].callback) {
- irq_xfer[adc].callback(irq_xfer[adc].callback_data,
- -EIO, QM_ADC_OVERFLOW,
- QM_ADC_TRANSFER);
+ if (irq_xfer[adc]->callback) {
+ irq_xfer[adc]->callback(irq_xfer[adc]->callback_data,
+ -EIO, QM_ADC_OVERFLOW,
+ QM_ADC_TRANSFER);
}
}
@@ -94,16 +94,16 @@ static void qm_adc_isr_handler(const qm_adc_t adc)
/* Calculate the number of samples to read. */
samples_to_read = QM_ADC[adc].adc_fifo_count;
if (samples_to_read >
- (irq_xfer[adc].samples_len - count[adc])) {
+ (irq_xfer[adc]->samples_len - count[adc])) {
samples_to_read =
- irq_xfer[adc].samples_len - count[adc];
+ irq_xfer[adc]->samples_len - count[adc];
}
/* Copy data out of FIFO. The sample must be shifted right by
* 2, 4 or 6 bits for 10, 8 and 6 bit resolution respectively
* to get the correct value. */
for (i = 0; i < samples_to_read; i++) {
- irq_xfer[adc].samples[count[adc]] =
+ irq_xfer[adc]->samples[count[adc]] =
(QM_ADC[adc].adc_sample >>
(2 * (3 - resolution[adc])));
count[adc]++;
@@ -111,15 +111,15 @@ static void qm_adc_isr_handler(const qm_adc_t adc)
/* Check if we have the requested number of samples, stop the
* conversion and call the user callback function. */
- if (count[adc] == irq_xfer[adc].samples_len) {
+ if (count[adc] == irq_xfer[adc]->samples_len) {
/* Stop the transfer. */
QM_ADC[adc].adc_cmd = QM_ADC_CMD_STOP_CONT;
/* Disable all interrupts. */
QM_ADC[adc].adc_intr_enable = 0;
/* Call the user callback. */
- if (irq_xfer[adc].callback) {
- irq_xfer[adc].callback(
- irq_xfer[adc].callback_data, 0,
+ if (irq_xfer[adc]->callback) {
+ irq_xfer[adc]->callback(
+ irq_xfer[adc]->callback_data, 0,
QM_ADC_COMPLETE, QM_ADC_TRANSFER);
}
}
@@ -134,7 +134,7 @@ static void qm_adc_isr_handler(const qm_adc_t adc)
/* Call the user callback if it is set. */
if (cal_callback[adc]) {
- cal_callback[adc](irq_xfer[adc].callback_data, 0,
+ cal_callback[adc](irq_xfer[adc]->callback_data, 0,
QM_ADC_IDLE, QM_ADC_CAL_COMPLETE);
}
}
@@ -152,7 +152,7 @@ static void qm_adc_isr_handler(const qm_adc_t adc)
/* Call the user callback if it is set. */
if (mode_callback[adc]) {
- mode_callback[adc](irq_xfer[adc].callback_data, 0,
+ mode_callback[adc](irq_xfer[adc]->callback_data, 0,
QM_ADC_IDLE, QM_ADC_MODE_CHANGED);
}
}
@@ -183,7 +183,7 @@ static void qm_adc_pwr_0_isr_handler(const qm_adc_t adc)
} else {
/* Call the user callback function */
if (mode_callback[adc]) {
- mode_callback[adc](irq_xfer[adc].callback_data, 0,
+ mode_callback[adc](irq_xfer[adc]->callback_data, 0,
QM_ADC_IDLE, QM_ADC_MODE_CHANGED);
}
}
@@ -256,7 +256,7 @@ int qm_adc_irq_calibrate(const qm_adc_t adc,
cal_callback[adc] = callback;
cal_callback_data[adc] = callback_data;
- /* Clear and enable the command complete interupt. */
+ /* Clear and enable the command complete interrupt. */
QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC;
QM_ADC[adc].adc_intr_enable |= QM_ADC_INTR_ENABLE_CC;
@@ -369,7 +369,8 @@ int qm_adc_set_config(const qm_adc_t adc, const qm_adc_config_t *const cfg)
return 0;
}
-int qm_adc_convert(const qm_adc_t adc, qm_adc_xfer_t *xfer)
+int qm_adc_convert(const qm_adc_t adc, qm_adc_xfer_t *xfer,
+ qm_adc_status_t *const status)
{
uint32_t i;
@@ -399,6 +400,10 @@ int qm_adc_convert(const qm_adc_t adc, qm_adc_xfer_t *xfer)
while (QM_ADC[adc].adc_fifo_count != xfer->samples_len)
;
+ if (status) {
+ *status = QM_ADC_COMPLETE;
+ }
+
/* Read the value into the data structure. The sample must be shifted
* right by 2, 4 or 6 bits for 10, 8 and 6 bit resolution respectively
* to get the correct value. */
@@ -428,7 +433,7 @@ int qm_adc_irq_convert(const qm_adc_t adc, qm_adc_xfer_t *xfer)
setup_seq_table(adc, xfer);
/* Copy the xfer struct so we can get access from the ISR. */
- memcpy(&irq_xfer[adc], xfer, sizeof(qm_adc_xfer_t));
+ irq_xfer[adc] = xfer;
/* Clear all pending interrupts. */
QM_ADC[adc].adc_intr_status = QM_ADC_INTR_STATUS_CC |
diff --git a/ext/hal/qmsi/drivers/qm_aon_counters.c b/ext/hal/qmsi/drivers/qm_aon_counters.c
index 37f7ce75b..6a8fa2cdf 100644
--- a/ext/hal/qmsi/drivers/qm_aon_counters.c
+++ b/ext/hal/qmsi/drivers/qm_aon_counters.c
@@ -85,7 +85,7 @@ int qm_aonc_disable(const qm_scss_aon_t aonc)
return 0;
}
-int qm_aonc_get_value(const qm_scss_aon_t aonc, uint32_t * const val)
+int qm_aonc_get_value(const qm_scss_aon_t aonc, uint32_t *const val)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
QM_CHECK(val != NULL, -EINVAL);
diff --git a/ext/hal/qmsi/drivers/qm_dma.c b/ext/hal/qmsi/drivers/qm_dma.c
index d6d37db8c..65129c810 100644
--- a/ext/hal/qmsi/drivers/qm_dma.c
+++ b/ext/hal/qmsi/drivers/qm_dma.c
@@ -354,7 +354,7 @@ int qm_dma_transfer_terminate(const qm_dma_t dma,
/* The channel is disabled and the transfer complete callback is
* triggered. This callback provides the client with the data length
- * transfered before the transfer was stopped. */
+ * transferred before the transfer was stopped. */
return_code = dma_channel_disable(dma, channel_id);
if (!return_code) {
chan_cfg = &dma_channel_config[dma][channel_id];
diff --git a/ext/hal/qmsi/drivers/qm_fpr.c b/ext/hal/qmsi/drivers/qm_fpr.c
index bef9c1ccf..1af8c9442 100644
--- a/ext/hal/qmsi/drivers/qm_fpr.c
+++ b/ext/hal/qmsi/drivers/qm_fpr.c
@@ -86,6 +86,58 @@ int qm_fpr_set_config(const qm_flash_t flash, const qm_fpr_id_t id,
return 0;
}
+#if (QM_SENSOR)
+int qm_fpr_set_violation_policy(const qm_fpr_viol_mode_t mode,
+ const qm_flash_t flash,
+ qm_fpr_callback_t callback_fn, void *data)
+{
+ QM_CHECK(mode <= FPR_VIOL_MODE_PROBE, -EINVAL);
+ QM_CHECK(flash < QM_FLASH_NUM, -EINVAL);
+ volatile uint32_t *int_flash_controller_mask =
+ &QM_SCSS_INT->int_flash_controller_0_mask;
+
+ /* interrupt mode */
+ if (FPR_VIOL_MODE_INTERRUPT == mode) {
+
+ callback[flash] = callback_fn;
+ callback_data[flash] = data;
+
+ int_flash_controller_mask[flash] &=
+ ~QM_INT_FLASH_CONTROLLER_SS_MASK;
+ int_flash_controller_mask[flash] |=
+ QM_INT_FLASH_CONTROLLER_SS_HALT_MASK;
+
+ QM_SCSS_SS->ss_cfg &= ~QM_SS_STS_HALT_INTERRUPT_REDIRECTION;
+ }
+
+ /* probe or reset mode */
+ else {
+ int_flash_controller_mask[flash] |=
+ QM_INT_FLASH_CONTROLLER_SS_MASK;
+ int_flash_controller_mask[flash] &=
+ ~QM_INT_FLASH_CONTROLLER_SS_HALT_MASK;
+
+ if (FPR_VIOL_MODE_PROBE == mode) {
+
+ /* When an enabled host halt interrupt occurs, this bit
+ * determines if the interrupt event triggers a warm
+ * reset
+ * or an entry into Probe Mode.
+ * 0b : Warm Reset
+ * 1b : Probe Mode Entry
+ */
+ QM_SCSS_SS->ss_cfg |=
+ QM_SS_STS_HALT_INTERRUPT_REDIRECTION;
+ } else {
+ QM_SCSS_SS->ss_cfg &=
+ ~QM_SS_STS_HALT_INTERRUPT_REDIRECTION;
+ }
+ }
+ return 0;
+}
+
+#else /* QM_SENSOR */
+
int qm_fpr_set_violation_policy(const qm_fpr_viol_mode_t mode,
const qm_flash_t flash,
qm_fpr_callback_t callback_fn, void *data)
@@ -109,13 +161,9 @@ int qm_fpr_set_violation_policy(const qm_fpr_viol_mode_t mode,
qm_irq_unmask(QM_IRQ_FLASH_1);
#endif
}
-#if defined(QM_SENSOR)
- int_flash_controller_mask[flash] |=
- QM_INT_FLASH_CONTROLLER_SS_HALT_MASK;
-#else /* QM_SENSOR */
+
int_flash_controller_mask[flash] |=
QM_INT_FLASH_CONTROLLER_HOST_HALT_MASK;
-#endif /* QM_SENSOR */
QM_SCSS_PMU->p_sts &= ~QM_P_STS_HALT_INTERRUPT_REDIRECTION;
}
@@ -130,13 +178,9 @@ int qm_fpr_set_violation_policy(const qm_fpr_viol_mode_t mode,
qm_irq_mask(QM_IRQ_FLASH_1);
#endif
}
-#if defined(QM_SENSOR)
- int_flash_controller_mask[flash] &=
- ~QM_INT_FLASH_CONTROLLER_SS_HALT_MASK;
-#else /* QM_SENSOR */
+
int_flash_controller_mask[flash] &=
~QM_INT_FLASH_CONTROLLER_HOST_HALT_MASK;
-#endif /* QM_SENSOR */
if (FPR_VIOL_MODE_PROBE == mode) {
@@ -156,3 +200,4 @@ int qm_fpr_set_violation_policy(const qm_fpr_viol_mode_t mode,
}
return 0;
}
+#endif /* QM_SENSOR */
diff --git a/ext/hal/qmsi/drivers/qm_gpio.c b/ext/hal/qmsi/drivers/qm_gpio.c
index 667299f82..edb41ebb2 100644
--- a/ext/hal/qmsi/drivers/qm_gpio.c
+++ b/ext/hal/qmsi/drivers/qm_gpio.c
@@ -45,6 +45,25 @@ static void gpio_isr(const qm_gpio_t gpio)
{
const uint32_t int_status = QM_GPIO[gpio]->gpio_intstatus;
+#if (QUARK_D2000)
+ /*
+ * If the SoC is in deep sleep mode, all the clocks are gated, if the
+ * interrupt source is cleared before the oscillators are ungated, the
+ * oscillators return to a powered down state and the SoC will not
+ * return to an active state then.
+ */
+ if ((QM_SCSS_GP->gps1 & QM_SCSS_GP_POWER_STATES_MASK) ==
+ QM_SCSS_GP_POWER_STATE_DEEP_SLEEP) {
+ /* Return the oscillators to an active state. */
+ QM_SCSS_CCU->osc0_cfg1 &= ~QM_OSC0_PD;
+ QM_SCSS_CCU->osc1_cfg0 &= ~QM_OSC1_PD;
+
+ /* HYB_OSC_PD_LATCH_EN = 1, RTC_OSC_PD_LATCH_EN=1 */
+ QM_SCSS_CCU->ccu_lp_clk_ctl |=
+ (QM_HYB_OSC_PD_LATCH_EN | QM_RTC_OSC_PD_LATCH_EN);
+ }
+#endif
+
if (callback[gpio]) {
(*callback[gpio])(callback_data[gpio], int_status);
}
diff --git a/ext/hal/qmsi/drivers/qm_i2c.c b/ext/hal/qmsi/drivers/qm_i2c.c
index 423bcdc7a..9c51210de 100644
--- a/ext/hal/qmsi/drivers/qm_i2c.c
+++ b/ext/hal/qmsi/drivers/qm_i2c.c
@@ -37,8 +37,8 @@
#define SPK_LEN_FS_FSP (2)
/* number of retries before giving up on disabling the controller */
-#define MAX_T_POLL_COUNT (100)
-#define TI2C_POLL_MICROSECOND (10000)
+#define I2C_POLL_COUNT (1000000)
+#define I2C_POLL_MICROSECOND (1)
#ifndef UNIT_TEST
#if (QUARK_SE)
@@ -49,9 +49,9 @@ qm_i2c_reg_t *qm_i2c[QM_I2C_NUM] = {(qm_i2c_reg_t *)QM_I2C_0_BASE};
#endif
#endif
-static qm_i2c_transfer_t i2c_transfer[QM_I2C_NUM];
+static const qm_i2c_transfer_t *i2c_transfer[QM_I2C_NUM];
static uint32_t i2c_write_pos[QM_I2C_NUM], i2c_read_pos[QM_I2C_NUM],
- i2c_read_buffer_remaining[QM_I2C_NUM];
+ i2c_read_cmd_send[QM_I2C_NUM];
/**
* I2C DMA controller configuration descriptor.
@@ -61,12 +61,13 @@ typedef struct {
qm_dma_t dma_controller_id;
qm_dma_channel_id_t dma_tx_channel_id; /* TX channel ID */
qm_dma_transfer_t dma_tx_transfer_config; /* Configuration for TX */
- volatile bool ongoing_dma_tx_operation; /* Keep track of ongoing TX */
qm_dma_channel_id_t dma_rx_channel_id; /* RX channel ID */
qm_dma_transfer_t dma_rx_transfer_config; /* Configuration for RX */
/* Configuration for writing READ commands during an RX operation */
qm_dma_transfer_t dma_cmd_transfer_config;
+ volatile bool ongoing_dma_tx_operation; /* Keep track of ongoing TX */
volatile bool ongoing_dma_rx_operation; /* Keep track of oingoing RX*/
+ int multimaster_abort_status;
} i2c_dma_context_t;
/* DMA context */
@@ -96,9 +97,12 @@ static int controller_disable(const qm_i2c_t i2c);
static void qm_i2c_isr_handler(const qm_i2c_t i2c)
{
+ const qm_i2c_transfer_t *const transfer = i2c_transfer[i2c];
uint32_t ic_data_cmd = 0, count_tx = (QM_I2C_FIFO_SIZE - TX_TL);
qm_i2c_status_t status = 0;
int rc = 0;
+ uint32_t read_buffer_remaining = transfer->rx_len - i2c_read_pos[i2c];
+ uint32_t write_buffer_remaining = transfer->tx_len - i2c_write_pos[i2c];
qm_i2c_reg_t *const controller = QM_I2C[i2c];
@@ -120,12 +124,24 @@ static void qm_i2c_isr_handler(const qm_i2c_t i2c)
controller->ic_intr_mask = QM_I2C_IC_INTR_MASK_ALL;
rc = (status & QM_I2C_TX_ABRT_USER_ABRT) ? -ECANCELED : -EIO;
- if (i2c_transfer[i2c].callback) {
- /* NOTE: currently 0 is returned for length but we
- * may revisit that soon
+
+ if ((i2c_dma_context[i2c].ongoing_dma_rx_operation == true) ||
+ (i2c_dma_context[i2c].ongoing_dma_tx_operation == true)) {
+ /* If in DMA mode, raise a flag and stop the channels */
+ i2c_dma_context[i2c].multimaster_abort_status = rc;
+ /* When terminating the DMA transfer, the DMA controller
+ * calls the TX or RX callback, which will trigger the
+ * error callback. This will disable the I2C controller
*/
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data, rc, status, 0);
+ qm_i2c_dma_transfer_terminate(i2c);
+ } else {
+ if (transfer->callback) {
+ /* NOTE: currently 0 is returned for length but
+ * we may revisit that soon
+ */
+ transfer->callback(transfer->callback_data, rc,
+ status, 0);
+ }
controller_disable(i2c);
}
}
@@ -133,39 +149,38 @@ static void qm_i2c_isr_handler(const qm_i2c_t i2c)
/* RX read from buffer */
if (controller->ic_intr_stat & QM_I2C_IC_INTR_STAT_RX_FULL) {
- while (i2c_read_buffer_remaining[i2c] && controller->ic_rxflr) {
- i2c_transfer[i2c].rx[i2c_read_pos[i2c]] =
+ while (read_buffer_remaining && controller->ic_rxflr) {
+ transfer->rx[i2c_read_pos[i2c]] =
controller->ic_data_cmd;
- i2c_read_buffer_remaining[i2c]--;
+ read_buffer_remaining--;
i2c_read_pos[i2c]++;
- if (i2c_read_buffer_remaining[i2c] == 0) {
+ if (read_buffer_remaining == 0) {
/* mask rx full interrupt if transfer
* complete
*/
controller->ic_intr_mask &=
~QM_I2C_IC_INTR_MASK_RX_FULL;
- if (i2c_transfer[i2c].stop) {
+ if (transfer->stop) {
controller_disable(i2c);
}
- if (i2c_transfer[i2c].callback) {
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data, 0,
+ if (transfer->callback) {
+ transfer->callback(
+ transfer->callback_data, 0,
QM_I2C_IDLE, i2c_read_pos[i2c]);
}
}
}
- if (i2c_read_buffer_remaining[i2c] > 0 &&
- i2c_read_buffer_remaining[i2c] < (RX_TL + 1)) {
+ if (read_buffer_remaining > 0 &&
+ read_buffer_remaining < (RX_TL + 1)) {
/* Adjust the RX threshold so the next 'RX_FULL'
* interrupt is generated when all the remaining
* data are received.
*/
- controller->ic_rx_tl =
- i2c_read_buffer_remaining[i2c] - 1;
+ controller->ic_rx_tl = read_buffer_remaining - 1;
}
/* RX_FULL INTR is autocleared when the buffer
@@ -176,9 +191,8 @@ static void qm_i2c_isr_handler(const qm_i2c_t i2c)
if (controller->ic_intr_stat & QM_I2C_IC_INTR_STAT_TX_EMPTY) {
if ((controller->ic_status & QM_I2C_IC_STATUS_TFE) &&
- (i2c_transfer[i2c].tx != NULL) &&
- (i2c_transfer[i2c].tx_len == 0) &&
- (i2c_transfer[i2c].rx_len == 0)) {
+ (transfer->tx != NULL) && (write_buffer_remaining == 0) &&
+ (read_buffer_remaining == 0)) {
controller->ic_intr_mask &=
~QM_I2C_IC_INTR_MASK_TX_EMPTY;
@@ -186,33 +200,31 @@ static void qm_i2c_isr_handler(const qm_i2c_t i2c)
/* if this is not a combined
* transaction, disable the controller now
*/
- if ((i2c_read_buffer_remaining[i2c] == 0) &&
- i2c_transfer[i2c].stop) {
+ if (transfer->stop) {
controller_disable(i2c);
/* callback */
- if (i2c_transfer[i2c].callback) {
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data, 0,
+ if (transfer->callback) {
+ transfer->callback(
+ transfer->callback_data, 0,
QM_I2C_IDLE, i2c_write_pos[i2c]);
}
}
}
- while ((count_tx) && i2c_transfer[i2c].tx_len) {
+ while ((count_tx) && write_buffer_remaining) {
count_tx--;
+ write_buffer_remaining--;
/* write command -IC_DATA_CMD[8] = 0 */
/* fill IC_DATA_CMD[7:0] with the data */
- ic_data_cmd = i2c_transfer[i2c].tx[i2c_write_pos[i2c]];
- i2c_transfer[i2c].tx_len--;
+ ic_data_cmd = transfer->tx[i2c_write_pos[i2c]];
/* if transfer is a combined transfer, only
* send stop at
* end of the transfer sequence */
- if (i2c_transfer[i2c].stop &&
- (i2c_transfer[i2c].tx_len == 0) &&
- (i2c_transfer[i2c].rx_len == 0)) {
+ if (transfer->stop && (write_buffer_remaining == 0) &&
+ (read_buffer_remaining == 0)) {
ic_data_cmd |= QM_I2C_IC_DATA_CMD_STOP_BIT_CTRL;
}
@@ -230,18 +242,15 @@ static void qm_i2c_isr_handler(const qm_i2c_t i2c)
count_tx = QM_I2C_FIFO_SIZE -
(controller->ic_txflr + controller->ic_rxflr + 1);
- while (i2c_transfer[i2c].rx_len &&
- (i2c_transfer[i2c].tx_len == 0) && count_tx) {
+ while (i2c_read_cmd_send[i2c] &&
+ (write_buffer_remaining == 0) && count_tx) {
count_tx--;
- i2c_transfer[i2c].rx_len--;
+ i2c_read_cmd_send[i2c]--;
- /* if transfer is a combined transfer, only
- * send stop at
- * end of
- * the transfer sequence */
- if (i2c_transfer[i2c].stop &&
- (i2c_transfer[i2c].rx_len == 0) &&
- (i2c_transfer[i2c].tx_len == 0)) {
+ /* If transfer is a combined transfer, only send stop at
+ * end of the transfer sequence
+ */
+ if (transfer->stop && (i2c_read_cmd_send[i2c] == 0)) {
controller->ic_data_cmd =
QM_I2C_IC_DATA_CMD_READ |
QM_I2C_IC_DATA_CMD_STOP_BIT_CTRL;
@@ -252,8 +261,8 @@ static void qm_i2c_isr_handler(const qm_i2c_t i2c)
}
/* generate a tx_empty interrupt when tx fifo is fully empty */
- if ((i2c_transfer[i2c].tx_len == 0) &&
- (i2c_transfer[i2c].rx_len == 0)) {
+ if ((write_buffer_remaining == 0) &&
+ (read_buffer_remaining == 0)) {
controller->ic_tx_tl = 0;
}
}
@@ -315,7 +324,7 @@ int qm_i2c_set_config(const qm_i2c_t i2c, const qm_i2c_config_t *const cfg)
/* disable controller */
if (controller_disable(i2c)) {
- return -EAGAIN;
+ return -EBUSY;
}
switch (cfg->mode) {
@@ -430,6 +439,7 @@ int qm_i2c_set_speed(const qm_i2c_t i2c, const qm_i2c_speed_t speed,
ic_con |= QM_I2C_IC_CON_SPEED_SS;
controller->ic_ss_scl_lcnt = lo_cnt;
controller->ic_ss_scl_hcnt = hi_cnt;
+ controller->ic_fs_spklen = SPK_LEN_SS;
break;
case QM_I2C_SPEED_FAST:
@@ -437,6 +447,7 @@ int qm_i2c_set_speed(const qm_i2c_t i2c, const qm_i2c_speed_t speed,
ic_con |= QM_I2C_IC_CON_SPEED_FS_FSP;
controller->ic_fs_scl_lcnt = lo_cnt;
controller->ic_fs_scl_hcnt = hi_cnt;
+ controller->ic_fs_spklen = SPK_LEN_FS_FSP;
break;
}
@@ -517,7 +528,7 @@ int qm_i2c_master_write(const qm_i2c_t i2c, const uint16_t slave_addr,
/* disable controller */
if (true == stop) {
if (controller_disable(i2c)) {
- ret = -EIO;
+ ret = -EBUSY;
}
}
@@ -590,7 +601,7 @@ int qm_i2c_master_read(const qm_i2c_t i2c, const uint16_t slave_addr,
/* disable controller */
if (true == stop) {
if (controller_disable(i2c)) {
- ret = -EIO;
+ ret = -EBUSY;
}
}
@@ -623,8 +634,8 @@ int qm_i2c_master_irq_transfer(const qm_i2c_t i2c,
i2c_write_pos[i2c] = 0;
i2c_read_pos[i2c] = 0;
- i2c_read_buffer_remaining[i2c] = xfer->rx_len;
- memcpy(&i2c_transfer[i2c], xfer, sizeof(i2c_transfer[i2c]));
+ i2c_read_cmd_send[i2c] = xfer->rx_len;
+ i2c_transfer[i2c] = xfer;
/* set threshold */
controller->ic_tx_tl = TX_TL;
@@ -666,12 +677,15 @@ static void controller_enable(const qm_i2c_t i2c)
QM_I2C_IC_ENABLE_STATUS_IC_EN))
;
}
+
+ /* be sure that all interrupts flag are cleared */
+ controller->ic_clr_intr;
}
static int controller_disable(const qm_i2c_t i2c)
{
qm_i2c_reg_t *const controller = QM_I2C[i2c];
- int poll_count = MAX_T_POLL_COUNT;
+ int poll_count = I2C_POLL_COUNT;
/* disable controller */
controller->ic_enable &= ~QM_I2C_IC_ENABLE_CONTROLLER_EN;
@@ -679,7 +693,7 @@ static int controller_disable(const qm_i2c_t i2c)
/* wait until controller is disabled */
while ((controller->ic_enable_status & QM_I2C_IC_ENABLE_STATUS_IC_EN) &&
poll_count--) {
- clk_sys_udelay(TI2C_POLL_MICROSECOND);
+ clk_sys_udelay(I2C_POLL_MICROSECOND);
}
/* returns 0 if ok, meaning controller is disabled */
@@ -718,26 +732,18 @@ int qm_i2c_dma_transfer_terminate(const qm_i2c_t i2c)
rc = qm_dma_transfer_terminate(
i2c_dma_context[i2c].dma_controller_id,
i2c_dma_context[i2c].dma_tx_channel_id);
- /* Then disable DMA transmit */
- QM_I2C[i2c]->ic_dma_cr &= ~QM_I2C_IC_DMA_CR_TX_ENABLE;
- i2c_dma_context[i2c].ongoing_dma_tx_operation = false;
}
- if (rc == 0) {
- if (i2c_dma_context[i2c].ongoing_dma_rx_operation) {
- /* First terminate the DMA transfer */
- rc = qm_dma_transfer_terminate(
- i2c_dma_context[i2c].dma_controller_id,
- i2c_dma_context[i2c].dma_rx_channel_id);
- /* Then disable DMA receive */
- QM_I2C[i2c]->ic_dma_cr &= ~QM_I2C_IC_DMA_CR_RX_ENABLE;
- i2c_dma_context[i2c].ongoing_dma_rx_operation = false;
- }
+ if (i2c_dma_context[i2c].ongoing_dma_rx_operation) {
+ /* First terminate the DMA transfer */
+ rc |= qm_dma_transfer_terminate(
+ i2c_dma_context[i2c].dma_controller_id,
+ i2c_dma_context[i2c].dma_rx_channel_id);
}
- /* And terminate the I2C transfer */
- if (rc == 0) {
- QM_I2C[i2c]->ic_enable |= QM_I2C_IC_ENABLE_CONTROLLER_ABORT;
+ /* Check if any of the calls failed */
+ if (rc != 0) {
+ rc = -EIO;
}
return rc;
@@ -749,6 +755,7 @@ int qm_i2c_dma_transfer_terminate(const qm_i2c_t i2c)
static void i2c_dma_transfer_error_callback(uint32_t i2c, int error_code,
uint32_t len)
{
+ const qm_i2c_transfer_t *const transfer = i2c_transfer[i2c];
qm_i2c_status_t status;
if (error_code != 0) {
@@ -764,12 +771,16 @@ static void i2c_dma_transfer_error_callback(uint32_t i2c, int error_code,
i2c_dma_context[i2c].ongoing_dma_rx_operation = false;
}
+ /* Wait until the controller is done and disable it */
+ while (!(QM_I2C[i2c]->ic_status & QM_I2C_IC_STATUS_TFE)) {
+ }
+ controller_disable(i2c);
+
/* If the user has provided a callback, let's call it */
- if (i2c_transfer[i2c].callback != NULL) {
+ if (transfer->callback != NULL) {
qm_i2c_get_status(i2c, &status);
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data, error_code, status,
- len);
+ transfer->callback(transfer->callback_data, error_code,
+ status, len);
}
}
}
@@ -785,8 +796,10 @@ static void i2c_dma_transmit_callback(void *callback_context, uint32_t len,
qm_i2c_status_t status;
qm_i2c_t i2c = ((i2c_dma_context_t *)callback_context)->i2c;
+ const qm_i2c_transfer_t *const transfer = i2c_transfer[i2c];
- if (error_code == 0) {
+ if ((error_code == 0) &&
+ (i2c_dma_context[i2c].multimaster_abort_status == 0)) {
/* Disable DMA transmit */
QM_I2C[i2c]->ic_dma_cr &= ~QM_I2C_IC_DMA_CR_TX_ENABLE;
i2c_dma_context[i2c].ongoing_dma_tx_operation = false;
@@ -805,8 +818,8 @@ static void i2c_dma_transmit_callback(void *callback_context, uint32_t len,
/* Check if we must issue a stop condition and it's not
a combined transaction */
- if ((i2c_transfer[i2c].stop == true) &&
- (i2c_transfer[i2c].rx_len == 0)) {
+ if ((transfer->stop == true) &&
+ (transfer->rx_len == 0)) {
data_command |=
QM_I2C_IC_DATA_CMD_STOP_BIT_CTRL;
}
@@ -816,12 +829,12 @@ static void i2c_dma_transmit_callback(void *callback_context, uint32_t len,
/* Check if there is a pending read operation, meaning
this is a combined transaction */
- if (i2c_transfer[i2c].rx_len > 0) {
+ if (transfer->rx_len > 0) {
i2c_start_dma_read(i2c);
} else {
/* Let's disable the I2C controller if we are
done */
- if (i2c_transfer[i2c].stop == true) {
+ if (transfer->stop == true) {
/* This callback is called when DMA is
done, but I2C can still be
transmitting, so let's wait
@@ -834,15 +847,21 @@ static void i2c_dma_transmit_callback(void *callback_context, uint32_t len,
/* If user provided a callback, it'll be called
only if this is a TX only operation, not in a
combined transaction */
- if (i2c_transfer[i2c].callback != NULL) {
+ if (transfer->callback != NULL) {
qm_i2c_get_status(i2c, &status);
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data,
- error_code, status, len);
+ transfer->callback(
+ transfer->callback_data, error_code,
+ status, len);
}
}
}
} else {
+ /* If error code is 0, a multimaster arbitration loss has
+ happened, so use it as error code */
+ if (error_code == 0) {
+ error_code =
+ i2c_dma_context[i2c].multimaster_abort_status;
+ }
i2c_dma_transfer_error_callback(i2c, error_code, len);
}
}
@@ -856,26 +875,31 @@ static void i2c_dma_receive_callback(void *callback_context, uint32_t len,
qm_i2c_status_t status;
qm_i2c_t i2c = ((i2c_dma_context_t *)callback_context)->i2c;
+ const qm_i2c_transfer_t *const transfer = i2c_transfer[i2c];
- if (error_code == 0) {
+ if ((error_code == 0) &&
+ (i2c_dma_context[i2c].multimaster_abort_status == 0)) {
/* Disable DMA receive */
QM_I2C[i2c]->ic_dma_cr &= ~QM_I2C_IC_DMA_CR_RX_ENABLE;
i2c_dma_context[i2c].ongoing_dma_rx_operation = false;
/* Let's disable the I2C controller if we are done */
- if (i2c_transfer[i2c].stop == true) {
+ if (transfer->stop == true) {
controller_disable(i2c);
}
/* If the user has provided a callback, let's call it */
- if (i2c_transfer[i2c].callback != NULL) {
+ if (transfer->callback != NULL) {
qm_i2c_get_status(i2c, &status);
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data, error_code, status,
- len);
+ transfer->callback(transfer->callback_data, error_code,
+ status, len);
}
} else {
- i2c_dma_transfer_error_callback(i2c, error_code, len);
+ /* Only call the error callback on RX error. Arbitration loss
+ errors are handled on the TX callback */
+ if (error_code != 0) {
+ i2c_dma_transfer_error_callback(i2c, error_code, len);
+ }
}
}
@@ -994,18 +1018,21 @@ int qm_i2c_master_dma_transfer(const qm_i2c_t i2c,
QM_CHECK(0 == xfer->rx_len ? xfer->tx_len != 0 : 1, -EINVAL);
/* Disable all IRQs but the TX abort one */
- QM_I2C[i2c]->ic_intr_mask = QM_I2C_IC_INTR_STAT_TX_ABRT;
+ QM_I2C[i2c]->ic_intr_mask = QM_I2C_IC_INTR_MASK_TX_ABORT;
/* write slave address to TAR */
QM_I2C[i2c]->ic_tar = slave_addr;
- memcpy(&i2c_transfer[i2c], xfer, sizeof(i2c_transfer[i2c]));
+ i2c_read_cmd_send[i2c] = xfer->rx_len;
+ i2c_transfer[i2c] = xfer;
/* Set DMA TX and RX waterlevels to 0, to make sure no data is lost */
/* NOTE: This can be optimized for performance */
QM_I2C[i2c]->ic_dma_rdlr = 0;
QM_I2C[i2c]->ic_dma_tdlr = 0;
+ i2c_dma_context[i2c].multimaster_abort_status = 0;
+
/* Setup RX if something to receive */
if (xfer->rx_len > 0) {
i2c_dma_context[i2c].dma_rx_transfer_config.block_size =
diff --git a/ext/hal/qmsi/drivers/qm_interrupt.c b/ext/hal/qmsi/drivers/qm_interrupt.c
index 56061c7c0..b35ef7c8c 100644
--- a/ext/hal/qmsi/drivers/qm_interrupt.c
+++ b/ext/hal/qmsi/drivers/qm_interrupt.c
@@ -158,6 +158,16 @@ void _qm_irq_setup(uint32_t irq, uint16_t register_offset)
void _qm_register_isr(uint32_t vector, qm_isr_t isr)
{
#if (QM_SENSOR)
+ /* Invalidate the i-cache line which contains the IRQ vector. This
+ * will bypass i-cache and set vector with the good ISR. */
+ __builtin_arc_sr((uint32_t)&__ivt_vect_table[0] + (vector * 4),
+ QM_SS_AUX_IC_IVIL);
+ /* All SR accesses to the IC_IVIL register must be followed by three
+ * NOP instructions, see chapter 3.3.59 in the datasheet
+ * "ARC_V2_ProgrammersReference.pdf" */
+ __builtin_arc_nop();
+ __builtin_arc_nop();
+ __builtin_arc_nop();
__ivt_vect_table[vector] = isr;
#else
idt_set_intr_gate_desc(vector, (uint32_t)isr);
@@ -180,7 +190,7 @@ static void ss_register_irq(unsigned int vector)
/* Edge sensitive. */
__builtin_arc_sr(vector, QM_SS_AUX_IRQ_SELECT);
__builtin_arc_sr(QM_SS_IRQ_EDGE_SENSITIVE,
- QM_SS_AUX_IRQ_TRIGER);
+ QM_SS_AUX_IRQ_TRIGGER);
}
}
#endif
diff --git a/ext/hal/qmsi/drivers/qm_mailbox.c b/ext/hal/qmsi/drivers/qm_mailbox.c
index daf278190..323076870 100644
--- a/ext/hal/qmsi/drivers/qm_mailbox.c
+++ b/ext/hal/qmsi/drivers/qm_mailbox.c
@@ -131,8 +131,8 @@ int qm_mbox_ch_set_config(const qm_mbox_ch_t mbox_ch, qm_mbox_callback_t mpr_cb,
int qm_mbox_ch_write(const qm_mbox_ch_t mbox_ch,
const qm_mbox_msg_t *const data)
{
- qm_mailbox_t *const mbox_reg = (qm_mailbox_t *)QM_SCSS_MAILBOX +
- mbox_ch;
+ qm_mailbox_t *const mbox_reg =
+ (qm_mailbox_t *)QM_SCSS_MAILBOX + mbox_ch;
/* Check if the previous message has been consumed. */
if (!(mbox_reg->ch_ctrl & QM_MBOX_TRIGGER_CH_INT)) {
@@ -152,7 +152,8 @@ int qm_mbox_ch_write(const qm_mbox_ch_t mbox_ch,
int qm_mbox_ch_read(const qm_mbox_ch_t mbox_ch, qm_mbox_msg_t *const data)
{
- qm_mailbox_t *const mbox_reg = (qm_mailbox_t *)QM_SCSS_MAILBOX + mbox_ch;
+ qm_mailbox_t *const mbox_reg =
+ (qm_mailbox_t *)QM_SCSS_MAILBOX + mbox_ch;
/* Read data from the mailbox channel and clear bit 31 of the
* control word. */
@@ -176,9 +177,9 @@ int qm_mbox_ch_get_status(const qm_mbox_ch_t mbox_ch,
qm_mbox_ch_status_t *const status)
{
QM_CHECK(mbox_ch < QM_MBOX_CH_NUM, -EINVAL);
- qm_mailbox_t *const mbox_reg = (qm_mailbox_t *)QM_SCSS_MAILBOX +
- mbox_ch;
- *status = mbox_reg->ch_sts &QM_MBOX_CH_STATUS_MASK;
+ qm_mailbox_t *const mbox_reg =
+ (qm_mailbox_t *)QM_SCSS_MAILBOX + mbox_ch;
+ *status = mbox_reg->ch_sts & QM_MBOX_CH_STATUS_MASK;
return 0;
}
diff --git a/ext/hal/qmsi/drivers/qm_mpr.c b/ext/hal/qmsi/drivers/qm_mpr.c
index 2cfe868af..15a3c7a46 100644
--- a/ext/hal/qmsi/drivers/qm_mpr.c
+++ b/ext/hal/qmsi/drivers/qm_mpr.c
@@ -58,14 +58,13 @@ int qm_mpr_set_config(const qm_mpr_id_t id, const qm_mpr_config_t *const cfg)
/* MPR Upper bound 16:10 */
((cfg->up_bound & ADDRESS_MASK_7_BIT) << QM_MPR_UP_BOUND_OFFSET)
/* MPR Lower bound 6:0 */
- |
- cfg->low_bound;
+ | cfg->low_bound;
/* enable/lock */
QM_MPR->mpr_cfg[id] |= (cfg->en_lock_mask << QM_MPR_EN_LOCK_OFFSET);
return 0;
}
-
+#if (QM_SENSOR)
int qm_mpr_set_violation_policy(const qm_mpr_viol_mode_t mode,
qm_mpr_callback_t callback_fn,
void *callback_data)
@@ -77,27 +76,67 @@ int qm_mpr_set_violation_policy(const qm_mpr_viol_mode_t mode,
callback_data = callback_data;
/* unmask interrupt */
- qm_irq_unmask(QM_IRQ_SRAM);
-#if defined(QM_SENSOR)
+ QM_SCSS_INT->int_sram_controller_mask &=
+ ~QM_INT_SRAM_CONTROLLER_SS_MASK;
+
QM_SCSS_INT->int_sram_controller_mask |=
QM_INT_SRAM_CONTROLLER_SS_HALT_MASK;
-#else /* QM_SENSOR */
+
+ QM_SCSS_SS->ss_cfg &= ~QM_SS_STS_HALT_INTERRUPT_REDIRECTION;
+ }
+
+ /* probe or reset mode */
+ else {
+ /* mask interrupt */
+ QM_SCSS_INT->int_sram_controller_mask |=
+ QM_INT_SRAM_CONTROLLER_SS_MASK;
+
+ QM_SCSS_INT->int_sram_controller_mask &=
+ ~QM_INT_SRAM_CONTROLLER_SS_HALT_MASK;
+
+ if (MPR_VIOL_MODE_PROBE == mode) {
+
+ /* When an enabled host halt interrupt occurs, this bit
+ * determines if the interrupt event triggers a warm
+ * reset
+ * or an entry into Probe Mode.
+ * 0b : Warm Reset
+ * 1b : Probe Mode Entry
+ */
+ QM_SCSS_SS->ss_cfg |=
+ QM_SS_STS_HALT_INTERRUPT_REDIRECTION;
+ } else {
+ QM_SCSS_SS->ss_cfg &=
+ ~QM_SS_STS_HALT_INTERRUPT_REDIRECTION;
+ }
+ }
+ return 0;
+}
+#else
+int qm_mpr_set_violation_policy(const qm_mpr_viol_mode_t mode,
+ qm_mpr_callback_t callback_fn,
+ void *callback_data)
+{
+ QM_CHECK(mode <= MPR_VIOL_MODE_PROBE, -EINVAL);
+ /* interrupt mode */
+ if (MPR_VIOL_MODE_INTERRUPT == mode) {
+ callback = callback_fn;
+ callback_data = callback_data;
+
+ /* unmask interrupt */
+ qm_irq_unmask(QM_IRQ_SRAM);
+
QM_SCSS_INT->int_sram_controller_mask |=
QM_INT_SRAM_CONTROLLER_HOST_HALT_MASK;
-#endif /* QM_SENSOR */
}
/* probe or reset mode */
else {
/* mask interrupt */
qm_irq_mask(QM_IRQ_SRAM);
-#if defined(QM_SENSOR)
- QM_SCSS_INT->int_sram_controller_mask &=
- ~QM_INT_SRAM_CONTROLLER_SS_HALT_MASK;
-#else /* QM_SENSOR */
+
QM_SCSS_INT->int_sram_controller_mask &=
~QM_INT_SRAM_CONTROLLER_HOST_HALT_MASK;
-#endif /* QM_SENSOR */
if (MPR_VIOL_MODE_PROBE == mode) {
@@ -110,12 +149,11 @@ int qm_mpr_set_violation_policy(const qm_mpr_viol_mode_t mode,
*/
QM_SCSS_PMU->p_sts |=
QM_P_STS_HALT_INTERRUPT_REDIRECTION;
- }
-
- else {
+ } else {
QM_SCSS_PMU->p_sts &=
~QM_P_STS_HALT_INTERRUPT_REDIRECTION;
}
}
return 0;
}
+#endif /* QM_SENSOR */ \ No newline at end of file
diff --git a/ext/hal/qmsi/drivers/qm_rtc.c b/ext/hal/qmsi/drivers/qm_rtc.c
index b69e12432..6a8d9d533 100644
--- a/ext/hal/qmsi/drivers/qm_rtc.c
+++ b/ext/hal/qmsi/drivers/qm_rtc.c
@@ -37,6 +37,33 @@ QM_ISR_DECLARE(qm_rtc_isr_0)
/* Disable RTC interrupt */
QM_RTC[QM_RTC_0].rtc_ccr &= ~QM_RTC_CCR_INTERRUPT_ENABLE;
+#if (QUARK_D2000)
+ /*
+ * If the SoC is in deep sleep mode, all the clocks are gated, if the
+ * interrupt source is cleared before the oscillators are ungated, the
+ * oscillators return to a powered down state and the SoC will not
+ * return to an active state then.
+ */
+ if ((QM_SCSS_GP->gps1 & QM_SCSS_GP_POWER_STATES_MASK) ==
+ QM_SCSS_GP_POWER_STATE_DEEP_SLEEP) {
+ /* Return the oscillators to an active state. */
+ QM_SCSS_CCU->osc0_cfg1 &=
+ ~QM_OSC0_PD; /* power on the oscillator. */
+ QM_SCSS_CCU->osc1_cfg0 &=
+ ~QM_OSC1_PD; /* power on crystal oscillator. */
+
+ /*
+ * datasheet 9.1.2 Low Power State to Active
+ *
+ * FW to program HYB_OSC_PD_LATCH_EN = 1, RTC_OSC_PD_LATCH_EN=1
+ * so that OSC0_PD and OSC1_PD values directly control the
+ * oscillators in active state.
+ */
+
+ QM_SCSS_CCU->ccu_lp_clk_ctl |=
+ (QM_HYB_OSC_PD_LATCH_EN | QM_RTC_OSC_PD_LATCH_EN);
+ }
+#endif
if (callback[QM_RTC_0]) {
(callback[QM_RTC_0])(callback_data[QM_RTC_0]);
}
diff --git a/ext/hal/qmsi/drivers/qm_spi.c b/ext/hal/qmsi/drivers/qm_spi.c
index b648a05c5..1d97e7781 100644
--- a/ext/hal/qmsi/drivers/qm_spi.c
+++ b/ext/hal/qmsi/drivers/qm_spi.c
@@ -36,9 +36,17 @@
/* SPI DMA transmit watermark level. When the number of valid data entries in
* the transmit FIFO is equal to or below this field value, dma_tx_req is
- * generated. The burst length has to fit in the remaining space of the transmit
- * FIFO, i.e. the burst length cannot be bigger than (16 - watermark level). */
-#define SPI_DMATDLR_DMATDL (0x03)
+ * generated. The destination burst length has to fit in the remaining space
+ * of the transmit FIFO, thus it must be <= (SPI_FIFOS_DEPTH - TDLR).
+ * For optimal results it must be set to that delta so we can ensure the number
+ * of DMA transactions (bursts) needed are minimal, leading to a better bus
+ * utilization.
+ *
+ * With that in mind, here we choose 4 frames as a watermark level (TDLR) so we
+ * can end up with a valid value for SPI_DMA_WRITE_BURST_LENGTH of 4 frames,
+ * still adhering to the above (FIFOS_DEPTH - TDLR = 4).
+ */
+#define SPI_DMATDLR_DMATDL (0x4)
#define SPI_DMA_WRITE_BURST_LENGTH QM_DMA_BURST_TRANS_LENGTH_4
/* SPI DMA receive watermark level. When the number of valid data entries in the
@@ -50,13 +58,21 @@
* 0 1
* 3 4
* 7 (highest) 8
+ *
+ * By keeping SPI_DMA_READ_BURST_LENGTH = RDLR + 1, we have optimal results
+ * since it reduces the number of DMA transactions, leading to a better bus
+ * utilization.
+ *
+ * Note that, unlike we do for IRQ transfers, there is no need to adjust the
+ * watermark level (RDLR for DMA transfers, RXFTLR for IRQ ones) during or at
+ * the start of the DMA transaction, if rx_len < RDLR. This is done
+ * automatically
+ * by the SPI DMA interface when it decides between burst or single transactions
+ * through means of the BLOCK_TS and SRC_MSIZE ratio.
*/
#define SPI_DMARDLR_DMARDL (0x03)
#define SPI_DMA_READ_BURST_LENGTH QM_DMA_BURST_TRANS_LENGTH_4
-/* Arbitrary byte sent in RX-only mode. */
-#define SPI_RX_ONLY_DUMMY_BYTE (0xf0)
-
/* DMA transfer information, relevant on callback invocations from the DMA
* driver. */
typedef struct {
@@ -81,7 +97,7 @@ qm_spi_reg_t *qm_spi_controllers[QM_SPI_NUM] = {
static const qm_spi_async_transfer_t *spi_async_transfer[QM_SPI_NUM];
static volatile uint16_t tx_counter[QM_SPI_NUM], rx_counter[QM_SPI_NUM];
static uint8_t dfs[QM_SPI_NUM];
-static const uint32_t tx_dummy_frame = SPI_RX_ONLY_DUMMY_BYTE;
+static const uint32_t tx_dummy_frame = 0;
static qm_spi_tmode_t tmode[QM_SPI_NUM];
/* DMA (memory to SPI controller) callback information. */
static dma_context_t dma_context_tx[QM_SPI_NUM];
@@ -220,8 +236,7 @@ static void handle_spi_interrupt(const qm_spi_t spi)
if (int_status & QM_SPI_ISR_RXOIS) {
if (transfer->callback) {
transfer->callback(transfer->callback_data, -EIO,
- QM_SPI_RX_OVERFLOW,
- rx_counter[spi]);
+ QM_SPI_RX_OVERFLOW, rx_counter[spi]);
}
controller->rxoicr;
@@ -361,8 +376,6 @@ int qm_spi_transfer(const qm_spi_t spi, const qm_spi_transfer_t *const xfer,
uint8_t *rx_buffer = xfer->rx;
const uint8_t *tx_buffer = xfer->tx;
- int frames;
-
/* RX Only transfers need a dummy byte to be sent for starting.
* This is covered by the databook on page 42.
*/
@@ -381,33 +394,21 @@ int qm_spi_transfer(const qm_spi_t spi, const qm_spi_transfer_t *const xfer,
break;
}
- while (i_rx && controller->rxflr) {
+ if (i_rx && (controller->sr & QM_SPI_SR_RFNE)) {
read_frame(spi, rx_buffer);
rx_buffer += dfs[spi];
i_rx--;
}
- frames =
- SPI_FIFOS_DEPTH - controller->txflr - controller->rxflr - 1;
- while (i_tx && frames) {
+ if (i_tx && (controller->sr & QM_SPI_SR_TFNF)) {
write_frame(spi, tx_buffer);
tx_buffer += dfs[spi];
i_tx--;
- frames--;
- }
- /* Databook page 43 says we always need to busy-wait until the
- * controller is ready again after writing frames to the TX
- * FIFO.
- *
- * That is only needed for TX or TX_RX transfer modes.
- */
- if (tmode[spi] == QM_SPI_TMOD_TX_RX ||
- tmode[spi] == QM_SPI_TMOD_TX) {
- wait_for_controller(controller);
}
}
+ wait_for_controller(controller);
- controller->ssienr = 0; /** Disable SPI Device */
+ controller->ssienr = 0; /* Disable SPI Device */
return rc;
}
@@ -548,12 +549,10 @@ static void spi_dma_callback(void *callback_context, uint32_t len,
/* TX transfer. */
frames_expected = transfer->tx_len;
cb_pending_alternate_p = &dma_context_rx[spi].cb_pending;
- } else if (dma_context_p == &dma_context_rx[spi]) {
- /* RX tranfer. */
+ } else {
+ /* RX transfer. */
frames_expected = transfer->rx_len;
cb_pending_alternate_p = &dma_context_tx[spi].cb_pending;
- } else {
- return;
}
QM_ASSERT(cb_pending_alternate_p);
@@ -598,7 +597,6 @@ int qm_spi_dma_channel_config(
QM_CHECK(dma_ctrl_id < QM_DMA_NUM, -EINVAL);
QM_CHECK(dma_channel_id < QM_DMA_CHANNEL_NUM, -EINVAL);
- int ret = -EINVAL;
dma_context_t *dma_context_p = NULL;
qm_dma_channel_config_t dma_chan_cfg = {0};
dma_chan_cfg.handshake_polarity = QM_DMA_HANDSHAKE_POLARITY_HIGH;
@@ -630,21 +628,14 @@ int qm_spi_dma_channel_config(
switch (dma_channel_direction) {
case QM_DMA_MEMORY_TO_PERIPHERAL:
- switch (spi) {
- case QM_SPI_MST_0:
- dma_chan_cfg.handshake_interface =
- DMA_HW_IF_SPI_MASTER_0_TX;
- break;
+
#if (QUARK_SE)
- case QM_SPI_MST_1:
- dma_chan_cfg.handshake_interface =
- DMA_HW_IF_SPI_MASTER_1_TX;
- break;
+ dma_chan_cfg.handshake_interface =
+ (QM_SPI_MST_0 == spi) ? DMA_HW_IF_SPI_MASTER_0_TX
+ : DMA_HW_IF_SPI_MASTER_1_TX;
+#else
+ dma_chan_cfg.handshake_interface = DMA_HW_IF_SPI_MASTER_0_TX;
#endif
- default:
- /* Slave SPI is not supported. */
- return -EINVAL;
- }
/* The DMA burst length has to fit in the space remaining in the
* TX FIFO after the watermark level, DMATDLR. */
@@ -656,22 +647,14 @@ int qm_spi_dma_channel_config(
break;
case QM_DMA_PERIPHERAL_TO_MEMORY:
- switch (spi) {
- case QM_SPI_MST_0:
- dma_chan_cfg.handshake_interface =
- DMA_HW_IF_SPI_MASTER_0_RX;
- break;
+
#if (QUARK_SE)
- case QM_SPI_MST_1:
- dma_chan_cfg.handshake_interface =
- DMA_HW_IF_SPI_MASTER_1_RX;
- break;
+ dma_chan_cfg.handshake_interface =
+ (QM_SPI_MST_0 == spi) ? DMA_HW_IF_SPI_MASTER_0_RX
+ : DMA_HW_IF_SPI_MASTER_1_RX;
+#else
+ dma_chan_cfg.handshake_interface = DMA_HW_IF_SPI_MASTER_0_RX;
#endif
- default:
- /* Slave SPI is not supported. */
- return -EINVAL;
- }
-
/* The DMA burst length has to match the value of the receive
* watermark level, DMARDLR + 1. */
dma_chan_cfg.source_burst_length = SPI_DMA_READ_BURST_LENGTH;
@@ -693,12 +676,6 @@ int qm_spi_dma_channel_config(
QM_ASSERT(dma_context_p);
dma_chan_cfg.callback_context = dma_context_p;
- ret = qm_dma_channel_set_config(dma_ctrl_id, dma_channel_id,
- &dma_chan_cfg);
- if (ret) {
- return ret;
- }
-
/* To be used on received DMA callback. */
dma_context_p->spi_id = spi;
dma_context_p->dma_channel_id = dma_channel_id;
@@ -706,7 +683,8 @@ int qm_spi_dma_channel_config(
/* To be used on transfer setup. */
dma_core[spi] = dma_ctrl_id;
- return 0;
+ return qm_dma_channel_set_config(dma_ctrl_id, dma_channel_id,
+ &dma_chan_cfg);
}
int qm_spi_dma_transfer(const qm_spi_t spi,
diff --git a/ext/hal/qmsi/drivers/qm_uart.c b/ext/hal/qmsi/drivers/qm_uart.c
index eb6d94272..dea6e262e 100644
--- a/ext/hal/qmsi/drivers/qm_uart.c
+++ b/ext/hal/qmsi/drivers/qm_uart.c
@@ -47,17 +47,20 @@ typedef struct {
const qm_uart_transfer_t *xfer; /**< User transfer structure. */
} dma_context_t;
-/* UART Callback pointers. */
-static uart_client_callback_t write_callback[QM_UART_NUM];
-static uart_client_callback_t read_callback[QM_UART_NUM];
-
-/* User callback data. */
-static void *write_data[QM_UART_NUM], *read_data[QM_UART_NUM];
+/**
+ * Parameters returned by DMA driver on DMA transfer complete callback.
+ */
+typedef volatile struct {
+ void *context; /**< Pointer to dma_context_t struct. */
+ uint32_t len; /**< Amount of data successfully transferred. */
+ int error_code; /**< Error code of failed transfer. */
+} dma_callback_par_t;
/* Buffer pointers to store transmit / receive data for UART */
-static uint8_t *write_buffer[QM_UART_NUM], *read_buffer[QM_UART_NUM];
-static uint32_t write_pos[QM_UART_NUM], write_len[QM_UART_NUM];
-static uint32_t read_pos[QM_UART_NUM], read_len[QM_UART_NUM];
+static uint32_t write_pos[QM_UART_NUM];
+static uint32_t read_pos[QM_UART_NUM];
+static const qm_uart_transfer_t *uart_read_transfer[QM_UART_NUM];
+static const qm_uart_transfer_t *uart_write_transfer[QM_UART_NUM];
/* DMA (memory to UART) callback information. */
static dma_context_t dma_context_tx[QM_UART_NUM];
@@ -65,21 +68,34 @@ static dma_context_t dma_context_tx[QM_UART_NUM];
static dma_context_t dma_context_rx[QM_UART_NUM];
/* DMA core being used by each UART. */
static qm_dma_t dma_core[QM_UART_NUM];
+/* DMA callback parameters returned by DMA driver (TX transfers). */
+static dma_callback_par_t dma_delayed_callback_par[QM_UART_NUM];
static bool is_read_xfer_complete(const qm_uart_t uart)
{
- return read_pos[uart] >= read_len[uart];
+ const qm_uart_transfer_t *const transfer = uart_read_transfer[uart];
+
+ return read_pos[uart] >= transfer->data_len;
}
static bool is_write_xfer_complete(const qm_uart_t uart)
{
- return write_pos[uart] >= write_len[uart];
+ const qm_uart_transfer_t *const transfer = uart_write_transfer[uart];
+
+ return write_pos[uart] >= transfer->data_len;
}
+static void uart_client_callback(void *data, int error, qm_uart_status_t status,
+ uint32_t len);
+
static void qm_uart_isr_handler(const qm_uart_t uart)
{
qm_uart_reg_t *const regs = QM_UART[uart];
uint8_t interrupt_id = regs->iir_fcr & QM_UART_IIR_IID_MASK;
+ const qm_uart_transfer_t *const read_transfer =
+ uart_read_transfer[uart];
+ const qm_uart_transfer_t *const write_transfer =
+ uart_write_transfer[uart];
/*
* Interrupt ID priority levels (from highest to lowest):
@@ -89,6 +105,22 @@ static void qm_uart_isr_handler(const qm_uart_t uart)
*/
switch (interrupt_id) {
case QM_UART_IIR_THR_EMPTY:
+
+ if (dma_delayed_callback_par[uart].context) {
+ /*
+ * A DMA TX transfer just completed, disable interrupt
+ * and invoke client callback.
+ */
+ regs->ier_dlh &= ~QM_UART_IER_ETBEI;
+
+ uart_client_callback(
+ dma_delayed_callback_par[uart].context,
+ dma_delayed_callback_par[uart].error_code,
+ QM_UART_IDLE, dma_delayed_callback_par[uart].len);
+ dma_delayed_callback_par[uart].context = NULL;
+ return;
+ }
+
if (is_write_xfer_complete(uart)) {
regs->ier_dlh &= ~QM_UART_IER_ETBEI;
/*
@@ -99,10 +131,10 @@ static void qm_uart_isr_handler(const qm_uart_t uart)
* complete.
*/
regs->scr |= BIT(0);
- if (write_callback[uart]) {
- write_callback[uart](write_data[uart], 0,
- QM_UART_IDLE,
- write_pos[uart]);
+ if (write_transfer->callback) {
+ write_transfer->callback(
+ write_transfer->callback_data, 0,
+ QM_UART_IDLE, write_pos[uart]);
}
return;
}
@@ -116,7 +148,7 @@ static void qm_uart_isr_handler(const qm_uart_t uart)
: QM_UART_FIFO_HALF_DEPTH;
while (count-- && !is_write_xfer_complete(uart)) {
regs->rbr_thr_dll =
- write_buffer[uart][write_pos[uart]++];
+ write_transfer->data[write_pos[uart]++];
}
/*
@@ -148,14 +180,14 @@ static void qm_uart_isr_handler(const qm_uart_t uart)
* in the future.
*/
if (lsr & QM_UART_LSR_ERROR_BITS) {
- if (read_callback[uart]) {
- read_callback[uart](
- read_data[uart], -EIO,
+ if (read_transfer->callback) {
+ read_transfer->callback(
+ read_transfer->callback_data, -EIO,
lsr & QM_UART_LSR_ERROR_BITS, 0);
}
}
if (lsr & QM_UART_LSR_DR) {
- read_buffer[uart][read_pos[uart]++] =
+ read_transfer->data[read_pos[uart]++] =
regs->rbr_thr_dll;
} else {
/* No more data in the RX FIFO */
@@ -170,24 +202,24 @@ static void qm_uart_isr_handler(const qm_uart_t uart)
*/
regs->ier_dlh &=
~(QM_UART_IER_ERBFI | QM_UART_IER_ELSI);
- if (read_callback[uart]) {
- read_callback[uart](read_data[uart], 0,
- QM_UART_IDLE,
- read_pos[uart]);
+ if (read_transfer->callback) {
+ read_transfer->callback(
+ read_transfer->callback_data, 0,
+ QM_UART_IDLE, read_pos[uart]);
}
}
break;
case QM_UART_IIR_RECV_LINE_STATUS:
- if (read_callback[uart]) {
+ if (read_transfer->callback) {
/*
* NOTE: Returned len is 0 for now, this might change
* in the future.
*/
- read_callback[uart](read_data[uart], -EIO,
- regs->lsr & QM_UART_LSR_ERROR_BITS,
- 0);
+ read_transfer->callback(
+ read_transfer->callback_data, -EIO,
+ regs->lsr & QM_UART_LSR_ERROR_BITS, 0);
}
break;
}
@@ -363,10 +395,7 @@ int qm_uart_irq_write(const qm_uart_t uart,
qm_uart_reg_t *const regs = QM_UART[uart];
write_pos[uart] = 0;
- write_len[uart] = xfer->data_len;
- write_buffer[uart] = xfer->data;
- write_callback[uart] = xfer->callback;
- write_data[uart] = xfer->callback_data;
+ uart_write_transfer[uart] = xfer;
/* Set threshold */
regs->iir_fcr =
@@ -386,10 +415,7 @@ int qm_uart_irq_read(const qm_uart_t uart, const qm_uart_transfer_t *const xfer)
qm_uart_reg_t *const regs = QM_UART[uart];
read_pos[uart] = 0;
- read_len[uart] = xfer->data_len;
- read_buffer[uart] = xfer->data;
- read_callback[uart] = xfer->callback;
- read_data[uart] = xfer->callback_data;
+ uart_read_transfer[uart] = xfer;
/* Set threshold */
regs->iir_fcr =
@@ -409,14 +435,14 @@ int qm_uart_irq_write_terminate(const qm_uart_t uart)
QM_CHECK(uart < QM_UART_NUM, -EINVAL);
qm_uart_reg_t *const regs = QM_UART[uart];
+ const qm_uart_transfer_t *const transfer = uart_write_transfer[uart];
/* Disable TX holding reg empty interrupt. */
regs->ier_dlh &= ~QM_UART_IER_ETBEI;
- if (write_callback[uart]) {
- write_callback[uart](write_data[uart], -ECANCELED, QM_UART_IDLE,
- write_pos[uart]);
+ if (transfer->callback) {
+ transfer->callback(transfer->callback_data, -ECANCELED,
+ QM_UART_IDLE, write_pos[uart]);
}
- write_len[uart] = 0;
return 0;
}
@@ -426,28 +452,71 @@ int qm_uart_irq_read_terminate(const qm_uart_t uart)
QM_CHECK(uart < QM_UART_NUM, -EINVAL);
qm_uart_reg_t *const regs = QM_UART[uart];
+ const qm_uart_transfer_t *const transfer = uart_read_transfer[uart];
/*
* Disable both 'Receiver Data Available' and 'Receiver Line Status'
* interrupts.
*/
regs->ier_dlh &= ~(QM_UART_IER_ERBFI | QM_UART_IER_ELSI);
- if (read_callback[uart]) {
- read_callback[uart](read_data[uart], -ECANCELED, QM_UART_IDLE,
- read_pos[uart]);
+ if (transfer->callback) {
+ transfer->callback(transfer->callback_data, -ECANCELED,
+ QM_UART_IDLE, read_pos[uart]);
}
- read_len[uart] = 0;
return 0;
}
-/* DMA driver invoked callback. */
+/*
+ * Called by the DMA driver when the whole TX buffer has been written to the TX
+ * FIFO (write transfers) or the expected amount of data has been read from the
+ * RX FIFO (read transfers).
+ */
static void uart_dma_callback(void *callback_context, uint32_t len,
int error_code)
{
QM_ASSERT(callback_context);
- const qm_uart_transfer_t *const xfer =
- ((dma_context_t *)callback_context)->xfer;
+ /*
+ * On TX transfers, the DMA driver invokes this function as soon as all
+ * data has been written to the TX FIFO, but we still need to wait until
+ * everything has been written to the shift register (TX FIFO empty
+ * interrupt) before the client callback is invoked.
+ */
+ if (callback_context >= (void *)&dma_context_tx[0] &&
+ callback_context <= (void *)&dma_context_tx[QM_UART_NUM - 1]) {
+ /*
+ * callback_context is within dma_context_tx array so this is a
+ * TX transfer, we extract the uart index from the position in
+ * the array.
+ */
+ const qm_uart_t uart =
+ (dma_context_t *)callback_context - dma_context_tx;
+ QM_ASSERT(callback_context == (void *)&dma_context_tx[uart]);
+ qm_uart_reg_t *const regs = QM_UART[uart];
+
+ dma_delayed_callback_par[uart].context = callback_context;
+ dma_delayed_callback_par[uart].len = len;
+ dma_delayed_callback_par[uart].error_code = error_code;
+
+ /*
+ * Change the threshold level to trigger an interrupt when the
+ * TX FIFO is empty and enable the TX FIFO empty interrupt.
+ */
+ regs->iir_fcr =
+ (QM_UART_FCR_FIFOE | QM_UART_FCR_TX_0_RX_1_2_THRESHOLD);
+ regs->ier_dlh |= QM_UART_IER_ETBEI;
+ } else {
+ /* RX transfer. */
+ uart_client_callback(callback_context, error_code, QM_UART_IDLE,
+ len);
+ }
+}
+
+/* Invoke the UART client callback. */
+static void uart_client_callback(void *data, int error, qm_uart_status_t status,
+ uint32_t len)
+{
+ const qm_uart_transfer_t *const xfer = ((dma_context_t *)data)->xfer;
QM_ASSERT(xfer);
const uart_client_callback_t client_callback = xfer->callback;
void *const client_data = xfer->callback_data;
@@ -457,19 +526,19 @@ static void uart_dma_callback(void *callback_context, uint32_t len,
return;
}
- if (error_code) {
+ if (error) {
/*
* Transfer failed, pass to client the error code returned by
* the DMA driver.
*/
- client_callback(client_data, error_code, QM_UART_IDLE, 0);
+ client_callback(client_data, error, status, 0);
} else if (len == client_expected_len) {
/* Transfer completed successfully. */
- client_callback(client_data, 0, QM_UART_IDLE, len);
+ client_callback(client_data, 0, status, len);
} else {
QM_ASSERT(len < client_expected_len);
/* Transfer cancelled. */
- client_callback(client_data, -ECANCELED, QM_UART_IDLE, len);
+ client_callback(client_data, -ECANCELED, status, len);
}
}
@@ -496,16 +565,9 @@ int qm_uart_dma_channel_config(
switch (dma_channel_direction) {
case QM_DMA_MEMORY_TO_PERIPHERAL:
- switch (uart) {
- case QM_UART_0:
- dma_chan_cfg.handshake_interface = DMA_HW_IF_UART_A_TX;
- break;
- case QM_UART_1:
- dma_chan_cfg.handshake_interface = DMA_HW_IF_UART_B_TX;
- break;
- default:
- return -EINVAL;
- }
+ dma_chan_cfg.handshake_interface = (QM_UART_0 == uart)
+ ? DMA_HW_IF_UART_A_TX
+ : DMA_HW_IF_UART_B_TX;
/*
* The DMA driver needs a pointer to the DMA context structure
@@ -516,16 +578,9 @@ int qm_uart_dma_channel_config(
break;
case QM_DMA_PERIPHERAL_TO_MEMORY:
- switch (uart) {
- case QM_UART_0:
- dma_chan_cfg.handshake_interface = DMA_HW_IF_UART_A_RX;
- break;
- case QM_UART_1:
- dma_chan_cfg.handshake_interface = DMA_HW_IF_UART_B_RX;
- break;
- default:
- return -EINVAL;
- }
+ dma_chan_cfg.handshake_interface = (QM_UART_0 == uart)
+ ? DMA_HW_IF_UART_A_RX
+ : DMA_HW_IF_UART_B_RX;
/*
* The DMA driver needs a pointer to the DMA context structure
diff --git a/ext/hal/qmsi/drivers/qm_version.c b/ext/hal/qmsi/drivers/qm_version.c
index 3d580567c..f2599ea7a 100644
--- a/ext/hal/qmsi/drivers/qm_version.c
+++ b/ext/hal/qmsi/drivers/qm_version.c
@@ -33,7 +33,7 @@ uint32_t qm_ver_rom(void)
{
volatile uint32_t *ver_pointer;
- ver_pointer = (uint32_t*)ROM_VERSION_ADDRESS;
+ ver_pointer = (uint32_t *)ROM_VERSION_ADDRESS;
return *ver_pointer;
}
diff --git a/ext/hal/qmsi/drivers/qm_wdt.c b/ext/hal/qmsi/drivers/qm_wdt.c
index 783c60331..57a4ebedd 100644
--- a/ext/hal/qmsi/drivers/qm_wdt.c
+++ b/ext/hal/qmsi/drivers/qm_wdt.c
@@ -28,6 +28,7 @@
*/
#include "qm_wdt.h"
+#include "soc_watch.h"
#define QM_WDT_RELOAD_VALUE (0x76)
@@ -37,7 +38,7 @@ static void *callback_data[QM_WDT_NUM];
QM_ISR_DECLARE(qm_wdt_isr_0)
{
if (callback[QM_WDT_0]) {
- callback[QM_WDT_0](callback_data);
+ callback[QM_WDT_0](callback_data[QM_WDT_0]);
}
QM_ISR_EOI(QM_IRQ_WDT_0_VECTOR);
}
@@ -58,6 +59,8 @@ int qm_wdt_start(const qm_wdt_t wdt)
#else
#error("Unsupported / unspecified processor detected.");
#endif
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER,
+ SOCW_REG_CCU_PERIPH_CLK_GATE_CTL);
QM_SCSS_PERIPHERAL->periph_cfg0 |= BIT(1);
diff --git a/ext/hal/qmsi/drivers/sensor/include/qm_ss_adc.h b/ext/hal/qmsi/drivers/sensor/include/qm_ss_adc.h
index 0f1702377..12a66fc91 100644
--- a/ext/hal/qmsi/drivers/sensor/include/qm_ss_adc.h
+++ b/ext/hal/qmsi/drivers/sensor/include/qm_ss_adc.h
@@ -31,6 +31,7 @@
#define __QM_SS_ADC_H__
#include "qm_common.h"
+#include "qm_soc_regs.h"
#include "qm_sensor_regs.h"
/**
@@ -171,7 +172,9 @@ int qm_ss_adc_set_mode(const qm_ss_adc_t adc, const qm_ss_adc_mode_t mode);
/**
* Switch operating mode of SS ADC.
*
- * This call is non-blocking and will call the user callback on completion.
+ * This call is non-blocking and will call the user callback on completion. An
+ * interrupt will not be generated if the user requests the same mode the ADC
+ * is currently in (default mode on boot is deep power down).
*
* @param[in] adc Which ADC to enable.
* @param[in] mode ADC operating mode.
@@ -273,12 +276,14 @@ int qm_ss_adc_set_config(const qm_ss_adc_t adc,
*
* @param[in] adc Which ADC to read.
* @param[in,out] xfer Channel and sample info. This must not be NULL.
+ * @param[out] status Get status of the adc device.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
-int qm_ss_adc_convert(const qm_ss_adc_t adc, qm_ss_adc_xfer_t *const xfer);
+int qm_ss_adc_convert(const qm_ss_adc_t adc, qm_ss_adc_xfer_t *const xfer,
+ qm_ss_adc_status_t *const status);
/**
* Asynchronously read values from the SS ADC.
diff --git a/ext/hal/qmsi/drivers/sensor/include/qm_ss_gpio.h b/ext/hal/qmsi/drivers/sensor/include/qm_ss_gpio.h
index 965e31029..66e2bd6f6 100644
--- a/ext/hal/qmsi/drivers/sensor/include/qm_ss_gpio.h
+++ b/ext/hal/qmsi/drivers/sensor/include/qm_ss_gpio.h
@@ -44,7 +44,7 @@
* GPIO SS pin states.
*/
typedef enum {
- QM_SS_GPIO_LOW, /**< Pin level high. */
+ QM_SS_GPIO_LOW, /**< Pin level high. */
QM_SS_GPIO_HIGH, /**< Pin level low. */
QM_SS_GPIO_STATE_NUM
} qm_ss_gpio_state_t;
@@ -60,6 +60,7 @@ typedef struct {
uint32_t int_type; /**< Interrupt type, 0b: level; 1b: edge. */
uint32_t int_polarity; /**< Interrupt polarity, 0b: low, 1b: high. */
uint32_t int_debounce; /**< Debounce on/off. */
+
/**
* User callback.
*
@@ -95,14 +96,15 @@ int qm_ss_gpio_set_config(const qm_ss_gpio_t gpio,
*
* @param[in] gpio SS GPIO port index.
* @param[in] pin Pin of SS GPIO port to read.
- * @param[out] state QM_GPIO_LOW for low or QM_GPIO_HIGH for high. This must not be NULL.
+ * @param[out] state QM_GPIO_LOW for low or QM_GPIO_HIGH for high. This must not
+ * be NULL.
*
* @return Standard errno return type for QMSI.
* @retval 0 on success.
* @retval Negative @ref errno for possible error codes.
*/
int qm_ss_gpio_read_pin(const qm_ss_gpio_t gpio, const uint8_t pin,
- qm_ss_gpio_state_t *const state);
+ qm_ss_gpio_state_t *const state);
/**
* Set a single pin on a given SS GPIO port.
diff --git a/ext/hal/qmsi/drivers/sensor/include/qm_ss_i2c.h b/ext/hal/qmsi/drivers/sensor/include/qm_ss_i2c.h
index 1cdb8c09a..76de61fb8 100644
--- a/ext/hal/qmsi/drivers/sensor/include/qm_ss_i2c.h
+++ b/ext/hal/qmsi/drivers/sensor/include/qm_ss_i2c.h
@@ -71,32 +71,32 @@
*/
typedef enum {
QM_SS_I2C_7_BIT = 0, /**< 7-bit mode. */
- QM_SS_I2C_10_BIT /**< 10-bit mode. */
+ QM_SS_I2C_10_BIT /**< 10-bit mode. */
} qm_ss_i2c_addr_t;
/**
* QM SS I2C Speed Type.
*/
typedef enum {
- QM_SS_I2C_SPEED_STD = 1, /**< Standard mode (100 Kbps). */
- QM_SS_I2C_SPEED_FAST = 2 /**< Fast mode (400 Kbps). */
+ QM_SS_I2C_SPEED_STD = 1, /**< Standard mode (100 Kbps). */
+ QM_SS_I2C_SPEED_FAST = 2 /**< Fast mode (400 Kbps). */
} qm_ss_i2c_speed_t;
/**
* QM SS I2C status type.
*/
typedef enum {
- QM_I2C_IDLE = 0, /**< Controller idle. */
+ QM_I2C_IDLE = 0, /**< Controller idle. */
QM_I2C_TX_ABRT_7B_ADDR_NOACK = BIT(0), /**< 7-bit address noack. */
- QM_I2C_TX_ABRT_TXDATA_NOACK = BIT(3), /**< Tx data noack. */
- QM_I2C_TX_ABRT_SBYTE_ACKDET = BIT(7), /**< Start ACK. */
- QM_I2C_TX_ABRT_MASTER_DIS = BIT(11), /**< Master disabled. */
- QM_I2C_TX_ARB_LOST = BIT(12), /**< Master lost arbitration. */
+ QM_I2C_TX_ABRT_TXDATA_NOACK = BIT(3), /**< Tx data noack. */
+ QM_I2C_TX_ABRT_SBYTE_ACKDET = BIT(7), /**< Start ACK. */
+ QM_I2C_TX_ABRT_MASTER_DIS = BIT(11), /**< Master disabled. */
+ QM_I2C_TX_ARB_LOST = BIT(12), /**< Master lost arbitration. */
QM_I2C_TX_ABRT_SLVFLUSH_TXFIFO = BIT(13), /**< Slave flush tx FIFO. */
- QM_I2C_TX_ABRT_SLV_ARBLOST = BIT(14), /**< Slave lost bus. */
- QM_I2C_TX_ABRT_SLVRD_INTX = BIT(15), /**< Slave read completion. */
- QM_I2C_TX_ABRT_USER_ABRT = BIT(16), /**< User abort. */
- QM_I2C_BUSY = BIT(17) /**< Controller busy. */
+ QM_I2C_TX_ABRT_SLV_ARBLOST = BIT(14), /**< Slave lost bus. */
+ QM_I2C_TX_ABRT_SLVRD_INTX = BIT(15), /**< Slave read completion. */
+ QM_I2C_TX_ABRT_USER_ABRT = BIT(16), /**< User abort. */
+ QM_I2C_BUSY = BIT(17) /**< Controller busy. */
} qm_ss_i2c_status_t;
/**
@@ -120,6 +120,7 @@ typedef struct {
uint8_t *rx; /**< Read data. */
uint32_t rx_len; /**< Read buffer length. */
bool stop; /**< Generate master STOP. */
+
/**
* User callback.
*
@@ -230,8 +231,9 @@ int qm_ss_i2c_master_read(const qm_ss_i2c_t i2c, const uint16_t slave_addr,
*
* @param[in] i2c Which I2C to transfer from.
* @param[in] xfer Transfer structure includes write / read data and length,
- * user callback function and the callback context.
- * This must not be NULL.
+ * user callback function and the callback context.
+ * The structure must not be NULL and must be kept valid until
+ * the transfer is complete.
* @param[in] slave_addr Address of slave to transfer data with.
*
* @return Standard errno return type for QMSI.
diff --git a/ext/hal/qmsi/drivers/sensor/include/qm_ss_spi.h b/ext/hal/qmsi/drivers/sensor/include/qm_ss_spi.h
index c1f5c9321..9e0179f01 100644
--- a/ext/hal/qmsi/drivers/sensor/include/qm_ss_spi.h
+++ b/ext/hal/qmsi/drivers/sensor/include/qm_ss_spi.h
@@ -110,14 +110,16 @@ typedef enum {
/**
* SPI slave select type.
*
- * Slave selects can be combined by logical OR.
+ * Slave selects can combined by logical OR if multiple slaves are selected
+ * during one transfer. Setting only QM_SS_SPI_SS_DISABLED prevents the
+ * controller from starting the transfer.
*/
typedef enum {
- QM_SS_SPI_SS_NONE = 0, /**< No slave select. */
- QM_SS_SPI_SS_0 = BIT(0), /**< Slave select 0. */
- QM_SS_SPI_SS_1 = BIT(1), /**< Slave select 1. */
- QM_SS_SPI_SS_2 = BIT(2), /**< Slave select 2. */
- QM_SS_SPI_SS_3 = BIT(3), /**< Slave select 3. */
+ QM_SS_SPI_SS_DISABLED = 0, /**< Slave select disable. */
+ QM_SS_SPI_SS_0 = BIT(0), /**< Slave select 0. */
+ QM_SS_SPI_SS_1 = BIT(1), /**< Slave select 1. */
+ QM_SS_SPI_SS_2 = BIT(2), /**< Slave select 2. */
+ QM_SS_SPI_SS_3 = BIT(3), /**< Slave select 3. */
} qm_ss_spi_slave_select_t;
/**
@@ -169,7 +171,7 @@ typedef struct {
*/
void (*callback)(void *data, int error, qm_ss_spi_status_t status,
uint16_t len);
- void *data; /**< Callback user data. */
+ void *callback_data; /**< Callback user data. */
} qm_ss_spi_async_transfer_t;
/**
diff --git a/ext/hal/qmsi/drivers/sensor/include/qm_ss_timer.h b/ext/hal/qmsi/drivers/sensor/include/qm_ss_timer.h
index a828a4b5b..189b53d2d 100644
--- a/ext/hal/qmsi/drivers/sensor/include/qm_ss_timer.h
+++ b/ext/hal/qmsi/drivers/sensor/include/qm_ss_timer.h
@@ -44,7 +44,7 @@
* Sensor Subsystem Timer Configuration Type.
*/
typedef struct {
- bool watchdog_mode; /**< Watchdog mode. */
+ bool watchdog_mode; /**< Watchdog mode. */
/**
* Increments in run state only.
@@ -55,8 +55,9 @@ typedef struct {
* running state.
*/
bool inc_run_only;
- bool int_en; /**< Interrupt enable. */
- uint32_t count; /**< Final count value. */
+ bool int_en; /**< Interrupt enable. */
+ uint32_t count; /**< Final count value. */
+
/**
* User callback.
*
diff --git a/ext/hal/qmsi/drivers/sensor/qm_ss_adc.c b/ext/hal/qmsi/drivers/sensor/qm_ss_adc.c
index 417e8958d..b022094f7 100644
--- a/ext/hal/qmsi/drivers/sensor/qm_ss_adc.c
+++ b/ext/hal/qmsi/drivers/sensor/qm_ss_adc.c
@@ -43,11 +43,11 @@
#define QM_SS_ADC_CMD_START_CAL (3)
#define QM_SS_ADC_CMD_LOAD_CAL (4)
-/* Mode change delay is clock speed * 5. */
+/* Mode change delay is (clock speed * 5). */
#define CALCULATE_DELAY() (clk_sys_get_ticks_per_us() * 5)
static uint32_t adc_base[QM_SS_ADC_NUM] = {QM_SS_ADC_BASE};
-static qm_ss_adc_xfer_t irq_xfer[QM_SS_ADC_NUM];
+static qm_ss_adc_xfer_t *irq_xfer[QM_SS_ADC_NUM];
static uint8_t sample_window[QM_SS_ADC_NUM];
static qm_ss_adc_resolution_t resolution[QM_SS_ADC_NUM];
@@ -65,7 +65,10 @@ static void *cal_callback_data[QM_SS_ADC_NUM];
static void dummy_conversion(uint32_t controller);
-static bool first_mode_callback_ignored[QM_SS_ADC_NUM] = {false};
+/* As the mode change interrupt is always asserted when the requested mode
+ * matches the current mode, an interrupt will be triggered whenever it is
+ * unmasked, which may need to be suppressed. */
+static volatile bool ignore_spurious_interrupt[QM_SS_ADC_NUM] = {true};
static qm_ss_adc_mode_t requested_mode[QM_SS_ADC_NUM];
static void enable_adc(void)
@@ -87,8 +90,8 @@ static void qm_ss_adc_isr_handler(const qm_ss_adc_t adc)
/* Calculate the number of samples to read. */
samples_to_read = FIFO_INTERRUPT_THRESHOLD;
- if (samples_to_read > (irq_xfer[adc].samples_len - count[adc])) {
- samples_to_read = irq_xfer[adc].samples_len - count[adc];
+ if (samples_to_read > (irq_xfer[adc]->samples_len - count[adc])) {
+ samples_to_read = irq_xfer[adc]->samples_len - count[adc];
}
/* Read the samples into the array. */
@@ -97,7 +100,7 @@ static void qm_ss_adc_isr_handler(const qm_ss_adc_t adc)
QM_SS_REG_AUX_OR(controller + QM_SS_ADC_SET,
QM_SS_ADC_SET_POP_RX);
/* Read the sample in the array. */
- irq_xfer[adc].samples[count[adc]] =
+ irq_xfer[adc]->samples[count[adc]] =
(__builtin_arc_lr(controller + QM_SS_ADC_SAMPLE) >>
(ADC_SAMPLE_SHIFT - resolution[adc]));
count[adc]++;
@@ -106,7 +109,7 @@ static void qm_ss_adc_isr_handler(const qm_ss_adc_t adc)
QM_SS_REG_AUX_OR(controller + QM_SS_ADC_CTRL,
QM_SS_ADC_CTRL_CLR_DATA_A);
- if (count[adc] == irq_xfer[adc].samples_len) {
+ if (count[adc] == irq_xfer[adc]->samples_len) {
/* Stop the sequencer. */
QM_SS_REG_AUX_NAND(controller + QM_SS_ADC_CTRL,
QM_SS_ADC_CTRL_SEQ_START);
@@ -116,10 +119,10 @@ static void qm_ss_adc_isr_handler(const qm_ss_adc_t adc)
QM_SS_ADC_CTRL_MSK_ALL_INT);
/* Call the user callback. */
- if (irq_xfer[adc].callback) {
- irq_xfer[adc].callback(irq_xfer[adc].callback_data, 0,
- QM_SS_ADC_COMPLETE,
- QM_SS_ADC_TRANSFER);
+ if (irq_xfer[adc]->callback) {
+ irq_xfer[adc]->callback(irq_xfer[adc]->callback_data, 0,
+ QM_SS_ADC_COMPLETE,
+ QM_SS_ADC_TRANSFER);
}
/* Disable the ADC. */
@@ -144,24 +147,24 @@ static void qm_ss_adc_isr_err_handler(const qm_ss_adc_t adc)
/* Call the user callback and pass it the status code. */
if (intstat & QM_SS_ADC_INTSTAT_OVERFLOW) {
- if (irq_xfer[adc].callback) {
- irq_xfer[adc].callback(irq_xfer[adc].callback_data,
- -EIO, QM_SS_ADC_OVERFLOW,
- QM_SS_ADC_TRANSFER);
+ if (irq_xfer[adc]->callback) {
+ irq_xfer[adc]->callback(irq_xfer[adc]->callback_data,
+ -EIO, QM_SS_ADC_OVERFLOW,
+ QM_SS_ADC_TRANSFER);
}
}
if (intstat & QM_SS_ADC_INTSTAT_UNDERFLOW) {
- if (irq_xfer[adc].callback) {
- irq_xfer[adc].callback(irq_xfer[adc].callback_data,
- -EIO, QM_SS_ADC_UNDERFLOW,
- QM_SS_ADC_TRANSFER);
+ if (irq_xfer[adc]->callback) {
+ irq_xfer[adc]->callback(irq_xfer[adc]->callback_data,
+ -EIO, QM_SS_ADC_UNDERFLOW,
+ QM_SS_ADC_TRANSFER);
}
}
if (intstat & QM_SS_ADC_INTSTAT_SEQERROR) {
- if (irq_xfer[adc].callback) {
- irq_xfer[adc].callback(irq_xfer[adc].callback_data,
- -EIO, QM_SS_ADC_SEQERROR,
- QM_SS_ADC_TRANSFER);
+ if (irq_xfer[adc]->callback) {
+ irq_xfer[adc]->callback(irq_xfer[adc]->callback_data,
+ -EIO, QM_SS_ADC_SEQERROR,
+ QM_SS_ADC_TRANSFER);
}
}
@@ -182,8 +185,8 @@ static void qm_ss_adc_isr_pwr_handler(const qm_ss_adc_t adc)
/* The IRQ associated with the mode change fires an interrupt as soon
* as it is enabled so it is necessary to ignore it the first time the
* ISR runs. */
- if (!first_mode_callback_ignored[adc]) {
- first_mode_callback_ignored[adc] = true;
+ if (ignore_spurious_interrupt[adc]) {
+ ignore_spurious_interrupt[adc] = false;
return;
}
@@ -215,7 +218,7 @@ static void qm_ss_adc_isr_cal_handler(const qm_ss_adc_t adc)
disable_adc();
}
-/* ISR for SS ADC 0 Data avaliable. */
+/* ISR for SS ADC 0 Data available. */
QM_ISR_DECLARE(qm_ss_adc_0_isr)
{
qm_ss_adc_isr_handler(QM_SS_ADC_0);
@@ -382,12 +385,17 @@ int qm_ss_adc_set_config(const qm_ss_adc_t adc,
int qm_ss_adc_set_mode(const qm_ss_adc_t adc, const qm_ss_adc_mode_t mode)
{
- uint32_t creg, delay;
+ uint32_t creg, delay, intstat;
uint32_t controller = adc_base[adc];
QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
QM_CHECK(mode <= QM_SS_ADC_MODE_NORM_NO_CAL, -EINVAL);
+ /* Save the state of the mode interrupt mask. */
+ intstat = QM_SCSS_INT->int_adc_pwr_mask & QM_INT_ADC_PWR_MASK;
+ /* Mask the ADC mode change interrupt. */
+ QM_SCSS_INT->int_adc_pwr_mask |= QM_INT_ADC_PWR_MASK;
+
/* Calculate the delay. */
delay = CALCULATE_DELAY();
@@ -403,6 +411,12 @@ int qm_ss_adc_set_mode(const qm_ss_adc_t adc, const qm_ss_adc_mode_t mode)
QM_SS_ADC_PWR_MODE_STS)) {
}
+ /* Restore the state of the mode change interrupt mask if necessary. */
+ if (!intstat) {
+ ignore_spurious_interrupt[adc] = true;
+ QM_SCSS_INT->int_adc_pwr_mask &= ~(QM_INT_ADC_PWR_MASK);
+ }
+
/* Perform a dummy conversion if transitioning to Normal Mode. */
if ((mode >= QM_SS_ADC_MODE_NORM_CAL)) {
dummy_conversion(controller);
@@ -440,9 +454,14 @@ int qm_ss_adc_irq_set_mode(const qm_ss_adc_t adc, const qm_ss_adc_mode_t mode,
int qm_ss_adc_calibrate(const qm_ss_adc_t adc __attribute__((unused)))
{
- uint32_t creg;
+ uint32_t creg, intstat;
QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
+ /* Save the state of the calibration interrupt mask. */
+ intstat = QM_SCSS_INT->int_adc_calib_mask & QM_INT_ADC_CALIB_MASK;
+ /* Mask the ADC calibration interrupt. */
+ QM_SCSS_INT->int_adc_calib_mask |= QM_INT_ADC_CALIB_MASK;
+
/* Enable the ADC. */
enable_adc();
@@ -458,13 +477,21 @@ int qm_ss_adc_calibrate(const qm_ss_adc_t adc __attribute__((unused)))
QM_SS_ADC_CAL_ACK)) {
}
- /* Clear the calibration request reg. */
+ /* Clear the calibration request reg and wait for it to complete. */
QM_SS_REG_AUX_NAND(QM_SS_CREG_BASE + QM_SS_IO_CREG_MST0_CTRL,
QM_SS_ADC_CAL_REQ);
+ while (__builtin_arc_lr(QM_SS_CREG_BASE + QM_SS_IO_CREG_SLV0_OBSR) &
+ QM_SS_ADC_CAL_ACK) {
+ }
/* Disable the ADC. */
disable_adc();
+ /* Restore the state of the calibration interrupt mask if necessary. */
+ if (!intstat) {
+ QM_SCSS_INT->int_adc_calib_mask &= ~(QM_INT_ADC_CALIB_MASK);
+ }
+
return 0;
}
@@ -496,11 +523,16 @@ int qm_ss_adc_irq_calibrate(const qm_ss_adc_t adc,
int qm_ss_adc_set_calibration(const qm_ss_adc_t adc __attribute__((unused)),
const qm_ss_adc_calibration_t cal_data)
{
- uint32_t creg;
+ uint32_t creg, intstat;
QM_CHECK(adc < QM_SS_ADC_NUM, -EINVAL);
QM_CHECK(cal_data <= QM_SS_ADC_CAL_MAX, -EINVAL);
+ /* Save the state of the calibration interrupt mask. */
+ intstat = QM_SCSS_INT->int_adc_calib_mask & QM_INT_ADC_CALIB_MASK;
+ /* Mask the ADC calibration interrupt. */
+ QM_SCSS_INT->int_adc_calib_mask |= QM_INT_ADC_CALIB_MASK;
+
/* Issue the load calibrate command. */
creg = __builtin_arc_lr(QM_SS_CREG_BASE + QM_SS_IO_CREG_MST0_CTRL);
creg &= ~(QM_SS_ADC_CAL_VAL_SET_MASK | QM_SS_ADC_CAL_CMD_MASK |
@@ -515,9 +547,17 @@ int qm_ss_adc_set_calibration(const qm_ss_adc_t adc __attribute__((unused)),
QM_SS_ADC_CAL_ACK)) {
}
- /* Clear the calibration request reg. */
+ /* Clear the calibration request reg and wait for it to complete. */
QM_SS_REG_AUX_NAND(QM_SS_CREG_BASE + QM_SS_IO_CREG_MST0_CTRL,
QM_SS_ADC_CAL_REQ);
+ while (__builtin_arc_lr(QM_SS_CREG_BASE + QM_SS_IO_CREG_SLV0_OBSR) &
+ QM_SS_ADC_CAL_ACK) {
+ }
+
+ /* Restore the state of the calibration interrupt mask if necessary. */
+ if (!intstat) {
+ QM_SCSS_INT->int_adc_calib_mask &= ~(QM_INT_ADC_CALIB_MASK);
+ }
return 0;
}
@@ -535,7 +575,8 @@ int qm_ss_adc_get_calibration(const qm_ss_adc_t adc __attribute__((unused)),
return 0;
}
-int qm_ss_adc_convert(const qm_ss_adc_t adc, qm_ss_adc_xfer_t *xfer)
+int qm_ss_adc_convert(const qm_ss_adc_t adc, qm_ss_adc_xfer_t *xfer,
+ qm_ss_adc_status_t *const status)
{
uint32_t reg, i;
uint32_t controller = adc_base[adc];
@@ -581,6 +622,9 @@ int qm_ss_adc_convert(const qm_ss_adc_t adc, qm_ss_adc_xfer_t *xfer)
/* Return if we get an error (UNDERFLOW, OVERFLOW, SEQ_ERROR). */
if (res > 1) {
+ if (status) {
+ *status = res;
+ }
return -EIO;
}
@@ -625,7 +669,7 @@ int qm_ss_adc_irq_convert(const qm_ss_adc_t adc, qm_ss_adc_xfer_t *xfer)
setup_seq_table(adc, xfer, false);
/* Copy the xfer struct so we can get access from the ISR. */
- memcpy(&irq_xfer[adc], xfer, sizeof(qm_ss_adc_xfer_t));
+ irq_xfer[adc] = xfer;
/* Set count back to 0. */
count[adc] = 0;
diff --git a/ext/hal/qmsi/drivers/sensor/qm_ss_gpio.c b/ext/hal/qmsi/drivers/sensor/qm_ss_gpio.c
index e0b693ffd..38b75858e 100644
--- a/ext/hal/qmsi/drivers/sensor/qm_ss_gpio.c
+++ b/ext/hal/qmsi/drivers/sensor/qm_ss_gpio.c
@@ -125,7 +125,7 @@ int qm_ss_gpio_clear_pin(const qm_ss_gpio_t gpio, const uint8_t pin)
}
int qm_ss_gpio_set_pin_state(const qm_ss_gpio_t gpio, const uint8_t pin,
- const qm_ss_gpio_state_t state)
+ const qm_ss_gpio_state_t state)
{
uint32_t val;
QM_CHECK(gpio < QM_SS_GPIO_NUM, -EINVAL);
diff --git a/ext/hal/qmsi/drivers/sensor/qm_ss_i2c.c b/ext/hal/qmsi/drivers/sensor/qm_ss_i2c.c
index ddc260edb..5615eb72b 100644
--- a/ext/hal/qmsi/drivers/sensor/qm_ss_i2c.c
+++ b/ext/hal/qmsi/drivers/sensor/qm_ss_i2c.c
@@ -26,14 +26,19 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
+#include <string.h>
+#include "qm_ss_i2c.h"
+#include "clk.h"
+
#define SPK_LEN_SS (1)
#define SPK_LEN_FS (2)
#define TX_TL (2)
#define RX_TL (5)
-#include <string.h>
-#include "qm_ss_i2c.h"
-#include "clk.h"
+/* number of retries before giving up on disabling the controller */
+#define I2C_POLL_COUNT (1000000)
+#define I2C_POLL_MICROSECOND (1)
/*
* NOTE: There are a number of differences between this Sensor Subsystem I2C
@@ -59,19 +64,22 @@
*/
static uint32_t i2c_base[QM_SS_I2C_NUM] = {QM_SS_I2C_0_BASE, QM_SS_I2C_1_BASE};
-static qm_ss_i2c_transfer_t i2c_transfer[QM_SS_I2C_NUM];
+static const qm_ss_i2c_transfer_t *i2c_transfer[QM_SS_I2C_NUM];
static uint32_t i2c_write_pos[QM_SS_I2C_NUM], i2c_read_pos[QM_SS_I2C_NUM],
- i2c_read_buffer_remaining[QM_SS_I2C_NUM];
+ i2c_read_cmd_send[QM_SS_I2C_NUM];
static void controller_enable(const qm_ss_i2c_t i2c);
-static void controller_disable(const qm_ss_i2c_t i2c);
+static int controller_disable(const qm_ss_i2c_t i2c);
static void qm_ss_i2c_isr_handler(const qm_ss_i2c_t i2c)
{
+ const qm_ss_i2c_transfer_t *const transfer = i2c_transfer[i2c];
uint32_t controller = i2c_base[i2c], data_cmd = 0,
count_tx = (QM_SS_I2C_FIFO_SIZE - TX_TL);
qm_ss_i2c_status_t status = 0;
int rc = 0;
+ uint32_t read_buffer_remaining = transfer->rx_len - i2c_read_pos[i2c];
+ uint32_t write_buffer_remaining = transfer->tx_len - i2c_write_pos[i2c];
/* Check for errors */
QM_ASSERT(!(__builtin_arc_lr(controller + QM_SS_I2C_INTR_STAT) &
@@ -101,27 +109,29 @@ static void qm_ss_i2c_isr_handler(const qm_ss_i2c_t i2c)
rc = (status & QM_I2C_TX_ABRT_USER_ABRT) ? -ECANCELED : -EIO;
- if (i2c_transfer[i2c].callback) {
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data, rc, status, 0);
+ if (i2c_transfer[i2c]->callback) {
+ i2c_transfer[i2c]->callback(
+ i2c_transfer[i2c]->callback_data, rc, status, 0);
}
+
+ controller_disable(i2c);
}
/* RX read from buffer */
if ((__builtin_arc_lr(controller + QM_SS_I2C_INTR_STAT) &
QM_SS_I2C_INTR_STAT_RX_FULL)) {
- while (i2c_read_buffer_remaining[i2c] &&
+ while (read_buffer_remaining &&
(__builtin_arc_lr(controller + QM_SS_I2C_RXFLR))) {
__builtin_arc_sr(QM_SS_I2C_DATA_CMD_POP,
controller + QM_SS_I2C_DATA_CMD);
/* IC_DATA_CMD[7:0] contains received data */
- i2c_transfer[i2c].rx[i2c_read_pos[i2c]] =
+ i2c_transfer[i2c]->rx[i2c_read_pos[i2c]] =
__builtin_arc_lr(controller + QM_SS_I2C_DATA_CMD);
- i2c_read_buffer_remaining[i2c]--;
+ read_buffer_remaining--;
i2c_read_pos[i2c]++;
- if (i2c_read_buffer_remaining[i2c] == 0) {
+ if (read_buffer_remaining == 0) {
/* mask rx full interrupt if transfer
* complete
*/
@@ -129,19 +139,19 @@ static void qm_ss_i2c_isr_handler(const qm_ss_i2c_t i2c)
(controller + QM_SS_I2C_INTR_MASK),
QM_SS_I2C_INTR_MASK_RX_FULL);
- if (i2c_transfer[i2c].stop) {
+ if (i2c_transfer[i2c]->stop) {
controller_disable(i2c);
}
- if (i2c_transfer[i2c].callback) {
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data, 0,
+ if (i2c_transfer[i2c]->callback) {
+ i2c_transfer[i2c]->callback(
+ i2c_transfer[i2c]->callback_data, 0,
QM_I2C_IDLE, i2c_read_pos[i2c]);
}
}
}
- if (i2c_read_buffer_remaining[i2c] > 0 &&
- i2c_read_buffer_remaining[i2c] < (RX_TL + 1)) {
+ if (read_buffer_remaining > 0 &&
+ read_buffer_remaining < (RX_TL + 1)) {
/* Adjust the RX threshold so the next 'RX_FULL'
* interrupt is generated when all the remaining
* data are received.
@@ -149,7 +159,7 @@ static void qm_ss_i2c_isr_handler(const qm_ss_i2c_t i2c)
QM_SS_REG_AUX_NAND((controller + QM_SS_I2C_TL),
QM_SS_I2C_TL_RX_TL_MASK);
QM_SS_REG_AUX_OR((controller + QM_SS_I2C_TL),
- (i2c_read_buffer_remaining[i2c] - 1));
+ (read_buffer_remaining - 1));
}
/* RX_FULL INTR is autocleared when the buffer
@@ -162,9 +172,9 @@ static void qm_ss_i2c_isr_handler(const qm_ss_i2c_t i2c)
if ((__builtin_arc_lr(controller + QM_SS_I2C_STATUS) &
QM_SS_I2C_STATUS_TFE) &&
- (i2c_transfer[i2c].tx != NULL) &&
- (i2c_transfer[i2c].tx_len == 0) &&
- (i2c_transfer[i2c].rx_len == 0)) {
+ (i2c_transfer[i2c]->tx != NULL) &&
+ (write_buffer_remaining == 0) &&
+ (read_buffer_remaining == 0)) {
QM_SS_REG_AUX_NAND((controller + QM_SS_I2C_INTR_MASK),
QM_SS_I2C_INTR_MASK_TX_EMPTY);
@@ -172,34 +182,33 @@ static void qm_ss_i2c_isr_handler(const qm_ss_i2c_t i2c)
/* if this is not a combined
* transaction, disable the controller now
*/
- if ((i2c_read_buffer_remaining[i2c] == 0) &&
- i2c_transfer[i2c].stop) {
+ if (i2c_transfer[i2c]->stop) {
controller_disable(i2c);
/* callback */
- if (i2c_transfer[i2c].callback) {
- i2c_transfer[i2c].callback(
- i2c_transfer[i2c].callback_data, 0,
- QM_I2C_IDLE, i2c_write_pos[i2c]);
+ if (i2c_transfer[i2c]->callback) {
+ i2c_transfer[i2c]->callback(
+ i2c_transfer[i2c]->callback_data, 0,
+ QM_I2C_IDLE, i2c_write_pos[i2c]);
}
}
}
- while ((count_tx) && i2c_transfer[i2c].tx_len) {
+ while ((count_tx) && write_buffer_remaining) {
count_tx--;
+ write_buffer_remaining--;
/* write command -IC_DATA_CMD[8] = 0 */
/* fill IC_DATA_CMD[7:0] with the data */
data_cmd = QM_SS_I2C_DATA_CMD_PUSH |
- i2c_transfer[i2c].tx[i2c_write_pos[i2c]];
- i2c_transfer[i2c].tx_len--;
+ i2c_transfer[i2c]->tx[i2c_write_pos[i2c]];
/* if transfer is a combined transfer, only
* send stop at
* end of the transfer sequence */
- if (i2c_transfer[i2c].stop &&
- (i2c_transfer[i2c].tx_len == 0) &&
- (i2c_transfer[i2c].rx_len == 0)) {
+ if (i2c_transfer[i2c]->stop &&
+ (read_buffer_remaining == 0) &&
+ (write_buffer_remaining == 0)) {
data_cmd |= QM_SS_I2C_DATA_CMD_STOP;
}
@@ -220,18 +229,17 @@ static void qm_ss_i2c_isr_handler(const qm_ss_i2c_t i2c)
(__builtin_arc_lr(controller + QM_SS_I2C_TXFLR) +
(__builtin_arc_lr(controller + QM_SS_I2C_RXFLR) + 1));
- while (i2c_transfer[i2c].rx_len &&
- (i2c_transfer[i2c].tx_len == 0) && count_tx) {
+ while (i2c_read_cmd_send[i2c] &&
+ (write_buffer_remaining == 0) && count_tx) {
count_tx--;
- i2c_transfer[i2c].rx_len--;
+ i2c_read_cmd_send[i2c]--;
/* if transfer is a combined transfer, only
* send stop at
* end of
* the transfer sequence */
- if (i2c_transfer[i2c].stop &&
- (i2c_transfer[i2c].rx_len == 0) &&
- (i2c_transfer[i2c].tx_len == 0)) {
+ if (i2c_transfer[i2c]->stop &&
+ (i2c_read_cmd_send[i2c] == 0)) {
__builtin_arc_sr((QM_SS_I2C_DATA_CMD_CMD |
QM_SS_I2C_DATA_CMD_PUSH |
@@ -249,8 +257,8 @@ static void qm_ss_i2c_isr_handler(const qm_ss_i2c_t i2c)
/* generate a tx_empty interrupt when tx fifo is fully
* empty */
- if ((i2c_transfer[i2c].tx_len == 0) &&
- (i2c_transfer[i2c].rx_len == 0)) {
+ if ((write_buffer_remaining == 0) &&
+ (read_buffer_remaining == 0)) {
QM_SS_REG_AUX_NAND((controller + QM_SS_I2C_TL),
QM_SS_I2C_TL_TX_TL_MASK);
}
@@ -297,7 +305,9 @@ int qm_ss_i2c_set_config(const qm_ss_i2c_t i2c,
controller + QM_SS_I2C_INTR_MASK);
/* disable controller */
- controller_disable(i2c);
+ if (controller_disable(i2c)) {
+ return -EBUSY;
+ }
/* set mode */
con |= QM_SS_I2C_CON_RESTART_EN |
@@ -379,7 +389,7 @@ int qm_ss_i2c_set_speed(const qm_ss_i2c_t i2c, const qm_ss_i2c_speed_t speed,
lo_cnt > QM_SS_I2C_IC_LCNT_MIN,
-EINVAL);
- con &= ~QM_SS_I2C_CON_SPEED_MASK;
+ con &= ~(QM_SS_I2C_CON_SPEED_MASK | QM_SS_I2C_CON_SPKLEN_MASK);
full_cnt = (lo_cnt & QM_SS_I2C_SS_FS_SCL_CNT_16BIT_MASK) |
(hi_cnt & QM_SS_I2C_SS_FS_SCL_CNT_16BIT_MASK)
@@ -387,12 +397,14 @@ int qm_ss_i2c_set_speed(const qm_ss_i2c_t i2c, const qm_ss_i2c_speed_t speed,
switch (speed) {
case QM_SS_I2C_SPEED_STD:
- con |= QM_SS_I2C_CON_SPEED_SS;
+ con |= (QM_SS_I2C_CON_SPEED_SS |
+ (SPK_LEN_SS << QM_SS_I2C_CON_SPKLEN_OFFSET));
__builtin_arc_sr(full_cnt, controller + QM_SS_I2C_SS_SCL_CNT);
break;
case QM_SS_I2C_SPEED_FAST:
- con |= QM_SS_I2C_CON_SPEED_FS;
+ con |= (QM_SS_I2C_CON_SPEED_FS |
+ (SPK_LEN_FS << QM_SS_I2C_CON_SPKLEN_OFFSET));
__builtin_arc_sr(full_cnt, controller + QM_SS_I2C_FS_SCL_CNT);
break;
}
@@ -480,7 +492,9 @@ int qm_ss_i2c_master_write(const qm_ss_i2c_t i2c, const uint16_t slave_addr,
/* disable controller */
if (true == stop) {
- controller_disable(i2c);
+ if (controller_disable(i2c)) {
+ ret = -EBUSY;
+ }
}
if (status != NULL) {
@@ -550,7 +564,8 @@ int qm_ss_i2c_master_read(const qm_ss_i2c_t i2c, const uint16_t slave_addr,
/* wait until rx fifo is empty, indicating pop is complete*/
while ((__builtin_arc_lr(controller + QM_SS_I2C_STATUS) &
- QM_SS_I2C_STATUS_RFNE));
+ QM_SS_I2C_STATUS_RFNE))
+ ;
/* IC_DATA_CMD[7:0] contains received data */
*d = __builtin_arc_lr(controller + QM_SS_I2C_DATA_CMD);
@@ -559,7 +574,9 @@ int qm_ss_i2c_master_read(const qm_ss_i2c_t i2c, const uint16_t slave_addr,
/* disable controller */
if (true == stop) {
- controller_disable(i2c);
+ if (controller_disable(i2c)) {
+ ret = -EBUSY;
+ }
}
if (status != NULL) {
@@ -595,8 +612,8 @@ int qm_ss_i2c_master_irq_transfer(const qm_ss_i2c_t i2c,
i2c_write_pos[i2c] = 0;
i2c_read_pos[i2c] = 0;
- i2c_read_buffer_remaining[i2c] = xfer->rx_len;
- memcpy(&i2c_transfer[i2c], xfer, sizeof(i2c_transfer[i2c]));
+ i2c_read_cmd_send[i2c] = xfer->rx_len;
+ i2c_transfer[i2c] = xfer;
/* set threshold */
if (xfer->rx_len > 0 && xfer->rx_len < (RX_TL + 1)) {
@@ -643,22 +660,30 @@ static void controller_enable(const qm_ss_i2c_t i2c)
QM_SS_I2C_ENABLE_STATUS_IC_EN))
;
}
+
+ /* Clear all interruption flags */
+ __builtin_arc_sr(QM_SS_I2C_INTR_CLR_ALL,
+ controller + QM_SS_I2C_INTR_CLR);
}
-static void controller_disable(const qm_ss_i2c_t i2c)
+static int controller_disable(const qm_ss_i2c_t i2c)
{
uint32_t controller = i2c_base[i2c];
- if (__builtin_arc_lr(controller + QM_SS_I2C_ENABLE_STATUS) &
- QM_SS_I2C_ENABLE_STATUS_IC_EN) {
- /* disable controller */
- QM_SS_REG_AUX_NAND((controller + QM_SS_I2C_CON),
- QM_SS_I2C_CON_ENABLE);
-
- /* wait until controller is disabled */
- while ((__builtin_arc_lr(controller + QM_SS_I2C_ENABLE_STATUS) &
- QM_SS_I2C_ENABLE_STATUS_IC_EN))
- ;
+ int poll_count = I2C_POLL_COUNT;
+
+ /* disable controller */
+ QM_SS_REG_AUX_NAND((controller + QM_SS_I2C_CON), QM_SS_I2C_CON_ENABLE);
+
+ /* wait until controller is disabled */
+ while ((__builtin_arc_lr(controller + QM_SS_I2C_ENABLE_STATUS) &
+ QM_SS_I2C_ENABLE_STATUS_IC_EN) &&
+ poll_count--) {
+ clk_sys_udelay(I2C_POLL_MICROSECOND);
}
+
+ /* returns 0 if ok, meaning controller is disabled */
+ return (__builtin_arc_lr(controller + QM_SS_I2C_ENABLE_STATUS) &
+ QM_SS_I2C_ENABLE_STATUS_IC_EN);
}
int qm_ss_i2c_irq_transfer_terminate(const qm_ss_i2c_t i2c)
diff --git a/ext/hal/qmsi/drivers/sensor/qm_ss_spi.c b/ext/hal/qmsi/drivers/sensor/qm_ss_spi.c
index 8fb116b32..9beba4303 100644
--- a/ext/hal/qmsi/drivers/sensor/qm_ss_spi.c
+++ b/ext/hal/qmsi/drivers/sensor/qm_ss_spi.c
@@ -38,13 +38,11 @@
static uint32_t base[QM_SS_SPI_NUM] = {QM_SS_SPI_0_BASE, QM_SS_SPI_1_BASE};
-static const qm_ss_spi_async_transfer_t *transfer[QM_SS_SPI_NUM];
+static const qm_ss_spi_async_transfer_t *spi_async_transfer[QM_SS_SPI_NUM];
static uint32_t rx_c[QM_SS_SPI_NUM];
static uint32_t tx_c[QM_SS_SPI_NUM];
-static uint8_t *rx_p[QM_SS_SPI_NUM];
-static uint8_t *tx_p[QM_SS_SPI_NUM];
-static uint16_t dummy_frame;
+static const uint16_t dummy_frame = 0;
/* Private Functions */
static void spi_disable(const qm_ss_spi_t spi)
@@ -57,7 +55,7 @@ static void spi_disable(const qm_ss_spi_t spi)
__builtin_arc_sr(QM_SS_SPI_INTR_ALL, base[spi] + QM_SS_SPI_CLR_INTR);
}
-static __inline__ void fifo_write(const qm_ss_spi_t spi, void *data,
+static __inline__ void fifo_write(const qm_ss_spi_t spi, const void *data,
uint8_t size)
{
uint32_t dr;
@@ -211,7 +209,7 @@ int qm_ss_spi_transfer(const qm_ss_spi_t spi,
tx_cnt--;
}
}
- /* Wait for last byte transfered */
+ /* Wait for last byte transferred */
while (__builtin_arc_lr(base[spi] + QM_SS_SPI_SR) & QM_SS_SPI_SR_BUSY)
;
@@ -231,20 +229,22 @@ int qm_ss_spi_irq_transfer(const qm_ss_spi_t spi,
uint32_t ctrl = __builtin_arc_lr(base[spi] + QM_SS_SPI_CTRL);
uint8_t tmode = (uint8_t)((ctrl & QM_SS_SPI_CTRL_TMOD_MASK) >>
QM_SS_SPI_CTRL_TMOD_OFFS);
+ uint8_t bytes = BYTES_PER_FRAME(ctrl);
QM_CHECK(tmode == QM_SS_SPI_TMOD_TX_RX ? (xfer->tx_len == xfer->rx_len)
: 1,
-EINVAL);
- transfer[spi] = xfer;
+ spi_async_transfer[spi] = xfer;
tx_c[spi] = xfer->tx_len;
rx_c[spi] = xfer->rx_len;
- tx_p[spi] = xfer->tx;
- rx_p[spi] = xfer->rx;
- /* RX only transfers need a dummy frame byte to be sent. */
- if (tmode == QM_SS_SPI_TMOD_RX) {
- tx_p[spi] = (uint8_t *)&dummy_frame;
- tx_c[spi] = 1;
+
+ /* Set NDF (Number of Data Frames) in RX or EEPROM Read mode. (-1) */
+ if (tmode == QM_SS_SPI_TMOD_RX || tmode == QM_SS_SPI_TMOD_EEPROM_READ) {
+ ctrl &= ~QM_SS_SPI_CTRL_NDF_MASK;
+ ctrl |= ((xfer->rx_len - 1) << QM_SS_SPI_CTRL_NDF_OFFS) &
+ QM_SS_SPI_CTRL_NDF_MASK;
+ __builtin_arc_sr(ctrl, base[spi] + QM_SS_SPI_CTRL);
}
uint32_t ftlr =
@@ -256,35 +256,44 @@ int qm_ss_spi_irq_transfer(const qm_ss_spi_t spi,
/* Unmask all interrupts */
__builtin_arc_sr(QM_SS_SPI_INTR_ALL, base[spi] + QM_SS_SPI_INTR_MASK);
+
/* Enable SPI device */
QM_SS_REG_AUX_OR(base[spi] + QM_SS_SPI_SPIEN, QM_SS_SPI_SPIEN_EN);
+ /* RX only transfers need a dummy frame byte to be sent. */
+ if (tmode == QM_SS_SPI_TMOD_RX) {
+ fifo_write(spi, (uint8_t *)&dummy_frame, bytes);
+ }
+
return 0;
}
int qm_ss_spi_transfer_terminate(const qm_ss_spi_t spi)
{
QM_CHECK(spi < QM_SS_SPI_NUM, -EINVAL);
+ const qm_ss_spi_async_transfer_t *const transfer =
+ spi_async_transfer[spi];
+
spi_disable(spi);
- if (transfer[spi]->callback) {
+ if (transfer->callback) {
uint32_t len = 0;
uint32_t ctrl = __builtin_arc_lr(base[spi] + QM_SS_SPI_CTRL);
uint8_t tmode = (uint8_t)((ctrl & QM_SS_SPI_CTRL_TMOD_MASK) >>
QM_SS_SPI_CTRL_TMOD_OFFS);
if (tmode == QM_SS_SPI_TMOD_TX ||
tmode == QM_SS_SPI_TMOD_TX_RX) {
- len = transfer[spi]->tx_len - tx_c[spi];
+ len = transfer->tx_len - tx_c[spi];
} else {
- len = transfer[spi]->rx_len - rx_c[spi];
+ len = transfer->rx_len - rx_c[spi];
}
/*
* NOTE: change this to return controller-specific code
* 'user aborted'.
*/
- transfer[spi]->callback(transfer[spi]->data, -ECANCELED,
- QM_SS_SPI_IDLE, (uint16_t)len);
+ transfer->callback(transfer->callback_data, -ECANCELED,
+ QM_SS_SPI_IDLE, (uint16_t)len);
}
return 0;
@@ -293,14 +302,17 @@ int qm_ss_spi_transfer_terminate(const qm_ss_spi_t spi)
static void handle_spi_err_interrupt(const qm_ss_spi_t spi)
{
uint32_t intr_stat = __builtin_arc_lr(base[spi] + QM_SS_SPI_INTR_STAT);
+ const qm_ss_spi_async_transfer_t *const transfer =
+ spi_async_transfer[spi];
+
spi_disable(spi);
- QM_ASSERT((intr_stat &
- (QM_SS_SPI_INTR_STAT_TXOI | QM_SS_SPI_INTR_STAT_RXFI)) == 0);
+ QM_ASSERT((intr_stat & QM_SS_SPI_INTR_STAT_TXOI) == 0);
+ QM_ASSERT((intr_stat & QM_SS_SPI_INTR_STAT_RXUI) == 0);
- if ((intr_stat & QM_SS_SPI_INTR_RXOI) && transfer[spi]->callback) {
- transfer[spi]->callback(transfer[spi]->data, -EIO,
- QM_SS_SPI_RX_OVERFLOW,
- transfer[spi]->rx_len - rx_c[spi]);
+ if ((intr_stat & QM_SS_SPI_INTR_RXOI) && transfer->callback) {
+ transfer->callback(transfer->callback_data, -EIO,
+ QM_SS_SPI_RX_OVERFLOW,
+ transfer->rx_len - rx_c[spi]);
}
}
@@ -314,14 +326,24 @@ static void handle_spi_tx_interrupt(const qm_ss_spi_t spi)
uint8_t bytes = BYTES_PER_FRAME(ctrl);
uint8_t tmode = (uint8_t)((ctrl & QM_SS_SPI_CTRL_TMOD_MASK) >>
QM_SS_SPI_CTRL_TMOD_OFFS);
+ const qm_ss_spi_async_transfer_t *const transfer =
+ spi_async_transfer[spi];
+
+ /* Jump to the right position of TX buffer.
+ * If no bytes were transmitted before, we start from the beginning,
+ * otherwise we jump to the next frame to be sent.
+ */
+ const uint8_t *tx_buffer =
+ transfer->tx + ((transfer->tx_len - tx_c[spi]) * bytes);
+
if (tx_c[spi] == 0 &&
!(__builtin_arc_lr(base[spi] + QM_SS_SPI_SR) & QM_SS_SPI_SR_BUSY)) {
if (tmode == QM_SS_SPI_TMOD_TX) {
spi_disable(spi);
- if (transfer[spi]->callback) {
- transfer[spi]->callback(transfer[spi]->data, 0,
- QM_SS_SPI_IDLE,
- transfer[spi]->tx_len);
+ if (transfer->callback) {
+ transfer->callback(transfer->callback_data, 0,
+ QM_SS_SPI_IDLE,
+ transfer->tx_len);
}
} else {
QM_SS_REG_AUX_NAND(base[spi] + QM_SS_SPI_INTR_MASK,
@@ -334,8 +356,8 @@ static void handle_spi_tx_interrupt(const qm_ss_spi_t spi)
uint32_t txflr = __builtin_arc_lr(base[spi] + QM_SS_SPI_TXFLR);
int32_t cnt = FIFO_SIZE - rxflr - txflr - 1;
while (tx_c[spi] && cnt > 0) {
- fifo_write(spi, tx_p[spi], bytes);
- tx_p[spi] += bytes;
+ fifo_write(spi, tx_buffer, bytes);
+ tx_buffer += bytes;
tx_c[spi]--;
cnt--;
}
@@ -349,10 +371,21 @@ static void handle_spi_rx_interrupt(const qm_ss_spi_t spi)
uint32_t ctrl = __builtin_arc_lr(base[spi] + QM_SS_SPI_CTRL);
/* Calculate number of bytes per frame (1 or 2)*/
uint8_t bytes = BYTES_PER_FRAME(ctrl);
+ const qm_ss_spi_async_transfer_t *const transfer =
+ spi_async_transfer[spi];
+
+ /*
+ * Jump to the right position of RX buffer.
+ * If no bytes were received before, we start from the beginning,
+ * otherwise we jump to the next available frame position.
+ */
+ uint8_t *rx_buffer =
+ transfer->rx + ((transfer->rx_len - rx_c[spi]) * bytes);
+
while (__builtin_arc_lr(base[spi] + QM_SS_SPI_SR) & QM_SS_SPI_SR_RFNE &&
rx_c[spi]) {
- fifo_read(spi, rx_p[spi], bytes);
- rx_p[spi] += bytes;
+ fifo_read(spi, rx_buffer, bytes);
+ rx_buffer += bytes;
rx_c[spi]--;
}
/* Set new FIFO threshold or complete transfer */
@@ -366,10 +399,9 @@ static void handle_spi_rx_interrupt(const qm_ss_spi_t spi)
__builtin_arc_sr(ftlr, base[spi] + QM_SS_SPI_FTLR);
} else {
spi_disable(spi);
- if (transfer[spi]->callback) {
- transfer[spi]->callback(transfer[spi]->data, 0,
- QM_SS_SPI_IDLE,
- transfer[spi]->rx_len);
+ if (transfer->callback) {
+ transfer->callback(transfer->callback_data, 0,
+ QM_SS_SPI_IDLE, transfer->rx_len);
}
}
}
diff --git a/ext/hal/qmsi/drivers/sensor/sensor.mk b/ext/hal/qmsi/drivers/sensor/sensor.mk
new file mode 100644
index 000000000..eaec3bc81
--- /dev/null
+++ b/ext/hal/qmsi/drivers/sensor/sensor.mk
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+### Variables
+SENSOR_DIR = $(BASE_DIR)/drivers/sensor
+OBJ_DIRS += $(SENSOR_DIR)/$(BUILD)/$(SOC)/$(TARGET)
+SENSOR_SOURCES = $(wildcard $(SENSOR_DIR)/*.c)
+OBJECTS += $(addprefix $(DRV_DIR)/$(BUILD)/$(SOC)/$(TARGET)/$(OBJ)/,$(notdir $(SENSOR_SOURCES:.c=.o)))
+
+### Flags
+CFLAGS += -I$(SENSOR_DIR)
+CFLAGS += -I$(SENSOR_DIR)/include
+CFLAGS += -I$(BASE_DIR)/soc/$(SOC_ROOT_DIR)/include
+
+### Build C files
+$(DRV_DIR)/$(BUILD)/$(SOC)/$(TARGET)/$(OBJ)/%.o: $(SENSOR_DIR)/%.c
+ $(call mkdir, $(DRV_DIR)/$(BUILD)/$(SOC)/$(TARGET)/$(OBJ))
+ $(CC) $(CFLAGS) -c -o $@ $<
diff --git a/ext/hal/qmsi/drivers/sensor/ss_power_states.c b/ext/hal/qmsi/drivers/sensor/ss_power_states.c
index 063ea5a08..2075ec284 100644
--- a/ext/hal/qmsi/drivers/sensor/ss_power_states.c
+++ b/ext/hal/qmsi/drivers/sensor/ss_power_states.c
@@ -28,6 +28,8 @@
*/
#include "ss_power_states.h"
+#include "qm_isr.h"
+#include "qm_sensor_regs.h"
/* Sensor Subsystem sleep operand definition.
* Only a subset applies as internal sensor RTC
@@ -58,6 +60,14 @@
*/
void 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.
+ * Switch to Level triggered interrupts and restore
+ * the setting after when waking up.
+ */
+ __builtin_arc_sr(QM_IRQ_RTC_0_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:
@@ -73,6 +83,10 @@ void ss_power_cpu_ss1(const ss_power_cpu_ss1_mode_t mode)
: "i"(QM_SS_SLEEP_MODE_CORE_OFF));
break;
}
+
+ /* Restore the RTC to edge interrupt after when waking up. */
+ __builtin_arc_sr(QM_IRQ_RTC_0_VECTOR, QM_SS_AUX_IRQ_SELECT);
+ __builtin_arc_sr(QM_SS_IRQ_EDGE_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
}
/* Enter SS2 :
@@ -81,8 +95,20 @@ void ss_power_cpu_ss1(const ss_power_cpu_ss1_mode_t mode)
*/
void ss_power_cpu_ss2(void)
{
+ /* The sensor cannot be woken up with an edge triggered
+ * interrupt from the RTC.
+ * Switch to Level triggered interrupts and restore
+ * the setting after when waking up.
+ */
+ __builtin_arc_sr(QM_IRQ_RTC_0_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 to edge interrupt after when waking up. */
+ __builtin_arc_sr(QM_IRQ_RTC_0_VECTOR, QM_SS_AUX_IRQ_SELECT);
+ __builtin_arc_sr(QM_SS_IRQ_EDGE_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
}
diff --git a/ext/hal/qmsi/drivers/soc_watch.c b/ext/hal/qmsi/drivers/soc_watch.c
new file mode 100644
index 000000000..595194eec
--- /dev/null
+++ b/ext/hal/qmsi/drivers/soc_watch.c
@@ -0,0 +1,355 @@
+/*
+ * 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.
+ */
+
+/*
+ * SoC Watch - QMSI power profiler
+ */
+
+#if (SOC_WATCH_ENABLE) && (!QM_SENSOR)
+
+#include <x86intrin.h>
+#include "qm_common.h"
+#include "qm_soc_regs.h"
+#include "qm_interrupt.h"
+#include "soc_watch.h"
+
+/*
+ * Define a macro for exposing some functions and other definitions
+ * only when unit testing. If we're not unit testing, then declare
+ * them as static, so that their declarations are hidden to normal
+ * code.
+ */
+#if (UNIT_TEST)
+#define NONUTSTATIC
+#else
+#define NONUTSTATIC static
+#endif
+
+/**
+ * "Event strings" table, describing message structures.
+ * The first character is the event code to write to the data file.
+ * The 2nd and subsequent characters describe how to format the record's
+ * data. Note that the ordering here needs to agree with the
+ * enumeration list in qmsw_stub.h.
+ *
+ * Table characters:
+ * + First char = event code to write into the result file.
+ * + T = TSC Timestamp (Hi-res timestamp)
+ * + t = RTC Timestamp (lo-res timestamp)
+ * + 1 = interpret ev_data as a 1-byte value
+ * + 4 = interpret ev_data as a 4-byte value
+ * + R = Using ev_data as a register enumeration, read that register,
+ * + and put that 4-byte value into the data file.
+ * + L = Trigger an RTC timestamp Later
+ */
+NONUTSTATIC const char *ev_strs[] = {
+ "HT", /* Halt event */
+ "IT1", /* Interrupt event */
+ "STtL", /* Sleep event */
+ "RT1R", /* Register read event: Timestamp, reg enum, reg value*/
+ "UTs4", /* User event: timestamp, subtype, data value. */
+};
+
+/*
+ * This list of registers corresponds to the SoC Watch register ID
+ * enumeration in soc_watch.h, and MUST STAY IN AGREEMENT with that
+ * list, since that enumeration is used to index this list.
+ *
+ * To record a register value, the SoC Watch code indexes into this
+ * array, and reads the corresponding address found in that slot.
+ */
+#if (QUARK_D2000)
+static const uint32_t *platform_regs[] = {
+ (uint32_t *)(&QM_SCSS_CCU->osc0_cfg1),
+ (uint32_t *)(&QM_SCSS_CCU->ccu_lp_clk_ctl),
+ (uint32_t *)(&QM_SCSS_CCU->ccu_sys_clk_ctl),
+ /* Clock Gating Registers */
+ (uint32_t *)(&QM_SCSS_CCU->ccu_periph_clk_gate_ctl),
+ (uint32_t *)(&QM_SCSS_CCU->ccu_ext_clock_ctl),
+ /* Power Consumption regs */
+ (uint32_t *)(&QM_SCSS_CMP->cmp_pwr),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_pullup),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_slew),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_in_en)};
+#elif(QUARK_SE)
+static const uint32_t *platform_regs[] = {
+ (uint32_t *)(&QM_SCSS_CCU->osc0_cfg1),
+ (uint32_t *)(&QM_SCSS_CCU->ccu_lp_clk_ctl),
+ (uint32_t *)(&QM_SCSS_CCU->ccu_sys_clk_ctl),
+ /* Clock Gating Registers */
+ (uint32_t *)(&QM_SCSS_CCU->ccu_periph_clk_gate_ctl),
+ (uint32_t *)(&QM_SCSS_CCU->ccu_ss_periph_clk_gate_ctl),
+ (uint32_t *)(&QM_SCSS_CCU->ccu_ext_clock_ctl),
+ /* Power Consumption regs */
+ (uint32_t *)(&QM_SCSS_CMP->cmp_pwr), (uint32_t *)(&QM_SCSS_PMU->slp_cfg),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_pullup),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_pullup[1]),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_pullup[2]),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_pullup[3]),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_slew),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_slew[1]),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_slew[2]),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_slew[3]),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_in_en),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_in_en[1]),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_in_en[2]),
+ (uint32_t *)(&QM_SCSS_PMUX->pmux_in_en[3])};
+#endif /* QUARK_SE */
+
+/* Define VERBOSE to turn on printf-based logging */
+#ifdef VERBOSE
+#define SOC_WATCH_TRACE QM_PRINTF
+#else
+#define SOC_WATCH_TRACE(...)
+#endif
+
+/*
+ * mlog routines -- low-level memory debug logging.
+ * Only enable if there's a need to debug this module.
+ */
+#ifdef MLOG_ENABLE
+#define MLOG(e) mlog(e)
+#define MLOG_BYTE(b) mlog_byte(b)
+#define MLOG_SIZE 512 /* Must be a power of 2 */
+static uint8_t mlog_events[MLOG_SIZE];
+static uint16_t mlog_idx = 0;
+void mlog(uint8_t event)
+{
+ mlog_events[++mlog_idx % (MLOG_SIZE)] = event;
+}
+void mlog_byte(uint8_t byte)
+{
+ const char c[] = {"0123456789ABCDEF"};
+ MLOG(c[byte >> 4]);
+ MLOG(c[byte & 4]);
+}
+#else /* !MLOG_ENABLE */
+#define MLOG(event)
+#define MLOG_BYTE(b)
+#endif /* !MLOG_ENABLE */
+
+/*
+ * CONFIGURABLE: Set this to control the number of bytes of RAM you
+ * want to dedicate to event buffering. The larger the buffer,
+ * the fewer (expensive) flushes we will have to do. The smaller,
+ * the lower the memory cost, but the more flushes you will do.
+ */
+#define SOC_WATCH_EVENT_BUFFER_SIZE (256) /* Measured in bytes */
+
+/**
+ * Power profiling event data buffer. Symbol must be globally
+ * visible, so that it can be seen by external tools.
+ */
+struct sw_profiling_event_buffer {
+ uint8_t eb_idx; /* Index of next byte to be written */
+ uint8_t eb_size; /* Buffer size == SOC_WATCH_EVENT_BUFFER_SIZE */
+ uint8_t event_data[SOC_WATCH_EVENT_BUFFER_SIZE - 2]; /* Event data -
+ sizeof(idx + size) */
+} soc_watch_event_buffer = {0, SOC_WATCH_EVENT_BUFFER_SIZE - 1, {0}};
+
+/* High water mark, i.e. "start trying to flush" point. */
+#define SW_EB_HIGH_WATER (((SOC_WATCH_EVENT_BUFFER_SIZE - 2) * 7) >> 3)
+
+NONUTSTATIC int soc_watch_buffer_full(void)
+{
+ return (soc_watch_event_buffer.eb_idx >= SW_EB_HIGH_WATER);
+}
+
+/**
+ * Flag used by the JTAG data extraction routine. During setup, a HW
+ * watchpoint is placed on this address. During the flush routine,
+ * software writes to it, causing the HW watchpoint to fire, and
+ * OpenOCD to extract the data. This symbol MUST be globally visible
+ * in order for JTAG data transfer to work.
+ */
+volatile uint8_t soc_watch_flush_flag = 0;
+
+/*
+ * soc_watch_event_buffer_flush -- Trigger the data buffer flush.
+ */
+static void soc_watch_event_buffer_flush(void)
+{
+/* Figure out if we can successfully flush the data out.
+ * If we're sleeping, the JTAG query will fail.
+ */
+#if (QUARK_D2000)
+ /**
+ * If the "we're going to sleep" bit is set, parts of the
+ * SOC are already asleep, and transferring data over
+ * the JTAG port is not always reliable. So defer transferring
+ * the data until later.
+ * @TODO: Determine if there is also a sensitivity to the
+ * clock rate.
+ */
+ MLOG('F');
+ if (QM_SCSS_PMU->aon_vr & QM_AON_VR_VREG_SEL) {
+ MLOG('-');
+ return; /* We would only send junk, so don't flush. */
+ }
+#endif
+
+ soc_watch_flush_flag = 1; /* Trigger the data extract brkpt */
+ soc_watch_event_buffer.eb_idx = 0;
+ MLOG('+');
+}
+
+/* Store a byte in the event buffer. */
+static void eb_write_char(uint8_t data)
+{
+ SOC_WATCH_TRACE("c%d:0x%x [0]=%x\n", soc_watch_event_buffer.eb_idx,
+ data, soc_watch_event_buffer.event_data[0]);
+ soc_watch_event_buffer.event_data[soc_watch_event_buffer.eb_idx++] =
+ data;
+}
+
+/* Store a word in the event buffer. */
+static void eb_write_uint32(uint32_t *data)
+{
+ uint32_t *uip = (uint32_t *)&soc_watch_event_buffer
+ .event_data[soc_watch_event_buffer.eb_idx];
+ *uip = *data;
+ SOC_WATCH_TRACE("I%d:0x%x\n", soc_watch_event_buffer.eb_idx, *data);
+ soc_watch_event_buffer.eb_idx += sizeof(uint32_t);
+}
+
+/* Log an event with one parameter. */
+void soc_watch_log_event(soc_watch_event_t event_id, uintptr_t ev_data)
+{
+ soc_watch_log_app_event(event_id, 0, ev_data);
+}
+
+/*
+ * Log an event with two parameters, where the subtype comes from
+ * the user. Note that what actually makes this an 'application event' is
+ * the event_id, not the fact that it is coming in via this interface.
+ */
+void soc_watch_log_app_event(soc_watch_event_t event_id, uint8_t ev_subtype,
+ uintptr_t ev_data)
+{
+ static uint8_t record_rtc = 0;
+ const uint32_t *rtc_ctr = (uint32_t *)&QM_RTC->rtc_ccr;
+ const char *cp;
+ uint64_t tsc = __builtin_ia32_rdtsc(); /* Grab hi-res timestamp */
+ uint32_t rtc_val = *rtc_ctr;
+
+#define AVG_EVENT_SIZE 8 /* Size of a typical message in bytes. */
+
+ MLOG('[');
+ qm_irq_disable();
+ /* TODO: We know exactly how many bytes of storage we need,
+ * since we know the event code. So don't do an "AVG" size thing
+ * here--use the exact size!
+ */
+ if ((soc_watch_event_buffer.eb_idx + AVG_EVENT_SIZE) <=
+ soc_watch_event_buffer.eb_size) {
+
+/* Map a halt event to a sleep event where appropriate. */
+#if (QUARK_D2000)
+ if (event_id == SOCW_EVENT_HALT) {
+ if (QM_SCSS_PMU->aon_vr & QM_AON_VR_VREG_SEL) {
+ event_id = SOCW_EVENT_SLEEP;
+ }
+ }
+#endif
+
+ /* Record the RTC of the waking event, if it's rousing us from
+ * sleep. */
+ if (record_rtc) {
+ eb_write_char('t');
+ eb_write_uint32((uint32_t *)(&rtc_val)); /* Timestamp */
+ record_rtc = 0;
+ }
+
+ if (event_id >= SOCW_EVENT_MAX) {
+ SOC_WATCH_TRACE("Unknown event id: 0x%x\n", event_id);
+ MLOG('?');
+ qm_irq_enable();
+ return;
+ }
+ cp = ev_strs[event_id]; /* Look up event string */
+ SOC_WATCH_TRACE("%c", *cp);
+ MLOG(*cp);
+ eb_write_char(*cp); /* Write event code */
+ while (*++cp) {
+ switch (*cp) {
+ case 'T':
+ eb_write_uint32((uint32_t *)(&tsc)); /* Hi-res
+ Timestamp */
+ break;
+ case 't':
+ eb_write_uint32(
+ (uint32_t *)(&rtc_val)); /* Lo-res
+ Timestamp */
+ break;
+ case 'L':
+ record_rtc = 1;
+ break;
+ case 'R': /* Register data value */
+ eb_write_uint32(
+ (uint32_t *)platform_regs[ev_data]);
+ break;
+ case '4': /* 32-bit data value */
+ eb_write_uint32((uint32_t *)&ev_data);
+ break;
+ case '1':
+ /* Register ID */
+ eb_write_char(((uint32_t)ev_data) & 0xff);
+ break;
+ case 's':
+ /* Event subtype */
+ eb_write_char(((uint32_t)ev_subtype) & 0xff);
+ break;
+ default:
+ SOC_WATCH_TRACE(
+ "Unknown string char: 0x%x on string "
+ "0x%x\n",
+ *cp, event_id);
+ break;
+ }
+ }
+ }
+
+ /*
+ * If this is an interrupt which roused the CPU out of a sleep state,
+ * don't flush the buffer. (Due to a bug in OpenOCD, doing so will
+ * clear the HW watchpoint, ensuring no further flushes are seen by
+ * OpenOCD.)
+ */
+ if ((soc_watch_buffer_full()) && (event_id != SOCW_EVENT_INTERRUPT)) {
+ SOC_WATCH_TRACE("\n --- FLUSH: idx= %d ---\n",
+ soc_watch_event_buffer.eb_idx);
+ soc_watch_event_buffer_flush();
+ }
+ MLOG(':');
+ MLOG_BYTE(soc_watch_event_buffer.eb_idx);
+ qm_irq_enable();
+ MLOG(']');
+}
+
+#endif /* !(defined(SOC_WATCH) && (!QM_SENSOR)) */
diff --git a/ext/hal/qmsi/include/qm_common.h b/ext/hal/qmsi/include/qm_common.h
index 8de124cc2..3b9e06bbe 100644
--- a/ext/hal/qmsi/include/qm_common.h
+++ b/ext/hal/qmsi/include/qm_common.h
@@ -55,15 +55,21 @@ struct interrupt_frame;
#define REG_VAL(addr) (*((volatile uint32_t *)addr))
+/* QM_ASSERT is not currently available for Zephyr. */
+#define ASSERT_EXCLUDE (ZEPHYR_OS)
+
/**
* In our reference implementation, by default DEBUG enables QM_PUTS and
* QM_ASSERT but not QM_PRINTF.
* User can modify this block to customise the default DEBUG configuration.
*/
+
#if (DEBUG)
+#if !ASSERT_EXCLUDE
#ifndef ASSERT_ENABLE
#define ASSERT_ENABLE (1)
#endif
+#endif /* ASSERT_EXCLUDE */
#ifndef PUTS_ENABLE
#define PUTS_ENABLE (1)
#endif
@@ -112,7 +118,8 @@ void stdout_uart_setup(uint32_t baud_divisors);
#endif /* PRINTF_ENABLE || PUTS_ENABLE || ASSERT_ENABLE */
#if (PRINTF_ENABLE)
-#define QM_PRINTF(...) printf(__VA_ARGS__)
+int pico_printf(const char *format, ...);
+#define QM_PRINTF(...) pico_printf(__VA_ARGS__)
#else
#define QM_PRINTF(...)
#endif /* PRINTF_ENABLE */
@@ -146,7 +153,7 @@ void stdout_uart_setup(uint32_t baud_divisors);
#endif
/*
- * Stdout UART intialization is enabled by default. Use this switch if you wish
+ * Stdout UART initialization is enabled by default. Use this switch if you wish
* to disable it (e.g. if the UART is already initialized by an application
* running on the other core).
*/
@@ -266,4 +273,39 @@ void stdout_uart_setup(uint32_t baud_divisors);
#define QM_VER_STRINGIFY(major, minor, patch) \
QM_STRINGIFY(major) "." QM_STRINGIFY(minor) "." QM_STRINGIFY(patch)
+#if (SOC_WATCH_ENABLE) && (!QM_SENSOR)
+/**
+ * Front-end macro for logging a SoC Watch event. When SOC_WATCH_ENABLE
+ * is not set to 1, the macro expands to nothing, there is no overhead.
+ *
+ * @param[in] event_id The Event ID of the profile event.
+ * @param[in] ev_data A parameter to the event ID (if the event needs one).
+ *
+ * @returns Nothing.
+ */
+#define SOC_WATCH_LOG_EVENT(event, param) \
+ do { \
+ soc_watch_log_event(event, param); \
+ } while (0)
+
+/**
+ * Front-end macro for logging application events via the power profiler
+ * logger. When SOC_WATCH_ENABLE is not set to 1, the macro expands to
+ * nothing, there is no overhead.
+ *
+ * @param[in] event_id The Event ID of the profile event.
+ * @param[in] ev_subtype A 1-byte user-defined event_id.
+ * @param[in] ev_data A parameter to the event ID (if the event needs one).
+ *
+ * @returns Nothing.
+ */
+#define SOC_WATCH_LOG_APP_EVENT(event, subtype, param) \
+ do { \
+ soc_watch_log_app_event(event, subtype, param); \
+ } while (0)
+#else
+#define SOC_WATCH_LOG_EVENT(event, param)
+#define SOC_WATCH_LOG_APP_EVENT(event, subtype, param)
+#endif
+
#endif /* __QM_COMMON_H__ */
diff --git a/ext/hal/qmsi/include/spinlock.h b/ext/hal/qmsi/include/spinlock.h
deleted file mode 100644
index 0819f2d85..000000000
--- a/ext/hal/qmsi/include/spinlock.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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 __SPINLOCK_H__
-#define __SPINLOCK_H__
-
-#include "qm_soc_regs.h"
-/*
- * Single, shared spinlock which can be used for synchronization between the
- * Lakemont and ARC cores.
- * The Spinlock lock size and position in RAM must be same on both cores.
- */
-#if (QUARK_SE)
-
-typedef struct {
- volatile char flag[2];
- volatile char turn;
-} spinlock_t;
-
-extern spinlock_t __esram_lock_start;
-void spinlock_lock(spinlock_t *lock);
-void spinlock_unlock(spinlock_t *lock);
-
-#define QM_SPINLOCK_LOCK() spinlock_lock(&__esram_lock_start)
-#define QM_SPINLOCK_UNLOCK() spinlock_unlock(&__esram_lock_start)
-
-#else
-
-#define QM_SPINLOCK_LOCK()
-#define QM_SPINLOCK_UNLOCK()
-
-#endif /* defined(QM_QUARK_SE) */
-
-#endif /* __SPINLOCK_H__ */
diff --git a/ext/hal/qmsi/soc/quark_d2000/drivers/power_states.c b/ext/hal/qmsi/soc/quark_d2000/drivers/power_states.c
index 2f5bd47f0..4f1b34713 100644
--- a/ext/hal/qmsi/soc/quark_d2000/drivers/power_states.c
+++ b/ext/hal/qmsi/soc/quark_d2000/drivers/power_states.c
@@ -30,13 +30,15 @@
#include "power_states.h"
#include "clk.h"
#include "qm_comparator.h"
-
+#include "qm_isr.h"
#include "qm_adc.h"
#include "rar.h"
+#include "soc_watch.h"
-void cpu_halt(void)
+void power_cpu_halt(void)
{
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_HALT, 0);
__asm__ __volatile__("hlt");
}
@@ -55,7 +57,7 @@ static void clear_all_pending_interrupts(void)
QM_GPIO[QM_GPIO_0]->gpio_porta_eoi = -1;
}
-void soc_sleep(void)
+void power_soc_sleep(void)
{
/* Variables to save register values. */
uint32_t ac_power_save;
@@ -79,6 +81,8 @@ void soc_sleep(void)
* Mask registers.
*/
QM_SCSS_CCU->ccu_lp_clk_ctl &= ~QM_WAKE_PROBE_MODE_MASK;
+ /* Enable all wake sources as interrupts. */
+ QM_SCSS_CCU->wake_mask = 0;
/*
* Ensure that powering down of oscillators is delayed by hardware until
@@ -93,10 +97,9 @@ void soc_sleep(void)
* frequency than RTC clock.
*/
/* CCU_LP_CLK_CTL.CCU_EXIT_TO_HYBOSC */
- QM_SCSS_CCU->ccu_lp_clk_ctl |= QM_CCU_EXIT_TO_HYBOSC;
-
- /* Power down hybrid oscillator after HALT instruction is executed. */
- QM_SCSS_CCU->osc0_cfg1 |= QM_OSC0_PD;
+ QM_SCSS_CCU->ccu_lp_clk_ctl |=
+ QM_CCU_EXIT_TO_HYBOSC | QM_CCU_MEM_HALT_EN | QM_CCU_CPU_HALT_EN;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_LP_CLK_CTL);
/*
* Only the following peripherals can be used as a wakeup source:
@@ -124,7 +127,7 @@ void soc_sleep(void)
* CCU_SYS_CLK_CTL.CCU_SYS_CLK_SEL to RTC Oscillator.
*/
/* Enter SoC sleep mode. */
- cpu_halt();
+ power_cpu_halt();
/* From here on, restore the SoC to an active state. */
/* Set the RAR to normal mode. */
@@ -137,6 +140,8 @@ void soc_sleep(void)
QM_SCSS_CCU->ccu_sys_clk_ctl |=
QM_CCU_SYS_CLK_DIV_EN | QM_CCU_RTC_CLK_DIV_EN;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_SYS_CLK_CTL);
+
/* Wait for the XTAL or SI oscillator to stabilise. */
while (!(QM_SCSS_CCU->osc0_stat1 &
(QM_OSC0_LOCK_SI | QM_OSC0_LOCK_XTAL))) {
@@ -145,12 +150,14 @@ void soc_sleep(void)
/* Restore original clocking, ADC, analog comparator states. */
QM_SCSS_CCU->osc0_cfg1 = osc0_cfg_save;
QM_SCSS_CCU->ccu_periph_clk_gate_ctl = clk_gate_save;
-
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_OSC0_CFG1);
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER,
+ SOCW_REG_CCU_PERIPH_CLK_GATE_CTL);
QM_SCSS_CMP->cmp_pwr = ac_power_save;
QM_ADC->adc_op_mode = adc_mode_save;
}
-void soc_deep_sleep(void)
+void power_soc_deep_sleep(const power_wake_event_t wake_event)
{
/* Variables to save register values. */
uint32_t ac_power_save;
@@ -170,9 +177,23 @@ void soc_deep_sleep(void)
/* Clear any pending interrupts. */
clear_all_pending_interrupts();
- /* Only clear the comparator wake mask bit. */
- QM_SCSS_CCU->wake_mask =
- SET_ALL_BITS & ~QM_CCU_WAKE_MASK_COMPARATOR_BIT;
+ /*
+ * Clear the wake mask bits. Default behaviour is to wake from GPIO /
+ * comparator.
+ */
+ switch (wake_event) {
+ case POWER_WAKE_FROM_RTC:
+ QM_SCSS_CCU->wake_mask =
+ SET_ALL_BITS & ~QM_CCU_WAKE_MASK_RTC_BIT;
+ break;
+ case POWER_WAKE_FROM_GPIO_COMP:
+ default:
+ QM_SCSS_CCU->wake_mask = SET_ALL_BITS &
+ ~(QM_CCU_WAKE_MASK_COMPARATOR_BIT |
+ QM_CCU_WAKE_MASK_GPIO_BIT);
+ break;
+ }
+
QM_SCSS_GP->gps1 |= QM_SCSS_GP_POWER_STATE_DEEP_SLEEP;
qm_adc_set_mode(QM_ADC_0, QM_ADC_MODE_DEEP_PWR_DOWN);
@@ -186,15 +207,20 @@ void soc_deep_sleep(void)
/* Disable external clocks. */
QM_SCSS_CCU->ccu_ext_clock_ctl = 0;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_EXT_CLK_CTL);
/* Set slew rate of all pins to 12mA. */
QM_SCSS_PMUX->pmux_slew[0] = 0;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_PMUX_SLEW);
- /* Disable RTC. */
- QM_SCSS_CCU->osc1_cfg0 &= ~QM_OSC1_PD;
+ if (wake_event != POWER_WAKE_FROM_RTC) {
+ /* Disable RTC. */
+ QM_SCSS_CCU->osc1_cfg0 &= ~QM_OSC1_PD;
- /* Set system clock source to hyb osc, 4 MHz, scaled down to 32 kHz. */
- clk_sys_set_mode(CLK_SYS_HYB_OSC_4MHZ, CLK_SYS_DIV_128);
+ /* Set system clock source to
+ * Silicon Oscillator 4 MHz, scaled down to 32 kHz. */
+ clk_sys_set_mode(CLK_SYS_HYB_OSC_4MHZ, CLK_SYS_DIV_128);
+ }
/* Power down the oscillator after the halt instruction is executed. */
QM_SCSS_CCU->ccu_lp_clk_ctl &= ~QM_HYB_OSC_PD_LATCH_EN;
@@ -204,6 +230,7 @@ void soc_deep_sleep(void)
*/
QM_SCSS_CCU->ccu_lp_clk_ctl |=
QM_CCU_EXIT_TO_HYBOSC | QM_CCU_MEM_HALT_EN | QM_CCU_CPU_HALT_EN;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_LP_CLK_CTL);
/* Power down hybrid oscillator. */
QM_SCSS_CCU->osc0_cfg1 |= QM_OSC0_PD;
@@ -244,8 +271,16 @@ void soc_deep_sleep(void)
/* Set the RAR to retention mode. */
rar_set_mode(RAR_RETENTION);
+ if (wake_event == POWER_WAKE_FROM_RTC) {
+ /* Start running on the rtc clock */
+ clk_sys_set_mode(CLK_SYS_RTC_OSC, CLK_SYS_DIV_1);
+ }
+
+ /* Disable all peripheral clocks. */
+ clk_periph_disable(CLK_PERIPH_REGISTER | CLK_PERIPH_CLK);
+
/* Enter SoC deep sleep mode. */
- cpu_halt();
+ power_cpu_halt();
/* We are now exiting from deep sleep mode. */
/* Set the RAR to normal mode. */
@@ -297,6 +332,7 @@ void soc_deep_sleep(void)
while (!(QM_SCSS_CCU->osc0_stat1 &
(QM_OSC0_LOCK_SI | QM_OSC0_LOCK_XTAL))) {
};
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_SYS_CLK_CTL);
/* Re-enable clocks. */
clk_periph_enable(CLK_PERIPH_REGISTER);
@@ -309,6 +345,9 @@ void soc_deep_sleep(void)
QM_SCSS_CCU->ccu_periph_clk_gate_ctl = clk_gate_save;
QM_SCSS_CCU->osc1_cfg0 = osc1_cfg_save;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_OSC0_CFG1);
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER,
+ SOCW_REG_CCU_PERIPH_CLK_GATE_CTL);
QM_SCSS_CMP->cmp_pwr = ac_power_save;
QM_ADC->adc_op_mode = adc_mode_save;
@@ -316,6 +355,10 @@ void soc_deep_sleep(void)
QM_SCSS_CCU->ccu_ext_clock_ctl = ext_clock_save;
QM_SCSS_CCU->ccu_lp_clk_ctl = lp_clk_save;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_PMUX_SLEW);
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_LP_CLK_CTL);
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_EXT_CLK_CTL);
+
QM_SCSS_CCU->wake_mask = SET_ALL_BITS;
QM_SCSS_GP->gps1 &= ~QM_SCSS_GP_POWER_STATE_DEEP_SLEEP;
}
diff --git a/ext/hal/qmsi/soc/quark_d2000/include/flash_layout.h b/ext/hal/qmsi/soc/quark_d2000/include/flash_layout.h
index b4dd64b5f..2dce50a4a 100644
--- a/ext/hal/qmsi/soc/quark_d2000/include/flash_layout.h
+++ b/ext/hal/qmsi/soc/quark_d2000/include/flash_layout.h
@@ -84,6 +84,78 @@ typedef union {
#define QM_FLASH_TRIM_PRESENT_MASK (0xFC00)
#define QM_FLASH_TRIM_PRESENT (0x7C00)
+/*
+ * Bootloader data
+ */
+
+/** The flash controller where BL-Data is stored. */
+#define BL_DATA_FLASH_CONTROLLER QM_FLASH_0
+/** The flash region where BL-Data is stored. */
+#define BL_DATA_FLASH_REGION QM_FLASH_REGION_DATA
+/** The flash address where the BL-Data Section starts. */
+#define BL_DATA_FLASH_REGION_BASE QM_FLASH_REGION_DATA_0_BASE
+/** The flash page where the BL-Data Section starts. */
+#define BL_DATA_SECTION_BASE_PAGE (0)
+
+/** The size (in pages) of the System flash region of Quark D2000. */
+#define QM_FLASH_REGION_SYS_0_PAGES (16)
+
+/** The size of each flash partition for Lakemont application code. */
+#if (BL_CONFIG_DUAL_BANK)
+#define BL_PARTITION_SIZE_LMT (QM_FLASH_REGION_SYS_0_PAGES / 2)
+#else /* !BL_CONFIG_DUAL_BANK */
+#define BL_PARTITION_SIZE_LMT (QM_FLASH_REGION_SYS_0_PAGES)
+#endif /* BL_CONFIG_DUAL_BANK */
+
+/** Number of boot targets. */
+#define BL_BOOT_TARGETS_NUM (1)
+
+#define BL_TARGET_IDX_LMT (0)
+
+#define BL_PARTITION_IDX_LMT0 (0)
+#define BL_PARTITION_IDX_LMT1 (1)
+
+#define BL_TARGET_0_LMT \
+ { \
+ .active_partition_idx = BL_PARTITION_IDX_LMT0, .svn = 0 \
+ }
+
+#define BL_PARTITION_0_LMT0 \
+ { \
+ .target_idx = BL_TARGET_IDX_LMT, .controller = QM_FLASH_0, \
+ .first_page = 0, .num_pages = BL_PARTITION_SIZE_LMT, \
+ .start_addr = (uint32_t *)QM_FLASH_REGION_SYS_0_BASE, \
+ .is_consistent = true, \
+ }
+
+#define BL_PARTITION_1_LMT1 \
+ { \
+ .target_idx = BL_TARGET_IDX_LMT, .controller = QM_FLASH_0, \
+ .first_page = BL_PARTITION_SIZE_LMT, \
+ .num_pages = BL_PARTITION_SIZE_LMT, \
+ .start_addr = \
+ (uint_32_t *)QM_FLASH_REGION_SYS_0_BASE + \
+ (BL_PARTITION_SIZE_LMT * QM_FLAH_PAGE_SIZE_DWORDS), \
+ .is_consistent = true, \
+ }
+
+#define BL_TARGET_LIST \
+ { \
+ BL_TARGET_0_LMT \
+ }
+
+#if (BL_CONFIG_DUAL_BANK)
+#define BL_PARTITION_LIST \
+ { \
+ BL_PARTITION_0_LMT0, BL_PARTITION_1_LMT1 \
+ }
+#else /* !BL_CONFIG_DUAL_BANK */
+#define BL_PARTITION_LIST \
+ { \
+ BL_PARTITION_0_LMT0 \
+ }
+#endif /* BL_CONFIG_DUAL_BANK */
+
/**
* @}
*/
diff --git a/ext/hal/qmsi/soc/quark_d2000/include/power_states.h b/ext/hal/qmsi/soc/quark_d2000/include/power_states.h
index b18990a1e..f3102cc16 100644
--- a/ext/hal/qmsi/soc/quark_d2000/include/power_states.h
+++ b/ext/hal/qmsi/soc/quark_d2000/include/power_states.h
@@ -41,11 +41,19 @@
*/
/**
+* Wake source for deep sleep mode type.
+*/
+typedef enum {
+ POWER_WAKE_FROM_GPIO_COMP, /**< Use GPIO / Comparator as wake source. */
+ POWER_WAKE_FROM_RTC, /**< Use RTC as wake source. */
+} power_wake_event_t;
+
+/**
* Put CPU in halt state.
*
* Halts the CPU until next interrupt or reset.
*/
-void cpu_halt(void);
+void power_cpu_halt(void);
/**
* Put SoC to sleep.
@@ -68,15 +76,19 @@ void cpu_halt(void);
* - RTC
* - Low power comparators
*/
-void soc_sleep();
+void power_soc_sleep();
/**
* Put SoC to deep sleep.
*
- * Enter into deep sleep mode. All clocks are gated. The only way to return
- * from this is to have an interrupt trigger on the low power comparators.
+ * Enter into deep sleep mode. All clocks are gated. The Wake source for this
+ * function depends on the input parameter, POWER_WAKE_FROM_GPIO_COMP will
+ * enable waking from GPIO or comparator pins and POWER_WAKE_FROM_RTC will
+ * enable waking from the RTC.
+ *
+ * @param[in] wake_source Select wake source for deep sleep mode.
*/
-void soc_deep_sleep();
+void power_soc_deep_sleep(const power_wake_event_t wake_event);
/**
* @}
diff --git a/ext/hal/qmsi/soc/quark_d2000/include/qm_soc_regs.h b/ext/hal/qmsi/soc/quark_d2000/include/qm_soc_regs.h
index f46157061..8e07c00d0 100644
--- a/ext/hal/qmsi/soc/quark_d2000/include/qm_soc_regs.h
+++ b/ext/hal/qmsi/soc/quark_d2000/include/qm_soc_regs.h
@@ -33,10 +33,10 @@
#include "qm_common.h"
/**
- * Quark Microcontroller D2000 Register file.
- *
- * @brief Quark Microcontroller D2000 Registers.
+ * Quark D2000 SoC Registers.
*
+ * @defgroup groupQUARKD2000SEREG SoC Registers (D2000)
+ * @{
*/
#define QUARK_D2000 (1)
@@ -44,10 +44,11 @@
#define HAS_MVIC (1)
/**
- * @defgroup groupD2000REG Quark D2000 Registers
- @{
+ * @name System Core
+ * @{
*/
+/** System Core register map. */
typedef struct {
QM_RW uint32_t osc0_cfg0; /**< Hybrid Oscillator Configuration 0 */
QM_RW uint32_t osc0_stat1; /**< Hybrid Oscillator status 1 */
@@ -79,7 +80,6 @@ qm_scss_ccu_reg_t test_scss_ccu;
#else
#define QM_SCSS_CCU_BASE (0xB0800000)
-/** system control subsystem clock control unit register block */
#define QM_SCSS_CCU ((qm_scss_ccu_reg_t *)QM_SCSS_CCU_BASE)
#endif
@@ -88,16 +88,16 @@ qm_scss_ccu_reg_t test_scss_ccu;
#define QM_OSC0_PD BIT(2)
#define QM_OSC1_PD BIT(1)
-/* Enable Crystal oscillator*/
+/* Enable Crystal oscillator. */
#define QM_OSC0_EN_CRYSTAL BIT(0)
-/* Crystal oscillator parameters */
+/* Crystal oscillator parameters. */
#define OSC0_CFG1_OSC0_FADJ_XTAL_MASK (0x000F0000)
#define OSC0_CFG1_OSC0_FADJ_XTAL_OFFS (16)
#define OSC0_CFG0_OSC0_XTAL_COUNT_VALUE_MASK (0x00600000)
#define OSC0_CFG0_OSC0_XTAL_COUNT_VALUE_OFFS (21)
-/* Silicon Oscillator parameters */
+/* Silicon Oscillator parameters. */
#define OSC0_CFG1_FTRIMOTP_MASK (0x3FF00000)
#define OSC0_CFG1_FTRIMOTP_OFFS (20)
#define OSC0_CFG1_SI_FREQ_SEL_MASK (0x00000300)
@@ -106,36 +106,44 @@ qm_scss_ccu_reg_t test_scss_ccu;
#define QM_OSC0_LOCK_SI BIT(0)
#define QM_OSC0_LOCK_XTAL BIT(1)
#define QM_OSC0_EN_SI_OSC BIT(1)
+
#define QM_SI_OSC_1V2_MODE BIT(0)
+/** Peripheral clock divider control */
+#define QM_CCU_PERIPH_PCLK_DIV_OFFSET (1)
+#define QM_CCU_PERIPH_PCLK_DIV_EN BIT(0)
+
+/* System clock control */
#define QM_CCU_SYS_CLK_SEL BIT(0)
#define QM_CCU_PERIPH_CLK_EN BIT(1)
#define QM_CCU_ADC_CLK_DIV_OFFSET (16)
#define QM_CCU_ADC_CLK_DIV_DEF_MASK (0xFC00FFFF)
#define QM_CCU_PERIPH_PCLK_DIV_DEF_MASK (0xFFFFFFF8)
-#define QM_CCU_PERIPH_PCLK_DIV_OFFSET (1)
-#define QM_CCU_PERIPH_PCLK_DIV_EN BIT(0)
+#define QM_CCU_RTC_CLK_EN BIT(1)
+#define QM_CCU_RTC_CLK_DIV_EN BIT(2)
#define QM_CCU_SYS_CLK_DIV_EN BIT(7)
#define QM_CCU_SYS_CLK_DIV_MASK (0x00000700)
-#define QM_CCU_SYS_CLK_DIV_DEF_MASK (0xFFFFF47F)
+
#define QM_OSC0_SI_FREQ_SEL_DEF_MASK (0xFFFFFCFF)
+#define QM_CCU_SYS_CLK_DIV_DEF_MASK (0xFFFFF47F)
#define QM_OSC0_SI_FREQ_SEL_4MHZ (3 >> 8)
-#define QM_CCU_RTC_CLK_DIV_EN BIT(2)
+
#define QM_CCU_EXTERN_DIV_OFFSET (3)
#define QM_CCU_EXT_CLK_DIV_EN BIT(2)
#define QM_CCU_GPIO_DB_DIV_OFFSET (2)
#define QM_CCU_GPIO_DB_CLK_DIV_EN BIT(1)
+#define QM_CCU_GPIO_DB_CLK_EN BIT(0)
#define QM_CCU_RTC_CLK_DIV_OFFSET (3)
#define QM_CCU_SYS_CLK_DIV_OFFSET (8)
-#define QM_CCU_RTC_CLK_EN BIT(1)
#define QM_CCU_GPIO_DB_CLK_DIV_DEF_MASK (0xFFFFFFE1)
#define QM_CCU_EXT_CLK_DIV_DEF_MASK (0xFFFFFFE3)
#define QM_CCU_RTC_CLK_DIV_DEF_MASK (0xFFFFFF83)
#define QM_CCU_DMA_CLK_EN BIT(6)
-
+#define QM_CCU_WAKE_MASK_RTC_BIT BIT(2)
+#define QM_CCU_WAKE_MASK_GPIO_BIT BIT(15)
#define QM_CCU_WAKE_MASK_COMPARATOR_BIT BIT(14)
+#define QM_CCU_WAKE_MASK_GPIO_BIT BIT(15)
-#define QM_CCU_GPIO_DB_CLK_EN BIT(0)
#define QM_HYB_OSC_PD_LATCH_EN BIT(14)
#define QM_RTC_OSC_PD_LATCH_EN BIT(15)
#define QM_CCU_EXIT_TO_HYBOSC BIT(4)
@@ -144,16 +152,24 @@ qm_scss_ccu_reg_t test_scss_ccu;
#define QM_WAKE_PROBE_MODE_MASK BIT(13)
+/** @} */
+
+/**
+ * @name General Purpose
+ * @{
+ */
+
+/** General Purpose register map. */
typedef struct {
- QM_RW uint32_t gps0; /**< General Purpose Sticky Registers */
- QM_RW uint32_t gps1; /**< General Purpose Sticky Registers */
- QM_RW uint32_t gps2; /**< General Purpose Sticky Registers */
- QM_RW uint32_t gps3; /**< General Purpose Sticky Registers */
+ QM_RW uint32_t gps0; /**< General Purpose Sticky Register 0 */
+ QM_RW uint32_t gps1; /**< General Purpose Sticky Register 1 */
+ QM_RW uint32_t gps2; /**< General Purpose Sticky Register 2 */
+ QM_RW uint32_t gps3; /**< General Purpose Sticky Register 3 */
QM_RW uint32_t reserved;
- QM_RW uint32_t gp0; /**< General Purpose Scratchpad Registers */
- QM_RW uint32_t gp1; /**< General Purpose Scratchpad Registers */
- QM_RW uint32_t gp2; /**< General Purpose Scratchpad Registers */
- QM_RW uint32_t gp3; /**< General Purpose Scratchpad Registers */
+ QM_RW uint32_t gp0; /**< General Purpose Scratchpad Register 0 */
+ QM_RW uint32_t gp1; /**< General Purpose Scratchpad Register 1 */
+ QM_RW uint32_t gp2; /**< General Purpose Scratchpad Register 2 */
+ QM_RW uint32_t gp3; /**< General Purpose Scratchpad Register 3 */
QM_RW uint32_t reserved1[3];
QM_RW uint32_t wo_sp; /**< Write-One-to-Set Scratchpad Register */
QM_RW uint32_t
@@ -166,21 +182,28 @@ qm_scss_gp_reg_t test_scss_gp;
#else
#define QM_SCSS_GP_BASE (0xB0800100)
-/** system control subsystem general purpose register block */
#define QM_SCSS_GP ((qm_scss_gp_reg_t *)QM_SCSS_GP_BASE)
#endif
#define QM_SCSS_GP_POWER_STATES_MASK (BIT(6) | BIT(7) | BIT(8) | BIT(9))
#define QM_SCSS_GP_POWER_STATE_DEEP_SLEEP BIT(6)
+/** @} */
+
+/**
+ * @name Comparator
+ * @{
+ */
+
+/** Comparator register map. */
typedef struct {
- QM_RW uint32_t cmp_en; /**< Comparator enable */
- QM_RW uint32_t cmp_ref_sel; /**< Comparator reference select */
+ QM_RW uint32_t cmp_en; /**< Comparator enable. */
+ QM_RW uint32_t cmp_ref_sel; /**< Comparator reference select. */
QM_RW uint32_t
- cmp_ref_pol; /**< Comparator reference polarity select register */
- QM_RW uint32_t cmp_pwr; /**< Comparator power enable register */
+ cmp_ref_pol; /**< Comparator reference polarity select register. */
+ QM_RW uint32_t cmp_pwr; /**< Comparator power enable register. */
QM_RW uint32_t reserved[6];
- QM_RW uint32_t cmp_stat_clr; /**< Comparator clear register */
+ QM_RW uint32_t cmp_stat_clr; /**< Comparator clear register. */
} qm_scss_cmp_reg_t;
#if (UNIT_TEST)
@@ -189,12 +212,19 @@ qm_scss_cmp_reg_t test_scss_cmp;
#else
#define QM_SCSS_CMP_BASE (0xB0800300)
-/** system control subsystem comparators register block */
#define QM_SCSS_CMP ((qm_scss_cmp_reg_t *)QM_SCSS_CMP_BASE)
#endif
#define QM_AC_HP_COMPARATORS_MASK (0x7FFC0)
+/** @} */
+
+/**
+ * @name Interrupt
+ * @{
+ */
+
+/** Interrupt register map. */
typedef struct {
QM_RW uint32_t int_i2c_mst_0_mask; /**< Interrupt Routing Mask 0 */
QM_RW uint32_t reserved[2]; /* There is a hole in the address space. */
@@ -244,17 +274,23 @@ qm_scss_int_reg_t test_scss_int;
#else
#define QM_SCSS_INT_BASE (0xB0800448)
-/** system control subsystem Interrupt masking register block */
#define QM_SCSS_INT ((qm_scss_int_reg_t *)QM_SCSS_INT_BASE)
#endif
#define QM_INT_TIMER_HOST_HALT_MASK BIT(0)
-
#define QM_INT_SRAM_CONTROLLER_HOST_HALT_MASK BIT(16)
#define QM_INT_SRAM_CONTROLLER_HOST_MASK BIT(0)
#define QM_INT_FLASH_CONTROLLER_HOST_HALT_MASK BIT(16)
#define QM_INT_FLASH_CONTROLLER_HOST_MASK BIT(0)
+/** @} */
+
+/**
+ * @name Power Management
+ * @{
+ */
+
+/** Power Management register map. */
typedef struct {
QM_RW uint32_t aon_vr; /**< AON Voltage Regulator */
QM_RW uint32_t reserved[5];
@@ -274,12 +310,18 @@ qm_scss_pmu_reg_t test_scss_pmu;
#else
#define QM_SCSS_PMU_BASE (0xB0800540)
-/** system control subsystem power management register block */
#define QM_SCSS_PMU ((qm_scss_pmu_reg_t *)QM_SCSS_PMU_BASE)
#endif
#define QM_P_STS_HALT_INTERRUPT_REDIRECTION BIT(26)
+/** @} */
+
+/**
+ * @name Always-on controllers.
+ * @{
+ */
+
#define QM_AON_VR_ROK_BUF_VREG_MASK BIT(9)
#define QM_AON_VR_VREG_SEL BIT(8)
#define QM_AON_VR_PASS_CODE (0x9DC4 << 16)
@@ -288,20 +330,19 @@ qm_scss_pmu_reg_t test_scss_pmu;
#define QM_AON_VR_VSEL_1V8 (0x10)
#define QM_AON_VR_VSTRB BIT(5)
-/**
- * Number of SCSS Always on controllers.
- */
+/** Number of SCSS Always-on controllers. */
typedef enum { QM_SCSS_AON_0 = 0, QM_SCSS_AON_NUM } qm_scss_aon_t;
+/** Always-on Controller register map. */
typedef struct {
- QM_RW uint32_t aonc_cnt; /**< Always on counter register */
- QM_RW uint32_t aonc_cfg; /**< Always on counter enable */
- QM_RW uint32_t aonpt_cnt; /**< Always on periodic timer */
+ QM_RW uint32_t aonc_cnt; /**< Always-on counter register. */
+ QM_RW uint32_t aonc_cfg; /**< Always-on counter enable. */
+ QM_RW uint32_t aonpt_cnt; /**< Always-on periodic timer. */
QM_RW uint32_t
- aonpt_stat; /**< Always on periodic timer status register */
- QM_RW uint32_t aonpt_ctrl; /**< Always on periodic timer control */
+ aonpt_stat; /**< Always-on periodic timer status register. */
+ QM_RW uint32_t aonpt_ctrl; /**< Always-on periodic timer control. */
QM_RW uint32_t
- aonpt_cfg; /**< Always on periodic timer configuration register */
+ aonpt_cfg; /**< Always-on periodic timer configuration register. */
} qm_scss_aon_reg_t;
#if (UNIT_TEST)
@@ -310,10 +351,17 @@ qm_scss_aon_reg_t test_scss_aon;
#else
#define QM_SCSS_AON_BASE (0xB0800700)
-/** system control subsystem always on register block */
#define QM_SCSS_AON ((qm_scss_aon_reg_t *)QM_SCSS_AON_BASE)
#endif
+/** @} */
+
+/**
+ * @name Peripheral Registers
+ * @{
+ */
+
+/** Peripheral Registers register map. */
typedef struct {
QM_RW uint32_t periph_cfg0; /**< Peripheral Configuration */
QM_RW uint32_t reserved[2];
@@ -326,10 +374,17 @@ qm_scss_peripheral_reg_t test_scss_peripheral;
#else
#define QM_SCSS_PERIPHERAL_BASE (0xB0800804)
-/** system control subsystem peripheral register block */
#define QM_SCSS_PERIPHERAL ((qm_scss_peripheral_reg_t *)QM_SCSS_PERIPHERAL_BASE)
#endif
+/** @} */
+
+/**
+ * @name Pin MUX
+ * @{
+ */
+
+/** Pin MUX register map. */
typedef struct {
QM_RW uint32_t pmux_pullup[1]; /**< Pin Mux Pullup */
QM_RW uint32_t reserved[3];
@@ -352,10 +407,17 @@ qm_scss_pmux_reg_t test_scss_pmux;
#else
#define QM_SCSS_PMUX_BASE (0xB0800900)
-/** system control subsystem pin muxing register block */
#define QM_SCSS_PMUX ((qm_scss_pmux_reg_t *)QM_SCSS_PMUX_BASE)
#endif
+/** @} */
+
+/**
+ * @name ID
+ * @{
+ */
+
+/** Information register map. */
typedef struct {
QM_RW uint32_t id; /**< Identification Register */
QM_RW uint32_t rev; /**< Revision Register */
@@ -371,11 +433,17 @@ qm_scss_info_reg_t test_scss_info;
#else
#define QM_SCSS_INFO_BASE (0xB0801000)
-/** system control subsystem pin muxing register block */
#define QM_SCSS_INFO ((qm_scss_info_reg_t *)QM_SCSS_INFO_BASE)
#endif
-/** IRQs and interrupt vectors.
+/** @} */
+
+/**
+ * @name IRQs and Interrupts
+ * @{
+ */
+
+/* IRQs and interrupt vectors.
*
* The vector numbers must be defined without arithmetic expressions nor
* parentheses because they are expanded as token concatenation.
@@ -383,93 +451,93 @@ qm_scss_info_reg_t test_scss_info;
#define QM_INT_VECTOR_DOUBLE_FAULT 8
-#define QM_IRQ_RTC_0 (2)
-#define QM_IRQ_RTC_0_MASK_OFFSET (12)
+#define QM_IRQ_RTC_0 2
+#define QM_IRQ_RTC_0_MASK_OFFSET 12
#define QM_IRQ_RTC_0_VECTOR 34
-#define QM_IRQ_AONPT_0 (3)
-#define QM_IRQ_AONPT_0_MASK_OFFSET (32)
+#define QM_IRQ_AONPT_0 3
+#define QM_IRQ_AONPT_0_MASK_OFFSET 32
#define QM_IRQ_AONPT_0_VECTOR 35
-#define QM_IRQ_SPI_MASTER_0 (7)
-#define QM_IRQ_SPI_MASTER_0_MASK_OFFSET (3)
-#define QM_IRQ_SPI_MASTER_0_VECTOR 39
-
-#define QM_IRQ_PWM_0 (11)
-#define QM_IRQ_PWM_0_MASK_OFFSET (10)
+#define QM_IRQ_PWM_0 11
+#define QM_IRQ_PWM_0_MASK_OFFSET 10
#define QM_IRQ_PWM_0_VECTOR 43
-#define QM_IRQ_AC (14)
-#define QM_IRQ_AC_MASK_OFFSET (26)
-#define QM_IRQ_AC_VECTOR 46
+#define QM_IRQ_SPI_MASTER_0 7
+#define QM_IRQ_SPI_MASTER_0_MASK_OFFSET 3
+#define QM_IRQ_SPI_MASTER_0_VECTOR 39
-#define QM_IRQ_ADC_0 (9)
-#define QM_IRQ_ADC_0_MASK_OFFSET (34)
+#define QM_IRQ_ADC_0 9
+#define QM_IRQ_ADC_0_MASK_OFFSET 34
#define QM_IRQ_ADC_0_VECTOR 41
-#define QM_IRQ_ADC_PWR_0 (19)
-#define QM_IRQ_ADC_PWR_0_MASK_OFFSET (33)
+#define QM_IRQ_ADC_PWR_0 19
+#define QM_IRQ_ADC_PWR_0_MASK_OFFSET 33
#define QM_IRQ_ADC_PWR_0_VECTOR 51
-#define QM_IRQ_WDT_0 (16)
-#define QM_IRQ_WDT_0_MASK_OFFSET (13)
+#define QM_IRQ_WDT_0 16
+#define QM_IRQ_WDT_0_MASK_OFFSET 13
#define QM_IRQ_WDT_0_VECTOR 48
-#define QM_IRQ_GPIO_0 (15)
-#define QM_IRQ_GPIO_0_MASK_OFFSET (9)
+#define QM_IRQ_GPIO_0 15
+#define QM_IRQ_GPIO_0_MASK_OFFSET 9
#define QM_IRQ_GPIO_0_VECTOR 47
-#define QM_IRQ_I2C_0 (4)
-#define QM_IRQ_I2C_0_MASK_OFFSET (0)
+#define QM_IRQ_I2C_0 4
+#define QM_IRQ_I2C_0_MASK_OFFSET 0
#define QM_IRQ_I2C_0_VECTOR 36
-#define QM_IRQ_PIC_TIMER (10)
+#define QM_IRQ_PIC_TIMER 10
/* No SCSS mask register for PIC timer: point to an unused register */
-#define QM_IRQ_PIC_TIMER_MASK_OFFSET (1)
+#define QM_IRQ_PIC_TIMER_MASK_OFFSET 1
#define QM_IRQ_PIC_TIMER_VECTOR 42
-#define QM_IRQ_SRAM (17)
-#define QM_IRQ_SRAM_MASK_OFFSET (29)
+#define QM_IRQ_AC 14
+#define QM_IRQ_AC_MASK_OFFSET 26
+#define QM_IRQ_AC_VECTOR 46
+
+#define QM_IRQ_SRAM 17
+#define QM_IRQ_SRAM_MASK_OFFSET 29
#define QM_IRQ_SRAM_VECTOR 49
-#define QM_IRQ_FLASH_0 (18)
-#define QM_IRQ_FLASH_0_MASK_OFFSET (30)
+#define QM_IRQ_FLASH_0 18
+#define QM_IRQ_FLASH_0_MASK_OFFSET 30
#define QM_IRQ_FLASH_0_VECTOR 50
-#define QM_IRQ_UART_0 (8)
-#define QM_IRQ_UART_0_MASK_OFFSET (6)
+#define QM_IRQ_UART_0 8
+#define QM_IRQ_UART_0_MASK_OFFSET 6
#define QM_IRQ_UART_0_VECTOR 40
-#define QM_IRQ_UART_1 (6)
-#define QM_IRQ_UART_1_MASK_OFFSET (7)
+#define QM_IRQ_UART_1 6
+#define QM_IRQ_UART_1_MASK_OFFSET 7
#define QM_IRQ_UART_1_VECTOR 38
-#define QM_IRQ_DMA_0 (13)
-#define QM_IRQ_DMA_0_MASK_OFFSET (14)
+#define QM_IRQ_DMA_0 13
+#define QM_IRQ_DMA_0_MASK_OFFSET 14
#define QM_IRQ_DMA_0_VECTOR 45
-#define QM_IRQ_DMA_1 (12)
-#define QM_IRQ_DMA_1_MASK_OFFSET (15)
+#define QM_IRQ_DMA_1 12
+#define QM_IRQ_DMA_1_MASK_OFFSET 15
#define QM_IRQ_DMA_1_VECTOR 44
-#define QM_IRQ_DMA_ERR (0)
-#define QM_IRQ_DMA_ERR_MASK_OFFSET (28)
+#define QM_IRQ_DMA_ERR 0
+#define QM_IRQ_DMA_ERR_MASK_OFFSET 28
#define QM_IRQ_DMA_ERR_VECTOR 32
+/** @} */
+
/**
- * Number of PWM/Timer controllers.
+ * @name PWM / Timer
+ * @{
*/
+
+/** Number of PWM / Timer controllers. */
typedef enum { QM_PWM_0 = 0, QM_PWM_NUM } qm_pwm_t;
-/**
- * PWM id type.
- */
+/** PWM ID type. */
typedef enum { QM_PWM_ID_0 = 0, QM_PWM_ID_1, QM_PWM_ID_NUM } qm_pwm_id_t;
-/**
- * PWM / Timer register map.
- */
-
+/** PWM / Timer channel register map. */
typedef struct {
QM_RW uint32_t loadcount; /**< Load Count */
QM_RW uint32_t currentvalue; /**< Current Value */
@@ -478,6 +546,7 @@ typedef struct {
QM_RW uint32_t intstatus; /**< Interrupt Status */
} qm_pwm_channel_t;
+/** PWM / Timer register map. */
typedef struct {
qm_pwm_channel_t timer[QM_PWM_ID_NUM]; /**< 4 Timers */
QM_RW uint32_t reserved[30];
@@ -501,14 +570,17 @@ qm_pwm_reg_t test_pwm_t;
#define QM_PWM_INTERRUPT_MASK_OFFSET (2)
+/** @} */
+
/**
- * Number of WDT controllers.
+ * @name WDT
+ * @{
*/
+
+/** Number of WDT controllers. */
typedef enum { QM_WDT_0 = 0, QM_WDT_NUM } qm_wdt_t;
-/**
- * Watchdog timer register block type.
- */
+/** Watchdog timer register map. */
typedef struct {
QM_RW uint32_t wdt_cr; /**< Control Register */
QM_RW uint32_t wdt_torr; /**< Timeout Range Register */
@@ -538,15 +610,17 @@ qm_wdt_reg_t test_wdt;
#define QM_WDT ((qm_wdt_reg_t *)QM_WDT_BASE)
#endif
-/**
- * Number of UART controllers.
- */
-typedef enum { QM_UART_0 = 0, QM_UART_1, QM_UART_NUM } qm_uart_t;
+/** @} */
/**
- * UART register block type.
+ * @name UART
+ * @{
*/
+/** Number of UART controllers. */
+typedef enum { QM_UART_0 = 0, QM_UART_1, QM_UART_NUM } qm_uart_t;
+
+/** UART register map. */
typedef struct {
QM_RW uint32_t rbr_thr_dll; /**< Rx Buffer/ Tx Holding/ Div Latch Low */
QM_RW uint32_t ier_dlh; /**< Interrupt Enable / Divisor Latch High */
@@ -587,14 +661,17 @@ extern qm_uart_reg_t *qm_uart[QM_UART_NUM];
#define QM_UART qm_uart
#endif
+/** @} */
+
/**
- * Number of SPI controllers.
+ * @name SPI
+ * @{
*/
+
+/** Number of SPI controllers. */
typedef enum { QM_SPI_MST_0 = 0, QM_SPI_SLV_0 = 1, QM_SPI_NUM } qm_spi_t;
-/**
- * SPI register block type
- */
+/** SPI register map. */
typedef struct {
QM_RW uint32_t ctrlr0; /**< Control Register 0 */
QM_RW uint32_t ctrlr1; /**< Control Register 1 */
@@ -658,6 +735,8 @@ extern qm_spi_reg_t *qm_spi_controllers[QM_SPI_NUM];
#define QM_SPI_SR_BUSY BIT(0)
#define QM_SPI_SR_TFNF BIT(1)
#define QM_SPI_SR_TFE BIT(2)
+#define QM_SPI_SR_RFNE BIT(3)
+#define QM_SPI_SR_RFF BIT(4)
/* SPI Interrupt Mask register */
#define QM_SPI_IMR_MASK_ALL (0x00)
@@ -685,14 +764,17 @@ extern qm_spi_reg_t *qm_spi_controllers[QM_SPI_NUM];
#define QM_SPI_DMACR_RDMAE BIT(0)
#define QM_SPI_DMACR_TDMAE BIT(1)
+/** @} */
+
/**
- * Number of RTC controllers.
+ * @name RTC
+ * @{
*/
+
+/** Number of RTC controllers. */
typedef enum { QM_RTC_0 = 0, QM_RTC_NUM } qm_rtc_t;
-/**
- * QM RTC Register block type.
- */
+/** RTC register map. */
typedef struct {
QM_RW uint32_t rtc_ccvr; /**< Current Counter Value Register */
QM_RW uint32_t rtc_cmr; /**< Current Match Register */
@@ -709,18 +791,24 @@ qm_rtc_reg_t test_rtc;
#define QM_RTC ((qm_rtc_reg_t *)(&test_rtc))
#else
-/** RTC register base address */
+/** RTC register base address. */
#define QM_RTC_BASE (0xB0000400)
-/** RTC register block */
+/** RTC register block. */
#define QM_RTC ((qm_rtc_reg_t *)QM_RTC_BASE)
#endif
+/** @} */
+
/**
- * Number of I2C controllers.
+ * @name I2C
+ * @{
*/
+
+/** Number of I2C controllers. */
typedef enum { QM_I2C_0 = 0, QM_I2C_NUM } qm_i2c_t;
+/** I2C register map. */
typedef struct {
QM_RW uint32_t ic_con; /**< Control Register */
QM_RW uint32_t ic_tar; /**< Master Target Address */
@@ -785,10 +873,10 @@ qm_i2c_reg_t *test_i2c[QM_I2C_NUM];
#define QM_I2C test_i2c
#else
-/** I2C Master register base address */
+/** I2C Master register base address. */
#define QM_I2C_0_BASE (0xB0002800)
-/** I2C register block */
+/** I2C register block. */
extern qm_i2c_reg_t *qm_i2c[QM_I2C_NUM];
#define QM_I2C qm_i2c
#endif
@@ -810,6 +898,7 @@ extern qm_i2c_reg_t *qm_i2c[QM_I2C_NUM];
#define QM_I2C_IC_DATA_CMD_READ BIT(8)
#define QM_I2C_IC_DATA_CMD_STOP_BIT_CTRL BIT(9)
#define QM_I2C_IC_DATA_CMD_LSB_MASK (0x000000FF)
+#define QM_I2C_IC_RAW_INTR_STAT_RX_FULL BIT(2)
#define QM_I2C_IC_RAW_INTR_STAT_TX_ABRT BIT(6)
#define QM_I2C_IC_TX_ABRT_SOURCE_NAK_MASK (0x1F)
#define QM_I2C_IC_TX_ABRT_SOURCE_ARB_LOST BIT(12)
@@ -845,14 +934,17 @@ extern qm_i2c_reg_t *qm_i2c[QM_I2C_NUM];
#define QM_I2C_IC_DMA_CR_RX_ENABLE BIT(0)
#define QM_I2C_IC_DMA_CR_TX_ENABLE BIT(1)
+/** @} */
+
/**
- * Number of GPIO controllers.
+ * @name GPIO
+ * @{
*/
+
+/** Number of GPIO controllers. */
typedef enum { QM_GPIO_0 = 0, QM_GPIO_NUM } qm_gpio_t;
-/**
- * GPIO register block type.
- */
+/** GPIO register map. */
typedef struct {
QM_RW uint32_t gpio_swporta_dr; /**< Port A Data */
QM_RW uint32_t gpio_swporta_ddr; /**< Port A Data Direction */
@@ -883,6 +975,7 @@ qm_gpio_reg_t *test_gpio[QM_GPIO_NUM];
#define QM_GPIO test_gpio
#else
+
/** GPIO register base address */
#define QM_GPIO_BASE (0xB0000C00)
@@ -891,14 +984,17 @@ extern qm_gpio_reg_t *qm_gpio[QM_GPIO_NUM];
#define QM_GPIO qm_gpio
#endif
+/** @} */
+
/**
- * Number of ADC controllers.
+ * @name ADC
+ * @{
*/
+
+/** Number of ADC controllers. */
typedef enum { QM_ADC_0 = 0, QM_ADC_NUM } qm_adc_t;
-/**
-* ADC register block type.
-*/
+/** ADC register map. */
typedef struct {
QM_RW uint32_t adc_seq0; /**< ADC Channel Sequence Table Entry 0 */
QM_RW uint32_t adc_seq1; /**< ADC Channel Sequence Table Entry 1 */
@@ -960,14 +1056,17 @@ qm_adc_reg_t test_adc;
#define QM_ADC_OP_MODE_DELAY_MASK (0xFFF8)
#define QM_ADC_OP_MODE_OM_MASK (0x7)
+/** @} */
+
/**
- * Number of Flash controllers.
+ * @name Flash
+ * @{
*/
+
+/** Number of Flash controllers. */
typedef enum { QM_FLASH_0 = 0, QM_FLASH_NUM } qm_flash_t;
-/**
- * Flash register block type.
- */
+/** Flash register map. */
typedef struct {
QM_RW uint32_t tmg_ctrl; /**< TMG_CTRL */
QM_RW uint32_t rom_wr_ctrl; /**< ROM_WR_CTRL */
@@ -1001,7 +1100,7 @@ uint8_t test_flash_page[0x800];
#define QM_FLASH_MAX_ADDR (0xFFFFFFFF)
#else
-/** Flash physical address mappings */
+/* Flash physical address mappings */
#define QM_FLASH_REGION_DATA_0_BASE (0x00200000)
#define QM_FLASH_REGION_SYS_0_BASE (0x00180000)
#define QM_FLASH_REGION_OTP_0_BASE (0x00000000)
@@ -1009,12 +1108,13 @@ uint8_t test_flash_page[0x800];
#define QM_FLASH_PAGE_MASK (0xF800)
#define QM_FLASH_MAX_ADDR (0x8000)
-/** Flash controller register base address */
+/** Flash controller register base address. */
#define QM_FLASH_BASE_0 (0xB0100000)
-/** Flash controller register block */
+/** Flash controller register block. */
extern qm_flash_reg_t *qm_flash[QM_FLASH_NUM];
#define QM_FLASH qm_flash
+
#endif
#define QM_FLASH_REGION_DATA_BASE_OFFSET (0x04)
@@ -1024,9 +1124,14 @@ extern qm_flash_reg_t *qm_flash[QM_FLASH_NUM];
(QM_FLASH_MAX_ADDR / (4 * QM_FLASH_PAGE_SIZE_DWORDS))
#define QM_FLASH_LVE_MODE BIT(5)
+/** @} */
+
/**
- * Memory Protection Region register block type.
+ * @name Memory Protection Region
+ * @{
*/
+
+/** Memory Protection Region register map. */
typedef struct {
QM_RW uint32_t mpr_cfg[4]; /**< MPR CFG */
QM_RW uint32_t mpr_vdata; /**< MPR_VDATA */
@@ -1054,14 +1159,20 @@ qm_mpr_reg_t test_mpr;
#define QM_MPR_UP_BOUND_OFFSET (10)
#define QM_MPR_VSTS_VALID BIT(31)
+/** @} */
+
+/**
+ * @name PIC
+ * @{
+ */
+
+/** PIC timer register structure. */
typedef struct {
QM_RW uint32_t reg;
QM_RW uint32_t pad[3];
} pic_timer_reg_pad_t;
-/**
-* PIC timer register block type.
-*/
+/** PIC timer register map. */
typedef struct {
QM_RW pic_timer_reg_pad_t lvttimer; /**< Local Vector Table Timer */
QM_RW pic_timer_reg_pad_t reserved[5];
@@ -1074,19 +1185,66 @@ qm_pic_timer_reg_t test_pic_timer;
#define QM_PIC_TIMER ((qm_pic_timer_reg_t *)(&test_pic_timer))
#else
-/** PIC timer */
+/** PIC timer base address. */
#define QM_PIC_TIMER_BASE (0xFEE00320)
#define QM_PIC_TIMER ((qm_pic_timer_reg_t *)QM_PIC_TIMER_BASE)
#endif
+/** @} */
+
/**
- * MVIC register block type.
+ * @name Peripheral Clock
+ * @{
*/
+
+/** Peripheral clock register map. */
+typedef enum {
+ CLK_PERIPH_REGISTER = BIT(0), /**< Peripheral Clock Gate Enable. */
+ CLK_PERIPH_CLK = BIT(1), /**< Peripheral Clock Enable. */
+ CLK_PERIPH_I2C_M0 = BIT(2), /**< I2C Master 0 Clock Enable. */
+ CLK_PERIPH_SPI_S = BIT(4), /**< SPI Slave Clock Enable. */
+ CLK_PERIPH_SPI_M0 = BIT(5), /**< SPI Master 0 Clock Enable. */
+ CLK_PERIPH_GPIO_INTERRUPT = BIT(7), /**< GPIO Interrupt Clock Enable. */
+ CLK_PERIPH_GPIO_DB = BIT(8), /**< GPIO Debounce Clock Enable. */
+ CLK_PERIPH_WDT_REGISTER = BIT(10), /**< Watchdog Clock Enable. */
+ CLK_PERIPH_RTC_REGISTER = BIT(11), /**< RTC Clock Gate Enable. */
+ CLK_PERIPH_PWM_REGISTER = BIT(12), /**< PWM Clock Gate Enable. */
+ CLK_PERIPH_GPIO_REGISTER = BIT(13), /**< GPIO Clock Gate Enable. */
+ CLK_PERIPH_SPI_M0_REGISTER =
+ BIT(14), /**< SPI Master 0 Clock Gate Enable. */
+ CLK_PERIPH_SPI_S_REGISTER =
+ BIT(16), /**< SPI Slave Clock Gate Enable. */
+ CLK_PERIPH_UARTA_REGISTER = BIT(17), /**< UARTA Clock Gate Enable. */
+ CLK_PERIPH_UARTB_REGISTER = BIT(18), /**< UARTB Clock Gate Enable. */
+ CLK_PERIPH_I2C_M0_REGISTER =
+ BIT(19), /**< I2C Master 0 Clock Gate Enable. */
+ CLK_PERIPH_ADC = BIT(22), /**< ADC Clock Enable. */
+ CLK_PERIPH_ADC_REGISTER = BIT(23), /**< ADC Clock Gate Enable. */
+ CLK_PERIPH_ALL = 0xCFFFFF /**< Quark D2000 peripherals Enable. */
+} clk_periph_t;
+
+/* Default mask values */
+#define CLK_EXTERN_DIV_DEF_MASK (0xFFFFFFE3)
+#define CLK_SYS_CLK_DIV_DEF_MASK (0xFFFFF87F)
+#define CLK_RTC_DIV_DEF_MASK (0xFFFFFF83)
+#define CLK_GPIO_DB_DIV_DEF_MASK (0xFFFFFFE1)
+#define CLK_ADC_DIV_DEF_MASK (0xFC00FFFF)
+#define CLK_PERIPH_DIV_DEF_MASK (0xFFFFFFF9)
+
+/** @} */
+
+/**
+ * @name MVIC
+ * @{
+ */
+
+/** MVIC register structure. */
typedef struct {
QM_RW uint32_t reg;
QM_RW uint32_t pad[3];
} mvic_reg_pad_t;
+/** MVIC register map. */
typedef struct {
QM_RW mvic_reg_pad_t tpr; /**< Task priority*/
QM_RW mvic_reg_pad_t reserved;
@@ -1113,7 +1271,7 @@ qm_mvic_reg_t test_mvic;
#define QM_MVIC ((qm_mvic_reg_t *)(&test_mvic))
#else
-/** Quark Microcontroller D2000 Interrupt Controller */
+/** Interrupt Controller base address. */
#define QM_MVIC_BASE (0xFEE00080)
#define QM_MVIC ((qm_mvic_reg_t *)QM_MVIC_BASE)
#endif
@@ -1142,28 +1300,27 @@ qm_ioapic_reg_t test_ioapic;
#define QM_IOAPIC ((qm_ioapic_reg_t *)QM_IOAPIC_BASE)
#endif
-/** DMA */
+/** @} */
/**
- * DMA instances
+ * @name DMA
+ * @{
*/
+
+/** DMA instances. */
typedef enum {
QM_DMA_0, /**< DMA controller id. */
QM_DMA_NUM /**< Number of DMA controllers. */
} qm_dma_t;
-/**
- * DMA channel IDs
- */
+/** DMA channel IDs. */
typedef enum {
QM_DMA_CHANNEL_0 = 0, /**< DMA channel id for channel 0 */
QM_DMA_CHANNEL_1, /**< DMA channel id for channel 1 */
QM_DMA_CHANNEL_NUM /**< Number of DMA channels */
} qm_dma_channel_id_t;
-/**
- * DMA hardware handshake interfaces
- */
+/** DMA hardware handshake interfaces. */
typedef enum {
DMA_HW_IF_UART_A_TX = 0x0, /**< UART_A_TX */
DMA_HW_IF_UART_A_RX = 0x1, /**< UART_A_RX */
@@ -1177,9 +1334,7 @@ typedef enum {
DMA_HW_IF_I2C_MASTER_0_RX = 0xd, /**< I2C_Master_0_RX */
} qm_dma_handshake_interface_t;
-/**
- * DMA channel register block type
- */
+/** DMA channel register map. */
typedef struct {
QM_RW uint32_t sar_low; /**< SAR */
QM_RW uint32_t sar_high; /**< SAR */
@@ -1205,7 +1360,7 @@ typedef struct {
QM_RW uint32_t dst_sg_high; /**< DSR */
} qm_dma_chan_reg_t;
-/** DMA channel control register offsets and masks */
+/* DMA channel control register offsets and masks. */
#define QM_DMA_CTL_L_INT_EN_MASK BIT(0)
#define QM_DMA_CTL_L_DST_TR_WIDTH_OFFSET (1)
#define QM_DMA_CTL_L_DST_TR_WIDTH_MASK (0x7 << QM_DMA_CTL_L_DST_TR_WIDTH_OFFSET)
@@ -1228,7 +1383,7 @@ typedef struct {
#define QM_DMA_CTL_H_BLOCK_TS_MAX 4095
#define QM_DMA_CTL_H_BLOCK_TS_MIN 1
-/** DMA channel config register offsets and masks */
+/* DMA channel config register offsets and masks. */
#define QM_DMA_CFG_L_CH_SUSP_MASK BIT(8)
#define QM_DMA_CFG_L_FIFO_EMPTY_MASK BIT(9)
#define QM_DMA_CFG_L_HS_SEL_DST_OFFSET 10
@@ -1246,9 +1401,7 @@ typedef struct {
#define QM_DMA_CFG_H_DEST_PER_OFFSET (11)
#define QM_DMA_CFG_H_DEST_PER_MASK (0xf << QM_DMA_CFG_H_DEST_PER_OFFSET)
-/**
- * DMA interrupt register block type
- */
+/** DMA interrupt register map. */
typedef struct {
QM_RW uint32_t raw_tfr_low; /**< RawTfr */
QM_RW uint32_t raw_tfr_high; /**< RawTfr */
@@ -1294,13 +1447,11 @@ typedef struct {
QM_RW uint32_t status_int_high; /**< StatusInt */
} qm_dma_int_reg_t;
-/** DMA interrupt status register bits */
+/* DMA interrupt status register bits. */
#define QM_DMA_INT_STATUS_TFR BIT(0)
#define QM_DMA_INT_STATUS_ERR BIT(4)
-/**
- * DMA miscellaneous register block type
- */
+/** DMA miscellaneous register map. */
typedef struct {
QM_RW uint32_t cfg_low; /**< DmaCfgReg */
QM_RW uint32_t cfg_high; /**< DmaCfgReg */
@@ -1313,10 +1464,10 @@ typedef struct {
QM_RW uint32_t reserved[4]; /**< Reserved */
} qm_dma_misc_reg_t;
-/** Channel write enable in the misc channel enable register */
+/** Channel write enable in the misc channel enable register. */
#define QM_DMA_MISC_CHAN_EN_WE_OFFSET (8)
-/** Controller enable bit in the misc config register */
+/** Controller enable bit in the misc config register. */
#define QM_DMA_MISC_CFG_DMA_EN BIT(0)
typedef struct {
@@ -1336,45 +1487,13 @@ extern qm_dma_reg_t *qm_dma[QM_DMA_NUM];
#define QM_DMA qm_dma
#endif
-/**
- * Peripheral clock type.
- */
-typedef enum {
- CLK_PERIPH_REGISTER = BIT(0), /**< Peripheral Clock Gate Enable. */
- CLK_PERIPH_CLK = BIT(1), /**< Peripheral Clock Enable. */
- CLK_PERIPH_I2C_M0 = BIT(2), /**< I2C Master 0 Clock Enable. */
- CLK_PERIPH_SPI_S = BIT(4), /**< SPI Slave Clock Enable. */
- CLK_PERIPH_SPI_M0 = BIT(5), /**< SPI Master 0 Clock Enable. */
- CLK_PERIPH_GPIO_INTERRUPT = BIT(7), /**< GPIO Interrupt Clock Enable. */
- CLK_PERIPH_GPIO_DB = BIT(8), /**< GPIO Debounce Clock Enable. */
- CLK_PERIPH_WDT_REGISTER = BIT(10), /**< Watchdog Clock Enable. */
- CLK_PERIPH_RTC_REGISTER = BIT(11), /**< RTC Clock Gate Enable. */
- CLK_PERIPH_PWM_REGISTER = BIT(12), /**< PWM Clock Gate Enable. */
- CLK_PERIPH_GPIO_REGISTER = BIT(13), /**< GPIO Clock Gate Enable. */
- CLK_PERIPH_SPI_M0_REGISTER =
- BIT(14), /**< SPI Master 0 Clock Gate Enable. */
- CLK_PERIPH_SPI_S_REGISTER =
- BIT(16), /**< SPI Slave Clock Gate Enable. */
- CLK_PERIPH_UARTA_REGISTER = BIT(17), /**< UARTA Clock Gate Enable. */
- CLK_PERIPH_UARTB_REGISTER = BIT(18), /**< UARTB Clock Gate Enable. */
- CLK_PERIPH_I2C_M0_REGISTER =
- BIT(19), /**< I2C Master 0 Clock Gate Enable. */
- CLK_PERIPH_ADC = BIT(22), /**< ADC Clock Enable. */
- CLK_PERIPH_ADC_REGISTER = BIT(23), /**< ADC Clock Gate Enable. */
- CLK_PERIPH_ALL = 0xCFFFFF /**< Quark D2000 peripherals Enable. */
-} clk_periph_t;
-
-/* Default mask values */
-#define CLK_EXTERN_DIV_DEF_MASK (0xFFFFFFE3)
-#define CLK_SYS_CLK_DIV_DEF_MASK (0xFFFFF87F)
-#define CLK_RTC_DIV_DEF_MASK (0xFFFFFF83)
-#define CLK_GPIO_DB_DIV_DEF_MASK (0xFFFFFFE1)
-#define CLK_ADC_DIV_DEF_MASK (0xFC00FFFF)
-#define CLK_PERIPH_DIV_DEF_MASK (0xFFFFFFF9)
+/** @} */
/**
- * Version variables.
+ * @name Versioning
+ * @{
*/
+
#if (UNIT_TEST)
uint32_t test_rom_version;
#define ROM_VERSION_ADDRESS &test_rom_version;
@@ -1382,7 +1501,8 @@ uint32_t test_rom_version;
#define ROM_VERSION_ADDRESS (0x1FFC);
#endif
-/**
-@}
-*/
+/** @} */
+
+/** @} */
+
#endif /* __REGISTERS_H__ */
diff --git a/ext/hal/qmsi/soc/quark_se/drivers/power_states.c b/ext/hal/qmsi/soc/quark_se/drivers/power_states.c
index 935ededd1..382e30d6d 100644
--- a/ext/hal/qmsi/soc/quark_se/drivers/power_states.c
+++ b/ext/hal/qmsi/soc/quark_se/drivers/power_states.c
@@ -33,32 +33,64 @@
#if (QM_SENSOR)
#include "qm_sensor_regs.h"
#endif
+#include "soc_watch.h"
void power_soc_lpss_enable()
{
QM_SCSS_CCU->ccu_lp_clk_ctl |= QM_SCSS_CCU_SS_LPS_EN;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_LP_CLK_CTL);
}
void power_soc_lpss_disable()
{
QM_SCSS_CCU->ccu_lp_clk_ctl &= ~QM_SCSS_CCU_SS_LPS_EN;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_LP_CLK_CTL);
}
void power_soc_sleep()
{
+#if (QM_SENSOR)
+ /* The sensor cannot be woken up with an edge triggered
+ * interrupt from the RTC.
+ * Switch to Level triggered interrupts.
+ * When waking up, the ROM will configure the RTC back to
+ * its initial settings.
+ */
+ __builtin_arc_sr(QM_IRQ_RTC_0_VECTOR, QM_SS_AUX_IRQ_SELECT);
+ __builtin_arc_sr(QM_SS_IRQ_LEVEL_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
+#endif
+
/* Go to sleep */
QM_SCSS_PMU->slp_cfg &= ~QM_SCSS_SLP_CFG_LPMODE_EN;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_SLP_CFG);
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_SLEEP, 0);
QM_SCSS_PMU->pm1c |= QM_SCSS_PM1C_SLPEN;
}
void power_soc_deep_sleep()
{
- /* Switch to linear regulators */
+#if (QM_SENSOR)
+ /* The sensor cannot be woken up with an edge triggered
+ * interrupt from the RTC.
+ * Switch to Level triggered interrupts.
+ * When waking up, the ROM will configure the RTC back to
+ * its initial settings.
+ */
+ __builtin_arc_sr(QM_IRQ_RTC_0_VECTOR, QM_SS_AUX_IRQ_SELECT);
+ __builtin_arc_sr(QM_SS_IRQ_LEVEL_SENSITIVE, QM_SS_AUX_IRQ_TRIGGER);
+#endif
+
+ /* 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;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_SLP_CFG);
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_SLEEP, 0);
QM_SCSS_PMU->pm1c |= QM_SCSS_PM1C_SLPEN;
}
@@ -71,14 +103,20 @@ void power_cpu_c1()
void power_cpu_c2()
{
QM_SCSS_CCU->ccu_lp_clk_ctl &= ~QM_SCSS_CCU_C2_LP_EN;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_LP_CLK_CTL);
+
/* Read P_LVL2 to trigger a C2 request */
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_SLEEP, 0);
QM_SCSS_PMU->p_lvl2;
}
void power_cpu_c2lp()
{
QM_SCSS_CCU->ccu_lp_clk_ctl |= QM_SCSS_CCU_C2_LP_EN;
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_REGISTER, SOCW_REG_CCU_LP_CLK_CTL);
+
/* Read P_LVL2 to trigger a C2 request */
+ SOC_WATCH_LOG_EVENT(SOCW_EVENT_SLEEP, 0);
QM_SCSS_PMU->p_lvl2;
}
#endif
diff --git a/ext/hal/qmsi/soc/quark_se/include/flash_layout.h b/ext/hal/qmsi/soc/quark_se/include/flash_layout.h
index 499d00ec4..2363de910 100644
--- a/ext/hal/qmsi/soc/quark_se/include/flash_layout.h
+++ b/ext/hal/qmsi/soc/quark_se/include/flash_layout.h
@@ -69,7 +69,7 @@ typedef union {
QM_RW uint16_t osc_trim_4mhz; /**< 4MHz Oscillator trim code. */
} fields;
QM_RW uint32_t osc_trim_u32[2]; /**< Oscillator trim code array.*/
- QM_RW uint16_t osc_trim_u16[2]; /**< Oscillator trim code array.*/
+ QM_RW uint16_t osc_trim_u16[4]; /**< Oscillator trim code array.*/
} qm_flash_data_trim_t;
#if (UNIT_TEST)
@@ -87,6 +87,117 @@ typedef union {
#define QM_FLASH_TRIM_PRESENT_MASK (0xFC00)
#define QM_FLASH_TRIM_PRESENT (0x0000)
+/*
+ * Bootloader data
+ */
+
+/** The flash controller where BL-Data is stored. */
+#define BL_DATA_FLASH_CONTROLLER QM_FLASH_0
+/** The flash region where BL-Data is stored. */
+#define BL_DATA_FLASH_REGION QM_FLASH_REGION_SYS
+/** The flash address where the BL-Data Section starts. */
+#define BL_DATA_FLASH_REGION_BASE QM_FLASH_REGION_SYS_0_BASE
+/** The flash page where the BL-Data Section starts. */
+#define BL_DATA_SECTION_BASE_PAGE (94)
+
+/** The size (in pages) of the System_0 flash region of Quark SE. */
+#define QM_FLASH_REGION_SYS_0_PAGES (96)
+/** The size (in pages) of the System_1 flash region of Quark SE. */
+#define QM_FLASH_REGION_SYS_1_PAGES (96)
+
+/** The size (in pages) of the Bootloader Data section. */
+#define BL_DATA_SECTION_PAGES (2)
+
+#if (BL_CONFIG_DUAL_BANK)
+/* ARC Partition size, in pages */
+#define BL_PARTITION_SIZE_ARC \
+ ((QM_FLASH_REGION_SYS_0_PAGES - BL_DATA_SECTION_PAGES) / 2)
+#define BL_PARTITION_SIZE_LMT (QM_FLASH_REGION_SYS_1_PAGES / 2)
+#else /* !BL_CONFIG_DUAL_BANK */
+#define BL_PARTITION_SIZE_ARC \
+ ((QM_FLASH_REGION_SYS_0_PAGES - BL_DATA_SECTION_PAGES))
+#define BL_PARTITION_SIZE_LMT (QM_FLASH_REGION_SYS_1_PAGES)
+#endif /* BL_CONFIG_DUAL_BANK */
+
+/** Number of boot targets. */
+#define BL_BOOT_TARGETS_NUM (2)
+
+#define BL_TARGET_IDX_LMT (0)
+#define BL_TARGET_IDX_ARC (1)
+
+#define BL_PARTITION_IDX_LMT0 (0)
+#define BL_PARTITION_IDX_ARC0 (1)
+#define BL_PARTITION_IDX_LMT1 (2)
+#define BL_PARTITION_IDX_ARC1 (3)
+
+#define BL_TARGET_0_LMT \
+ { \
+ .active_partition_idx = BL_PARTITION_IDX_LMT0, .svn = 0 \
+ }
+
+#define BL_TARGET_1_ARC \
+ { \
+ .active_partition_idx = BL_PARTITION_IDX_ARC0, .svn = 0 \
+ }
+
+/*
+ * Macro for defining an application flash partition.
+ *
+ * @param[in] target The index of the target associated with the partition.
+ * @param[in] ctrl The flash controller on which the partition is located.
+ * @param[in] region_addr The base address of the region where the partition is
+ * located.
+ * @param[in] size The size in pages of the partition.
+ * @param[in] idx The index of the partition within the flash region (0 for
+ * the first partition in the region, 1 for the second one).
+ */
+#define DEFINE_PARTITION(target, ctrl, region_addr, size, idx) \
+ { \
+ .target_idx = target, .controller = ctrl, \
+ .first_page = (idx * size), .num_pages = size, \
+ .start_addr = ((uint32_t *)region_addr) + \
+ (idx * size * QM_FLASH_PAGE_SIZE_DWORDS), \
+ .is_consistent = true \
+ }
+
+/* PARTITION 0: LMT-0 */
+#define BL_PARTITION_0 \
+ DEFINE_PARTITION(BL_TARGET_IDX_LMT, QM_FLASH_1, \
+ QM_FLASH_REGION_SYS_1_BASE, BL_PARTITION_SIZE_LMT, 0)
+
+/* PARTITION 1: ARC-0 */
+#define BL_PARTITION_1 \
+ DEFINE_PARTITION(BL_TARGET_IDX_ARC, QM_FLASH_0, \
+ QM_FLASH_REGION_SYS_0_BASE, BL_PARTITION_SIZE_ARC, 0)
+
+/* PARTITION 2: LMT-1 */
+#define BL_PARTITION_2 \
+ DEFINE_PARTITION(BL_TARGET_IDX_LMT, QM_FLASH_1, \
+ QM_FLASH_REGION_SYS_1_BASE, BL_PARTITION_SIZE_LMT, 1)
+
+/* PARTITION 3: ARC-1 */
+#define BL_PARTITION_3 \
+ DEFINE_PARTITION(BL_TARGET_IDX_ARC, QM_FLASH_0, \
+ QM_FLASH_REGION_SYS_0_BASE, BL_PARTITION_SIZE_ARC, 1)
+
+#define BL_TARGET_LIST \
+ { \
+ BL_TARGET_0_LMT, BL_TARGET_1_ARC \
+ }
+
+#if BL_CONFIG_DUAL_BANK
+#define BL_PARTITION_LIST \
+ { \
+ BL_PARTITION_0, BL_PARTITION_1, BL_PARTITION_2, BL_PARTITION_3 \
+ }
+#else /* !BL_CONFIG_DUAL_BANK */
+#define BL_PARTITION_LIST \
+ { \
+ BL_PARTITION_0, BL_PARTITION_1 \
+ }
+
+#endif /* BL_CONFIG_DUAL_BANK */
+
/**
* @}
*/
diff --git a/ext/hal/qmsi/soc/quark_se/include/qm_sensor_regs.h b/ext/hal/qmsi/soc/quark_se/include/qm_sensor_regs.h
index 5d202f49c..75ac92004 100644
--- a/ext/hal/qmsi/soc/quark_se/include/qm_sensor_regs.h
+++ b/ext/hal/qmsi/soc/quark_se/include/qm_sensor_regs.h
@@ -234,6 +234,7 @@ typedef enum {
#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)
@@ -358,7 +359,7 @@ typedef enum {
#define QM_SS_ADC_CAL_VAL_GET_OFFSET (5)
#define QM_SS_ADC_CAL_VAL_GET_MASK (0xFE0)
#define QM_SS_ADC_CAL_ACK BIT(4)
-#define QM_SS_ADC_PWR_MODE_STS BIT(3) /*FIXME doesnt match doc */
+#define QM_SS_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 | \
@@ -391,62 +392,62 @@ typedef enum {
* #define QM_SS_xxx - irq number
* #define QM_SS_xxx_VECTOR - vector number
*/
-#define QM_SS_INT_TIMER_0 (16)
-#define QM_SS_INT_TIMER_1 (17)
+#define QM_SS_INT_TIMER_0 16
+#define QM_SS_INT_TIMER_1 17
-#define QM_SS_IRQ_ADC_ERR (0)
-#define QM_SS_IRQ_ADC_ERR_VECTOR (18)
+#define QM_SS_IRQ_ADC_ERR 0
+#define QM_SS_IRQ_ADC_ERR_VECTOR 18
-#define QM_SS_IRQ_ADC_IRQ (1)
-#define QM_SS_IRQ_ADC_IRQ_VECTOR (19)
+#define QM_SS_IRQ_ADC_IRQ 1
+#define QM_SS_IRQ_ADC_IRQ_VECTOR 19
-#define QM_SS_IRQ_GPIO_INTR_0 (2)
-#define QM_SS_IRQ_GPIO_INTR_0_VECTOR (20)
+#define QM_SS_IRQ_GPIO_INTR_0 2
+#define QM_SS_IRQ_GPIO_INTR_0_VECTOR 20
-#define QM_SS_IRQ_GPIO_INTR_1 (3)
-#define QM_SS_IRQ_GPIO_INTR_1_VECTOR (21)
+#define QM_SS_IRQ_GPIO_INTR_1 3
+#define QM_SS_IRQ_GPIO_INTR_1_VECTOR 21
-#define QM_SS_IRQ_I2C_0_ERR (4)
-#define QM_SS_IRQ_I2C_0_ERR_VECTOR (22)
+#define QM_SS_IRQ_I2C_0_ERR 4
+#define QM_SS_IRQ_I2C_0_ERR_VECTOR 22
-#define QM_SS_IRQ_I2C_0_RX_AVAIL (5)
-#define QM_SS_IRQ_I2C_0_RX_AVAIL_VECTOR (23)
+#define QM_SS_IRQ_I2C_0_RX_AVAIL 5
+#define QM_SS_IRQ_I2C_0_RX_AVAIL_VECTOR 23
-#define QM_SS_IRQ_I2C_0_TX_REQ (6)
-#define QM_SS_IRQ_I2C_0_TX_REQ_VECTOR (24)
+#define QM_SS_IRQ_I2C_0_TX_REQ 6
+#define QM_SS_IRQ_I2C_0_TX_REQ_VECTOR 24
-#define QM_SS_IRQ_I2C_0_STOP_DET (7)
-#define QM_SS_IRQ_I2C_0_STOP_DET_VECTOR (25)
+#define QM_SS_IRQ_I2C_0_STOP_DET 7
+#define QM_SS_IRQ_I2C_0_STOP_DET_VECTOR 25
-#define QM_SS_IRQ_I2C_1_ERR (8)
-#define QM_SS_IRQ_I2C_1_ERR_VECTOR (26)
+#define QM_SS_IRQ_I2C_1_ERR 8
+#define QM_SS_IRQ_I2C_1_ERR_VECTOR 26
-#define QM_SS_IRQ_I2C_1_RX_AVAIL (9)
-#define QM_SS_IRQ_I2C_1_RX_AVAIL_VECTOR (27)
+#define QM_SS_IRQ_I2C_1_RX_AVAIL 9
+#define QM_SS_IRQ_I2C_1_RX_AVAIL_VECTOR 27
-#define QM_SS_IRQ_I2C_1_TX_REQ (10)
-#define QM_SS_IRQ_I2C_1_TX_REQ_VECTOR (28)
+#define QM_SS_IRQ_I2C_1_TX_REQ 10
+#define QM_SS_IRQ_I2C_1_TX_REQ_VECTOR 28
-#define QM_SS_IRQ_I2C_1_STOP_DET (11)
-#define QM_SS_IRQ_I2C_1_STOP_DET_VECTOR (29)
+#define QM_SS_IRQ_I2C_1_STOP_DET 11
+#define QM_SS_IRQ_I2C_1_STOP_DET_VECTOR 29
-#define QM_SS_IRQ_SPI_0_ERR_INT (12)
-#define QM_SS_IRQ_SPI_0_ERR_INT_VECTOR (30)
+#define QM_SS_IRQ_SPI_0_ERR_INT 12
+#define QM_SS_IRQ_SPI_0_ERR_INT_VECTOR 30
-#define QM_SS_IRQ_SPI_0_RX_AVAIL (13)
-#define QM_SS_IRQ_SPI_0_RX_AVAIL_VECTOR (31)
+#define QM_SS_IRQ_SPI_0_RX_AVAIL 13
+#define QM_SS_IRQ_SPI_0_RX_AVAIL_VECTOR 31
-#define QM_SS_IRQ_SPI_0_TX_REQ (14)
-#define QM_SS_IRQ_SPI_0_TX_REQ_VECTOR (32)
+#define QM_SS_IRQ_SPI_0_TX_REQ 14
+#define QM_SS_IRQ_SPI_0_TX_REQ_VECTOR 32
-#define QM_SS_IRQ_SPI_1_ERR_INT (15)
-#define QM_SS_IRQ_SPI_1_ERR_INT_VECTOR (33)
+#define QM_SS_IRQ_SPI_1_ERR_INT 15
+#define QM_SS_IRQ_SPI_1_ERR_INT_VECTOR 33
-#define QM_SS_IRQ_SPI_1_RX_AVAIL (16)
-#define QM_SS_IRQ_SPI_1_RX_AVAIL_VECTOR (34)
+#define QM_SS_IRQ_SPI_1_RX_AVAIL 16
+#define QM_SS_IRQ_SPI_1_RX_AVAIL_VECTOR 34
-#define QM_SS_IRQ_SPI_1_TX_REQ (17)
-#define QM_SS_IRQ_SPI_1_TX_REQ_VECTOR (35)
+#define QM_SS_IRQ_SPI_1_TX_REQ 17
+#define QM_SS_IRQ_SPI_1_TX_REQ_VECTOR 35
typedef enum {
QM_SS_INT_PRIORITY_0 = 0,
@@ -468,7 +469,7 @@ typedef enum {
#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_TRIGER (0x40D)
+#define QM_SS_AUX_IRQ_TRIGGER (0x40D)
/** @} */
diff --git a/ext/hal/qmsi/soc/quark_se/include/qm_soc_regs.h b/ext/hal/qmsi/soc/quark_se/include/qm_soc_regs.h
index 1202237d1..e0d37577a 100644
--- a/ext/hal/qmsi/soc/quark_se/include/qm_soc_regs.h
+++ b/ext/hal/qmsi/soc/quark_se/include/qm_soc_regs.h
@@ -33,10 +33,10 @@
#include "qm_common.h"
/**
- * Quark SE SOC Register file.
- *
- * @brief Quark SE SOC Registers.
+ * Quark SE SoC Registers.
*
+ * @defgroup groupQUARKSESEREG SoC Registers (SE)
+ * @{
*/
#define QUARK_SE (1)
@@ -49,12 +49,11 @@
#endif
/**
- * @defgroup groupSEREG Quark SE Registers
- @{
+ * @name System Core
+ * @{
*/
-/* Core system registers */
-
+/** System Core register map. */
typedef struct {
QM_RW uint32_t osc0_cfg0; /**< Hybrid Oscillator Configuration 0 */
QM_RW uint32_t osc0_stat1; /**< Hybrid Oscillator status 1 */
@@ -65,14 +64,13 @@ typedef struct {
QM_RW uint32_t
ccu_periph_clk_gate_ctl; /**< Peripheral Clock Gate Control */
QM_RW uint32_t
- ccu_periph_clk_div_ctl0; /**< Peripheral Clock Divider Control 0 */
+ ccu_periph_clk_div_ctl0; /**< Peripheral Clock Divider Control 0 */
QM_RW uint32_t
ccu_gpio_db_clk_ctl; /**< Peripheral Clock Divider Control 1 */
QM_RW uint32_t
ccu_ext_clock_ctl; /**< External Clock Control Register */
- QM_RW uint32_t ccu_ss_periph_clk_gate_ctl; /**< Sensor Subsystem
- peripheral clock gate
- control */
+ /** Sensor Subsystem peripheral clock gate control */
+ QM_RW uint32_t ccu_ss_periph_clk_gate_ctl;
QM_RW uint32_t ccu_lp_clk_ctl; /**< System Low Power Clock Control */
QM_RW uint32_t reserved;
QM_RW uint32_t ccu_mlayer_ahb_ctl; /**< AHB Control Register */
@@ -80,7 +78,6 @@ typedef struct {
QM_RW uint32_t osc_lock_0; /**< Clocks Lock Register */
} qm_scss_ccu_reg_t;
-/** system control subsystem clock control unit register block */
#if (UNIT_TEST)
qm_scss_ccu_reg_t test_scss_ccu;
#define QM_SCSS_CCU ((qm_scss_ccu_reg_t *)(&test_scss_ccu))
@@ -90,19 +87,66 @@ qm_scss_ccu_reg_t test_scss_ccu;
#define QM_SCSS_CCU ((qm_scss_ccu_reg_t *)QM_SCSS_CCU_BASE)
#endif
+/* Hybrid oscillator output select select (0=Silicon, 1=Crystal) */
+#define QM_OSC0_MODE_SEL BIT(3)
+#define QM_OSC0_PD BIT(2)
+#define QM_OSC1_PD BIT(1)
+
+/* Enable Crystal oscillator. */
+#define QM_OSC0_EN_CRYSTAL BIT(0)
+
+/* Crystal oscillator parameters. */
+#define OSC0_CFG1_OSC0_FADJ_XTAL_MASK (0x000F0000)
+#define OSC0_CFG1_OSC0_FADJ_XTAL_OFFS (16)
+#define OSC0_CFG0_OSC0_XTAL_COUNT_VALUE_MASK (0x00600000)
+#define OSC0_CFG0_OSC0_XTAL_COUNT_VALUE_OFFS (21)
+
+/* Silicon Oscillator parameters. */
+#define OSC0_CFG1_FTRIMOTP_MASK (0x3FF00000)
+#define OSC0_CFG1_FTRIMOTP_OFFS (20)
+#define OSC0_CFG1_SI_FREQ_SEL_MASK (0x00000300)
+#define OSC0_CFG1_SI_FREQ_SEL_OFFS (8)
+
#define QM_OSC0_MODE_SEL BIT(3)
#define QM_OSC0_LOCK_SI BIT(0)
#define QM_OSC0_LOCK_XTAL BIT(1)
#define QM_OSC0_EN_SI_OSC BIT(1)
-#define QM_OSC0_PD BIT(2)
-#define QM_OSC1_PD BIT(1)
+
#define QM_SI_OSC_1V2_MODE BIT(0)
+
+/** Peripheral clock divider control */
+#define QM_CCU_PERIPH_PCLK_DIV_OFFSET (1)
+#define QM_CCU_PERIPH_PCLK_DIV_EN BIT(0)
+
+/* Clock enable / disable register. */
+#define QM_CCU_MLAYER_AHB_CTL (REG_VAL(0xB0800034))
+
+/* System clock control */
+#define QM_CCU_SYS_CLK_SEL BIT(0)
#define QM_SCSS_CCU_SYS_CLK_SEL BIT(0)
#define QM_SCSS_CCU_C2_LP_EN (1)
#define QM_SCSS_CCU_SS_LPS_EN (0)
+#define QM_CCU_RTC_CLK_EN BIT(1)
+#define QM_CCU_RTC_CLK_DIV_EN BIT(2)
+#define QM_CCU_SYS_CLK_DIV_EN BIT(7)
+#define QM_CCU_SYS_CLK_DIV_MASK (0x00000300)
#define QM_OSC0_SI_FREQ_SEL_DEF_MASK (0xFFFFFCFF)
+#define QM_CCU_GPIO_DB_DIV_OFFSET (2)
+#define QM_CCU_GPIO_DB_CLK_DIV_EN BIT(1)
+#define QM_CCU_GPIO_DB_CLK_EN BIT(0)
+#define QM_CCU_RTC_CLK_DIV_OFFSET (3)
+#define QM_CCU_SYS_CLK_DIV_OFFSET (8)
+#define QM_CCU_DMA_CLK_EN BIT(6)
+
+/** @} */
+/**
+ * @name General Purpose
+ * @{
+ */
+
+/** General Purpose register map. */
typedef struct {
QM_RW uint32_t gps0; /**< General Purpose Sticky Register 0 */
QM_RW uint32_t gps1; /**< General Purpose Sticky Register 1 */
@@ -121,17 +165,23 @@ typedef struct {
wo_st; /**< Write-One-to-Set Sticky Scratchpad Register */
} qm_scss_gp_reg_t;
-/** system control subsystem general purpose register block */
#if (UNIT_TEST)
qm_scss_gp_reg_t test_scss_gp;
#define QM_SCSS_GP ((qm_scss_gp_reg_t *)(&test_scss_gp))
#else
#define QM_SCSS_GP_BASE (0xB0800100)
-/** system control subsystem general purpose register block */
#define QM_SCSS_GP ((qm_scss_gp_reg_t *)QM_SCSS_GP_BASE)
#endif
+/** @} */
+
+/**
+ * @name Memory Control
+ * @{
+ */
+
+/** Memory Control register map. */
typedef struct {
QM_RW uint32_t mem_ctrl; /**< Memory control */
} qm_scss_mem_reg_t;
@@ -141,19 +191,26 @@ qm_scss_mem_reg_t test_scss_mem;
#define QM_SCSS_MEM ((qm_scss_mem_reg_t *)(&test_scss_mem))
#else
-/** system control subsystem memory control register block */
#define QM_SCSS_MEM_BASE (0xB0800200)
#define QM_SCSS_MEM ((qm_scss_mem_reg_t *)QM_SCSS_MEM_BASE)
#endif
+/** @} */
+
+/**
+ * @name Comparator
+ * @{
+ */
+
+/** Comparator register map. */
typedef struct {
- QM_RW uint32_t cmp_en; /**< Comparator enable */
- QM_RW uint32_t cmp_ref_sel; /**< Comparator reference select */
+ QM_RW uint32_t cmp_en; /**< Comparator enable. */
+ QM_RW uint32_t cmp_ref_sel; /**< Comparator reference select. */
QM_RW uint32_t
- cmp_ref_pol; /**< Comparator reference polarity select register */
- QM_RW uint32_t cmp_pwr; /**< Comparator power enable register */
+ cmp_ref_pol; /**< Comparator reference polarity select register. */
+ QM_RW uint32_t cmp_pwr; /**< Comparator power enable register. */
QM_RW uint32_t reserved[6];
- QM_RW uint32_t cmp_stat_clr; /**< Comparator clear register */
+ QM_RW uint32_t cmp_stat_clr; /**< Comparator clear register. */
} qm_scss_cmp_reg_t;
#if (UNIT_TEST)
@@ -161,18 +218,25 @@ qm_scss_cmp_reg_t test_scss_cmp;
#define QM_SCSS_CMP ((qm_scss_cmp_reg_t *)(&test_scss_cmp))
#else
-/** system control subsystem comparators register block */
#define QM_SCSS_CMP_BASE (0xB0800300)
#define QM_SCSS_CMP ((qm_scss_cmp_reg_t *)QM_SCSS_CMP_BASE)
#endif
#define QM_AC_HP_COMPARATORS_MASK (0x7FFC0)
+/** @} */
+
+/**
+ * @name APIC
+ * @{
+ */
+
typedef struct {
QM_RW uint32_t reg;
QM_RW uint32_t pad[3];
} apic_reg_pad_t;
+/** APIC register block type. */
typedef struct {
QM_RW apic_reg_pad_t reserved0[2];
QM_RW apic_reg_pad_t id; /**< LAPIC ID */
@@ -247,11 +311,19 @@ qm_ioapic_reg_t test_ioapic;
#define QM_IOAPIC ((qm_ioapic_reg_t *)(&test_ioapic))
#else
-/** IO/APIC */
+/** IO / APIC base address. */
#define QM_IOAPIC_BASE (0xFEC00000)
#define QM_IOAPIC ((qm_ioapic_reg_t *)QM_IOAPIC_BASE)
#endif
+/** @} */
+
+/**
+ * @name Interrupt
+ * @{
+ */
+
+/** SS I2C Interrupt register map. */
typedef struct {
QM_RW uint32_t err_mask;
QM_RW uint32_t rx_avail_mask;
@@ -259,12 +331,14 @@ typedef struct {
QM_RW uint32_t stop_det_mask;
} int_ss_i2c_reg_t;
+/** SS SPI Interrupt register map. */
typedef struct {
QM_RW uint32_t err_int_mask;
QM_RW uint32_t rx_avail_mask;
QM_RW uint32_t tx_req_mask;
} int_ss_spi_reg_t;
+/** Interrupt register map. */
typedef struct {
QM_RW uint32_t int_ss_adc_err_mask;
QM_RW uint32_t int_ss_adc_irq_mask;
@@ -303,14 +377,17 @@ typedef struct {
QM_RW uint32_t int_comparators_host_mask;
QM_RW uint32_t int_host_bus_err_mask;
QM_RW uint32_t int_dma_error_mask;
- QM_RW uint32_t int_sram_controller_mask;
- QM_RW uint32_t int_flash_controller_0_mask;
- QM_RW uint32_t int_flash_controller_1_mask;
- QM_RW uint32_t int_aon_timer_mask;
- QM_RW uint32_t int_adc_pwr_mask;
- QM_RW uint32_t int_adc_calib_mask;
+ QM_RW uint32_t
+ int_sram_controller_mask; /**< Interrupt Routing Mask 28 */
+ QM_RW uint32_t
+ int_flash_controller_0_mask; /**< Interrupt Routing Mask 29 */
+ QM_RW uint32_t
+ int_flash_controller_1_mask; /**< Interrupt Routing Mask 30 */
+ QM_RW uint32_t int_aon_timer_mask; /**< Interrupt Routing Mask 31 */
+ QM_RW uint32_t int_adc_pwr_mask; /**< Interrupt Routing Mask 32 */
+ QM_RW uint32_t int_adc_calib_mask; /**< Interrupt Routing Mask 33 */
QM_RW uint32_t int_aon_gpio_mask;
- QM_RW uint32_t lock_int_mask_reg;
+ QM_RW uint32_t lock_int_mask_reg; /**< Interrupt Mask Lock Register */
} qm_scss_int_reg_t;
/** Number of SCSS interrupt mask registers (excluding mask lock register) */
@@ -325,7 +402,7 @@ qm_scss_int_reg_t test_scss_int;
#define QM_SCSS_INT ((qm_scss_int_reg_t *)(&test_scss_int))
#else
-/** system control subsystem Interrupt masking register block */
+/* System control subsystem interrupt masking register block. */
#define QM_SCSS_INT_BASE (0xB0800400)
#define QM_SCSS_INT ((qm_scss_int_reg_t *)QM_SCSS_INT_BASE)
#endif
@@ -338,7 +415,17 @@ qm_scss_int_reg_t test_scss_int;
#define QM_INT_FLASH_CONTROLLER_HOST_MASK BIT(0)
#define QM_INT_FLASH_CONTROLLER_SS_HALT_MASK BIT(24)
#define QM_INT_FLASH_CONTROLLER_SS_MASK BIT(8)
+#define QM_INT_ADC_PWR_MASK BIT(8)
+#define QM_INT_ADC_CALIB_MASK BIT(8)
+
+/** @} */
+
+/**
+ * @name Power Management
+ * @{
+ */
+/** Power Management register map. */
typedef struct {
QM_RW uint32_t p_lvl2; /**< Processor level 2 */
QM_RW uint32_t reserved[4];
@@ -349,19 +436,17 @@ typedef struct {
QM_RW uint32_t plat1p8_vr; /**< Platform 1p8 voltage regulator */
QM_RW uint32_t host_vr; /**< Host Voltage Regulator */
QM_RW uint32_t slp_cfg; /**< Sleeping Configuration */
- QM_RW uint32_t
- pmnetcs; /**< Power Management Network (PMNet) Control and
-Status */
+ /** Power Management Network (PMNet) Control and Status */
+ QM_RW uint32_t pmnetcs;
QM_RW uint32_t pm_wait; /**< Power Management Wait */
QM_RW uint32_t reserved2;
QM_RW uint32_t p_sts; /**< Processor Status */
QM_RW uint32_t reserved3[3];
- QM_RW uint32_t rstc; /**< Reset control */
- QM_RW uint32_t rsts; /**< Reset status */
+ QM_RW uint32_t rstc; /**< Reset Control */
+ QM_RW uint32_t rsts; /**< Reset Status */
QM_RW uint32_t reserved4[6];
QM_RW uint32_t vr_lock; /**< Voltage regulator lock */
- QM_RW uint32_t pm_lock; /**< Power management lock */
-
+ QM_RW uint32_t pm_lock; /**< Power Management Lock */
} qm_scss_pmu_reg_t;
#if (UNIT_TEST)
@@ -369,7 +454,6 @@ qm_scss_pmu_reg_t test_scss_pmu;
#define QM_SCSS_PMU ((qm_scss_pmu_reg_t *)(&test_scss_pmu))
#else
-/** system control subsystem power management register block */
#define QM_SCSS_PMU_BASE (0xB0800504)
#define QM_SCSS_PMU ((qm_scss_pmu_reg_t *)QM_SCSS_PMU_BASE)
#endif
@@ -378,6 +462,13 @@ qm_scss_pmu_reg_t test_scss_pmu;
#define QM_P_STS_HALT_INTERRUPT_REDIRECTION BIT(26)
#define QM_P_STS_ARC_HALT BIT(14)
+/** @} */
+
+/**
+ * @name Sensor Subsystem
+ * @{
+ */
+
#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)
@@ -391,13 +482,7 @@ qm_scss_pmu_reg_t test_scss_pmu;
#define QM_SCSS_VR_EN BIT(7)
#define QM_SCSS_VR_VREG_SEL BIT(6)
-#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)
-
+/** Sensor Subsystem register map. */
typedef struct {
QM_RW uint32_t ss_cfg; /**< Sensor Subsystem Configuration */
QM_RW uint32_t ss_sts; /**< Sensor Subsystem status */
@@ -408,25 +493,39 @@ qm_scss_ss_reg_t test_scss_ss;
#define QM_SCSS_SS ((qm_scss_ss_reg_t *)(&test_scss_ss))
#else
-/** system control subsystem sensor subsystem register block */
#define QM_SCSS_SS_BASE (0xB0800600)
#define QM_SCSS_SS ((qm_scss_ss_reg_t *)QM_SCSS_SS_BASE)
#endif
+#define QM_SS_STS_HALT_INTERRUPT_REDIRECTION BIT(26)
+
+/** @} */
+
/**
- * Number of SCSS Always on controllers.
+ * @name Always-on controllers.
+ * @{
*/
+
+#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)
+
+/** Number of SCSS Always-on controllers. */
typedef enum { QM_SCSS_AON_0 = 0, QM_SCSS_AON_NUM } qm_scss_aon_t;
+/** Always-on Controller register map. */
typedef struct {
- QM_RW uint32_t aonc_cnt; /**< Always on counter register */
- QM_RW uint32_t aonc_cfg; /**< Always on counter enable */
- QM_RW uint32_t aonpt_cnt; /**< Always on periodic timer */
+ QM_RW uint32_t aonc_cnt; /**< Always-on counter register. */
+ QM_RW uint32_t aonc_cfg; /**< Always-on counter enable. */
+ QM_RW uint32_t aonpt_cnt; /**< Always-on periodic timer. */
QM_RW uint32_t
- aonpt_stat; /**< Always on periodic timer status register */
- QM_RW uint32_t aonpt_ctrl; /**< Always on periodic timer control */
+ aonpt_stat; /**< Always-on periodic timer status register. */
+ QM_RW uint32_t aonpt_ctrl; /**< Always-on periodic timer control. */
QM_RW uint32_t
- aonpt_cfg; /**< Always on periodic timer configuration register */
+ aonpt_cfg; /**< Always-on periodic timer configuration register. */
} qm_scss_aon_reg_t;
#if (UNIT_TEST)
@@ -434,11 +533,18 @@ qm_scss_aon_reg_t test_scss_aon;
#define QM_SCSS_AON ((qm_scss_aon_reg_t *)(&test_scss_aon))
#else
-/** system control subsystem always on register block */
#define QM_SCSS_AON_BASE (0xB0800700)
#define QM_SCSS_AON ((qm_scss_aon_reg_t *)QM_SCSS_AON_BASE)
#endif
+/** @} */
+
+/**
+ * @name Peripheral Registers
+ * @{
+ */
+
+/** Peripheral Registers register map. */
typedef struct {
QM_RW uint32_t usb_phy_cfg0; /**< USB Configuration */
QM_RW uint32_t periph_cfg0; /**< Peripheral Configuration */
@@ -451,11 +557,18 @@ qm_scss_peripheral_reg_t test_scss_peripheral;
#define QM_SCSS_PERIPHERAL ((qm_scss_peripheral_reg_t *)(&test_scss_peripheral))
#else
-/** system control subsystem peripheral register block */
#define QM_SCSS_PERIPHERAL_BASE (0xB0800800)
#define QM_SCSS_PERIPHERAL ((qm_scss_peripheral_reg_t *)QM_SCSS_PERIPHERAL_BASE)
#endif
+/** @} */
+
+/**
+ * @name Pin MUX
+ * @{
+ */
+
+/** Pin MUX register map. */
typedef struct {
QM_RW uint32_t pmux_pullup[4]; /**< Pin Mux Pullup */
QM_RW uint32_t pmux_slew[4]; /**< Pin Mux Slew Rate */
@@ -473,22 +586,55 @@ qm_scss_pmux_reg_t test_scss_pmux;
#define QM_SCSS_PMUX ((qm_scss_pmux_reg_t *)(&test_scss_pmux))
#else
-/** system control subsystem pin muxing register block */
#define QM_SCSS_PMUX_BASE (0xB0800900)
#define QM_SCSS_PMUX ((qm_scss_pmux_reg_t *)QM_SCSS_PMUX_BASE)
#endif
+/* Pin MUX slew rate registers and settings */
+#define QM_PMUX_SLEW_4MA_DRIVER (0xFFFFFFFF)
+#define QM_PMUX_SLEW0 (REG_VAL(0xB0800910))
+#define QM_PMUX_SLEW1 (REG_VAL(0xB0800914))
+#define QM_PMUX_SLEW2 (REG_VAL(0xB0800918))
+#define QM_PMUX_SLEW3 (REG_VAL(0xB080091C))
+
+/** @} */
+
/**
- * Mailbox
+ * @name ID
+ * @{
*/
+
+/** Information register map. */
+typedef struct {
+ QM_RW uint32_t id;
+} qm_scss_info_reg_t;
+
+#if (UNIT_TEST)
+qm_scss_info_reg_t test_scss_info;
+#define QM_SCSS_INFO ((qm_scss_info_reg_t *)(&test_scss_info))
+
+#else
+#define QM_SCSS_INFO_BASE (0xB0801000)
+#define QM_SCSS_INFO ((qm_scss_info_reg_t *)QM_SCSS_INFO_BASE)
+#endif
+
+/** @} */
+
+/**
+ * @name Mailbox
+ * @{
+ */
+
#define QM_MBOX_TRIGGER_CH_INT BIT(31)
+/** Mailbox register structure. */
typedef struct {
QM_RW uint32_t ch_ctrl; /**< Channel Control Word */
QM_RW uint32_t ch_data[4]; /**< Channel Payload Data Word 0 */
QM_RW uint32_t ch_sts; /**< Channel status */
} qm_mailbox_t;
+/** Mailbox register map. */
typedef struct {
qm_mailbox_t mbox[8]; /**< 8 Mailboxes */
QM_RW uint32_t mbox_chall_sts; /**< All channel status */
@@ -499,35 +645,154 @@ qm_scss_mailbox_reg_t test_scss_mailbox;
#define QM_SCSS_MAILBOX ((qm_scss_mailbox_reg_t *)(&test_scss_mailbox))
#else
-/** system control subsystem mailbox register block */
#define QM_SCSS_MAILBOX_BASE (0xB0800A00)
#define QM_SCSS_MAILBOX ((qm_scss_mailbox_reg_t *)QM_SCSS_MAILBOX_BASE)
#endif
-typedef struct {
- QM_RW uint32_t id;
-} qm_scss_info_reg_t;
+/** @} */
-#if (UNIT_TEST)
-qm_scss_info_reg_t test_scss_info;
-#define QM_SCSS_INFO ((qm_scss_info_reg_t *)(&test_scss_info))
+/**
+ * @name IRQs and Interrupts
+ * @{
+ */
-#else
-/** system control subsystem information register block */
-#define QM_SCSS_INFO_BASE (0xB0801000)
-#define QM_SCSS_INFO ((qm_scss_info_reg_t *)QM_SCSS_INFO_BASE)
-#endif
+/* IRQs and interrupt vectors.
+ *
+ * Any IRQ > 1 actually has a SCSS mask register offset of +1.
+ * The vector numbers must be defined without arithmetic expressions nor
+ * parentheses because they are expanded as token concatenation.
+ */
+
+#define QM_INT_VECTOR_DOUBLE_FAULT 8
+#define QM_INT_VECTOR_PIC_TIMER 32
+
+#define QM_IRQ_RTC_0 11
+#define QM_IRQ_RTC_0_MASK_OFFSET 12
+#define QM_IRQ_RTC_0_VECTOR 47
-/* Peripheral registers */
+#define QM_IRQ_PWM_0 9
+#define QM_IRQ_PWM_0_MASK_OFFSET 10
+#define QM_IRQ_PWM_0_VECTOR 45
+
+#define QM_IRQ_USB_0 (10)
+#define QM_IRQ_USB_0_MASK_OFFSET (11)
+#define QM_IRQ_USB_0_VECTOR 46
+
+#define QM_IRQ_SPI_MASTER_0 2
+#define QM_IRQ_SPI_MASTER_0_MASK_OFFSET 3
+#define QM_IRQ_SPI_MASTER_0_VECTOR 38
+
+#define QM_IRQ_SPI_MASTER_1 3
+#define QM_IRQ_SPI_MASTER_1_MASK_OFFSET 4
+#define QM_IRQ_SPI_MASTER_1_VECTOR 39
+
+#define QM_IRQ_WDT_0 12
+#define QM_IRQ_WDT_0_MASK_OFFSET 13
+#define QM_IRQ_WDT_0_VECTOR 48
+
+#define QM_IRQ_GPIO_0 8
+#define QM_IRQ_GPIO_0_MASK_OFFSET 9
+#define QM_IRQ_GPIO_0_VECTOR 44
+
+#define QM_IRQ_I2C_0 0
+#define QM_IRQ_I2C_0_MASK_OFFSET 0
+#define QM_IRQ_I2C_0_VECTOR 36
+
+#define QM_IRQ_I2C_1 1
+#define QM_IRQ_I2C_1_MASK_OFFSET 1
+#define QM_IRQ_I2C_1_VECTOR 37
+
+#define QM_IRQ_MBOX 21
+#define QM_IRQ_MBOX_MASK_OFFSET 22
+#define QM_IRQ_MBOX_VECTOR 57
+
+#define QM_IRQ_AC 22
+#define QM_IRQ_AC_MASK_OFFSET 26
+#define QM_IRQ_AC_VECTOR 58
+
+#define QM_IRQ_SRAM 25
+#define QM_IRQ_SRAM_MASK_OFFSET 29
+#define QM_IRQ_SRAM_VECTOR 61
+
+#define QM_IRQ_FLASH_0 26
+#define QM_IRQ_FLASH_0_MASK_OFFSET 30
+#define QM_IRQ_FLASH_0_VECTOR 62
+
+#define QM_IRQ_FLASH_1 27
+#define QM_IRQ_FLASH_1_MASK_OFFSET 31
+#define QM_IRQ_FLASH_1_VECTOR 63
+
+#define QM_IRQ_AONPT_0 28
+#define QM_IRQ_AONPT_0_MASK_OFFSET 32
+#define QM_IRQ_AONPT_0_VECTOR 64
+
+#define QM_IRQ_AONGPIO_0 31
+#define QM_IRQ_AONGPIO_0_MASK_OFFSET 35
+#define QM_IRQ_AONGPIO_0_VECTOR 67
+
+#define QM_IRQ_UART_0 5
+#define QM_IRQ_UART_0_MASK_OFFSET 6
+#define QM_IRQ_UART_0_VECTOR 41
+
+#define QM_IRQ_UART_1 6
+#define QM_IRQ_UART_1_MASK_OFFSET 7
+#define QM_IRQ_UART_1_VECTOR 42
+
+#define QM_IRQ_DMA_0 13
+#define QM_IRQ_DMA_0_MASK_OFFSET 14
+#define QM_IRQ_DMA_0_VECTOR 49
+
+#define QM_IRQ_DMA_1 14
+#define QM_IRQ_DMA_1_MASK_OFFSET 15
+#define QM_IRQ_DMA_1_VECTOR 50
+
+#define QM_IRQ_DMA_2 15
+#define QM_IRQ_DMA_2_MASK_OFFSET 16
+#define QM_IRQ_DMA_2_VECTOR 51
+
+#define QM_IRQ_DMA_3 16
+#define QM_IRQ_DMA_3_MASK_OFFSET 17
+#define QM_IRQ_DMA_3_VECTOR 52
+
+#define QM_IRQ_DMA_4 17
+#define QM_IRQ_DMA_4_MASK_OFFSET 18
+#define QM_IRQ_DMA_4_VECTOR 53
+
+#define QM_IRQ_DMA_5 18
+#define QM_IRQ_DMA_5_MASK_OFFSET 19
+#define QM_IRQ_DMA_5_VECTOR 54
+
+#define QM_IRQ_DMA_6 19
+#define QM_IRQ_DMA_6_MASK_OFFSET 20
+#define QM_IRQ_DMA_6_VECTOR 55
+
+#define QM_IRQ_DMA_7 20
+#define QM_IRQ_DMA_7_MASK_OFFSET 21
+#define QM_IRQ_DMA_7_VECTOR 56
+
+#define QM_IRQ_DMA_ERR 24
+#define QM_IRQ_DMA_ERR_MASK_OFFSET 28
+#define QM_IRQ_DMA_ERR_VECTOR 60
+
+#define QM_SS_IRQ_ADC_PWR 29
+#define QM_SS_IRQ_ADC_PWR_MASK_OFFSET 33
+#define QM_SS_IRQ_ADC_PWR_VECTOR 65
+
+#define QM_SS_IRQ_ADC_CAL 30
+#define QM_SS_IRQ_ADC_CAL_MASK_OFFSET 34
+#define QM_SS_IRQ_ADC_CAL_VECTOR 66
+
+/** @} */
/**
- * Number of PWM/Timer controllers.
+ * @name PWM / Timer
+ * @{
*/
+
+/** Number of PWM / Timer controllers. */
typedef enum { QM_PWM_0 = 0, QM_PWM_NUM } qm_pwm_t;
-/**
- * PWM id type.
- */
+/** PWM ID type. */
typedef enum {
QM_PWM_ID_0 = 0,
QM_PWM_ID_1,
@@ -536,10 +801,7 @@ typedef enum {
QM_PWM_ID_NUM
} qm_pwm_id_t;
-/**
- * PWM / Timer register map.
- */
-
+/** PWM / Timer channel register map. */
typedef struct {
QM_RW uint32_t loadcount; /**< Load Count */
QM_RW uint32_t currentvalue; /**< Current Value */
@@ -548,6 +810,7 @@ typedef struct {
QM_RW uint32_t intstatus; /**< Interrupt Status */
} qm_pwm_channel_t;
+/** PWM / Timer register map. */
typedef struct {
qm_pwm_channel_t timer[QM_PWM_ID_NUM]; /**< 4 Timers */
QM_RW uint32_t reserved[20];
@@ -571,14 +834,17 @@ qm_pwm_reg_t test_pwm_t;
#define QM_PWM_INTERRUPT_MASK_OFFSET (2)
+/** @} */
+
/**
- * Number of WDT controllers.
+ * @name WDT
+ * @{
*/
+
+/** Number of WDT controllers. */
typedef enum { QM_WDT_0 = 0, QM_WDT_NUM } qm_wdt_t;
-/**
- * Watchdog timer register block type.
- */
+/** Watchdog timer register map. */
typedef struct {
QM_RW uint32_t wdt_cr; /**< Control Register */
QM_RW uint32_t wdt_torr; /**< Timeout Range Register */
@@ -603,19 +869,22 @@ qm_wdt_reg_t test_wdt;
#else
/** WDT register base address */
#define QM_WDT_BASE (0xB0000000)
+
/** WDT register block */
#define QM_WDT ((qm_wdt_reg_t *)QM_WDT_BASE)
#endif
-/**
- * Number of UART controllers.
- */
-typedef enum { QM_UART_0 = 0, QM_UART_1, QM_UART_NUM } qm_uart_t;
+/** @} */
/**
- * UART register block type.
+ * @name UART
+ * @{
*/
+/** Number of UART controllers. */
+typedef enum { QM_UART_0 = 0, QM_UART_1, QM_UART_NUM } qm_uart_t;
+
+/** UART register map. */
typedef struct {
QM_RW uint32_t rbr_thr_dll; /**< Rx Buffer/ Tx Holding/ Div Latch Low */
QM_RW uint32_t ier_dlh; /**< Interrupt Enable / Divisor Latch High */
@@ -649,39 +918,14 @@ extern qm_uart_reg_t *qm_uart[QM_UART_NUM];
#define QM_UART qm_uart
#endif
-/**
- * Number of RTC controllers.
- */
-typedef enum { QM_RTC_0 = 0, QM_RTC_NUM } qm_rtc_t;
+/** @} */
/**
- * QM RTC Register block type.
+ * @name SPI
+ * @{
*/
-typedef struct {
- QM_RW uint32_t rtc_ccvr; /**< Current Counter Value Register */
- QM_RW uint32_t rtc_cmr; /**< Current Match Register */
- QM_RW uint32_t rtc_clr; /**< Counter Load Register */
- QM_RW uint32_t rtc_ccr; /**< Counter Control Register */
- QM_RW uint32_t rtc_stat; /**< Interrupt Status Register */
- QM_RW uint32_t rtc_rstat; /**< Interrupt Raw Status Register */
- QM_RW uint32_t rtc_eoi; /**< End of Interrupt Register */
- QM_RW uint32_t rtc_comp_version; /**< End of Interrupt Register */
-} qm_rtc_reg_t;
-
-#if (UNIT_TEST)
-qm_rtc_reg_t test_rtc;
-#define QM_RTC ((qm_rtc_reg_t *)(&test_rtc))
-#else
-/** RTC register base address */
-#define QM_RTC_BASE (0xB0000400)
-/** RTC register block */
-#define QM_RTC ((qm_rtc_reg_t *)QM_RTC_BASE)
-#endif
-
-/**
- * Number of SPI controllers.
- */
+/** Number of SPI controllers. */
typedef enum {
QM_SPI_MST_0 = 0,
QM_SPI_MST_1,
@@ -689,9 +933,7 @@ typedef enum {
QM_SPI_NUM
} qm_spi_t;
-/**
- * SPI register entries
- */
+/** SPI register map. */
typedef struct {
QM_RW uint32_t ctrlr0; /**< Control Register 0 */
QM_RW uint32_t ctrlr1; /**< Control Register 1 */
@@ -756,6 +998,8 @@ extern qm_spi_reg_t *qm_spi_controllers[QM_SPI_NUM];
#define QM_SPI_SR_BUSY BIT(0)
#define QM_SPI_SR_TFNF BIT(1)
#define QM_SPI_SR_TFE BIT(2)
+#define QM_SPI_SR_RFNE BIT(3)
+#define QM_SPI_SR_RFF BIT(4)
/* SPI Interrupt Mask register */
#define QM_SPI_IMR_MASK_ALL (0x00)
@@ -783,14 +1027,51 @@ extern qm_spi_reg_t *qm_spi_controllers[QM_SPI_NUM];
#define QM_SPI_DMACR_RDMAE BIT(0)
#define QM_SPI_DMACR_TDMAE BIT(1)
+/** @} */
+
/**
- * Number of I2C controllers.
+ * @name RTC
+ * @{
*/
-typedef enum { QM_I2C_0 = 0, QM_I2C_1, QM_I2C_NUM } qm_i2c_t;
+
+/** Number of RTC controllers. */
+typedef enum { QM_RTC_0 = 0, QM_RTC_NUM } qm_rtc_t;
+
+/** RTC register map. */
+typedef struct {
+ QM_RW uint32_t rtc_ccvr; /**< Current Counter Value Register */
+ QM_RW uint32_t rtc_cmr; /**< Current Match Register */
+ QM_RW uint32_t rtc_clr; /**< Counter Load Register */
+ QM_RW uint32_t rtc_ccr; /**< Counter Control Register */
+ QM_RW uint32_t rtc_stat; /**< Interrupt Status Register */
+ QM_RW uint32_t rtc_rstat; /**< Interrupt Raw Status Register */
+ QM_RW uint32_t rtc_eoi; /**< End of Interrupt Register */
+ QM_RW uint32_t rtc_comp_version; /**< End of Interrupt Register */
+} qm_rtc_reg_t;
+
+#if (UNIT_TEST)
+qm_rtc_reg_t test_rtc;
+#define QM_RTC ((qm_rtc_reg_t *)(&test_rtc))
+
+#else
+/** RTC register base address. */
+#define QM_RTC_BASE (0xB0000400)
+
+/** RTC register block. */
+#define QM_RTC ((qm_rtc_reg_t *)QM_RTC_BASE)
+#endif
+
+/** @} */
/**
- * I2C Register block type.
+ * @name I2C
+ * @{
*/
+
+/** Number of I2C controllers. */
+typedef enum { QM_I2C_0 = 0, QM_I2C_1, QM_I2C_NUM } qm_i2c_t;
+
+/** I2C register map. */
typedef struct {
QM_RW uint32_t ic_con; /**< Control Register */
QM_RW uint32_t ic_tar; /**< Master Target Address */
@@ -854,11 +1135,11 @@ qm_i2c_reg_t *test_i2c[QM_I2C_NUM];
#define QM_I2C test_i2c
#else
-/** I2C Master register base address */
+/** I2C Master register base address. */
#define QM_I2C_0_BASE (0xB0002800)
#define QM_I2C_1_BASE (0xB0002C00)
-/** I2C register block */
+/** I2C register block. */
extern qm_i2c_reg_t *qm_i2c[QM_I2C_NUM];
#define QM_I2C qm_i2c
#endif
@@ -916,14 +1197,17 @@ extern qm_i2c_reg_t *qm_i2c[QM_I2C_NUM];
#define QM_I2C_IC_DMA_CR_RX_ENABLE BIT(0)
#define QM_I2C_IC_DMA_CR_TX_ENABLE BIT(1)
+/** @} */
+
/**
- * Number of GPIO controllers.
+ * @name GPIO
+ * @{
*/
+
+/** Number of GPIO controllers. */
typedef enum { QM_GPIO_0 = 0, QM_AON_GPIO_0 = 1, QM_GPIO_NUM } qm_gpio_t;
-/**
- * GPIO register block type.
- */
+/** GPIO register map. */
typedef struct {
QM_RW uint32_t gpio_swporta_dr; /**< Port A Data */
QM_RW uint32_t gpio_swporta_ddr; /**< Port A Data Direction */
@@ -966,14 +1250,17 @@ extern qm_gpio_reg_t *qm_gpio[QM_GPIO_NUM];
#define QM_GPIO qm_gpio
#endif
+/** @} */
+
/**
- * Number of Flash controllers.
+ * @name Flash
+ * @{
*/
+
+/** Number of Flash controllers. */
typedef enum { QM_FLASH_0 = 0, QM_FLASH_1, QM_FLASH_NUM } qm_flash_t;
-/**
- * Flash register block type.
- */
+/** Flash register map. */
typedef struct {
QM_RW uint32_t tmg_ctrl; /**< TMG_CTRL */
QM_RW uint32_t rom_wr_ctrl; /**< ROM_WR_CTRL */
@@ -986,7 +1273,7 @@ typedef struct {
QM_RW uint32_t
mpr_wr_cfg; /**< Flash Write Protection Control Register */
QM_RW uint32_t mpr_vsts; /**< Protection Status Register */
- QM_RW uint32_t mpr_vdata; /** MPR_VDATA */
+ QM_RW uint32_t mpr_vdata; /**< MPR Violation Data Value Register */
QM_RW uint32_t padding[0x3FFF2]; /* (0x100000 - 0x38) / 4 */
} qm_flash_reg_t;
@@ -1005,19 +1292,23 @@ uint8_t test_flash_page[0x800];
#define QM_FLASH_MAX_ADDR (0xFFFFFFFF)
#else
-/** Flash controller 0 register block */
-#define QM_FLASH_BASE_0 (0xB0100000)
-#define QM_FLASH_BASE_1 (0xB0200000)
-extern qm_flash_reg_t *qm_flash[QM_FLASH_NUM];
-#define QM_FLASH qm_flash
+/* Flash physical address mappings */
-/** Flash physical address mappings */
#define QM_FLASH_REGION_SYS_1_BASE (0x40030000)
#define QM_FLASH_REGION_SYS_0_BASE (0x40000000)
#define QM_FLASH_REGION_OTP_0_BASE (0xFFFFE000)
+
#define QM_FLASH_PAGE_MASK (0x3F800)
#define QM_FLASH_MAX_ADDR (0x30000)
+/** Flash controller register base address. */
+#define QM_FLASH_BASE_0 (0xB0100000)
+#define QM_FLASH_BASE_1 (0xB0200000)
+
+/** Flash controller register block. */
+extern qm_flash_reg_t *qm_flash[QM_FLASH_NUM];
+#define QM_FLASH qm_flash
+
#endif
#define QM_FLASH_REGION_DATA_BASE_OFFSET (0x00)
@@ -1027,9 +1318,14 @@ extern qm_flash_reg_t *qm_flash[QM_FLASH_NUM];
(QM_FLASH_MAX_ADDR / (4 * QM_FLASH_PAGE_SIZE_DWORDS))
#define QM_FLASH_LVE_MODE BIT(5)
+/** @} */
+
/**
- * Memory Protection Region register block type.
+ * @name Memory Protection Region
+ * @{
*/
+
+/** Memory Protection Region register map. */
typedef struct {
QM_RW uint32_t mpr_cfg[4]; /**< MPR CFG */
QM_RW uint32_t mpr_vdata; /**< MPR_VDATA */
@@ -1064,31 +1360,14 @@ qm_mpr_reg_t test_mpr;
#define QM_CCU_EXT_CLK_DIV_EN BIT(2)
/** End of External clock control @}*/
-/** GPIO Debounce Clock Control @{*/
-#define QM_CCU_GPIO_DB_DIV_OFFSET (2)
-#define QM_CCU_GPIO_DB_CLK_DIV_EN BIT(1)
-#define QM_CCU_GPIO_DB_CLK_EN BIT(0)
-/** End of GPIO Debounce Clock Control @}*/
-
-/** Peripheral clock divider control 0 @{*/
-#define QM_CCU_PERIPH_PCLK_DIV_OFFSET (1)
-#define QM_CCU_PERIPH_PCLK_DIV_EN BIT(0)
-/** End of Peripheral clock divider control 0 @}*/
-
-/** System clock control @{*/
-#define QM_CCU_SYS_CLK_SEL BIT(0)
-#define QM_CCU_RTC_CLK_EN BIT(1)
-#define QM_CCU_RTC_CLK_DIV_EN BIT(2)
-#define QM_CCU_SYS_CLK_DIV_EN BIT(7)
-#define QM_CCU_SYS_CLK_DIV_MASK (0x00000300)
-#define QM_CCU_DMA_CLK_EN BIT(6)
-
-#define QM_CCU_RTC_CLK_DIV_OFFSET (3)
-#define QM_CCU_SYS_CLK_DIV_OFFSET (8)
+/** @} */
/**
- * Peripheral clock type.
+ * @name Peripheral Clock
+ * @{
*/
+
+/** Peripheral clock type. */
typedef enum {
CLK_PERIPH_REGISTER = BIT(0), /**< Peripheral Clock Gate Enable. */
CLK_PERIPH_CLK = BIT(1), /**< Peripheral Clock Enable. */
@@ -1122,29 +1401,25 @@ typedef enum {
/* Default mask values */
#define CLK_EXTERN_DIV_DEF_MASK (0xFFFFFFE3)
-#define CLK_SYS_CLK_DIV_DEF_MASK (0xFFFFF87F)
+#define CLK_SYS_CLK_DIV_DEF_MASK (0xFFFFFC7F)
#define CLK_RTC_DIV_DEF_MASK (0xFFFFFF83)
#define CLK_GPIO_DB_DIV_DEF_MASK (0xFFFFFFE1)
#define CLK_PERIPH_DIV_DEF_MASK (0xFFFFFFF9)
-#define SYS_CLK_HYB_OSC_32MHZ_SETTINGS *((volatile uint32_t *)0x00000004)
-#define SYS_CLK_HYB_OSC_4MHZ_SETTINGS *((volatile uint32_t *)0x00000008)
-
-/** End of System clock control 0 @}*/
-
-/** DMA */
+/** @} */
/**
- * DMA instances
+ * @name DMA
+ * @{
*/
+
+/** DMA instances. */
typedef enum {
QM_DMA_0, /**< DMA controller id. */
QM_DMA_NUM /**< Number of DMA controllers. */
} qm_dma_t;
-/**
- * DMA channel IDs
- */
+/** DMA channel IDs. */
typedef enum {
QM_DMA_CHANNEL_0 = 0, /**< DMA channel id for channel 0 */
QM_DMA_CHANNEL_1, /**< DMA channel id for channel 1 */
@@ -1157,9 +1432,7 @@ typedef enum {
QM_DMA_CHANNEL_NUM /**< Number of DMA channels */
} qm_dma_channel_id_t;
-/**
- * DMA hardware handshake interfaces
- */
+/** DMA hardware handshake interfaces. */
typedef enum {
DMA_HW_IF_UART_A_TX = 0x0, /**< UART_A_TX */
DMA_HW_IF_UART_A_RX = 0x1, /**< UART_A_RX */
@@ -1179,9 +1452,7 @@ typedef enum {
DMA_HW_IF_I2C_MASTER_1_RX = 0xf, /**< I2C_Master_1_RX */
} qm_dma_handshake_interface_t;
-/**
- * DMA channel register block type
- */
+/** DMA channel register map. */
typedef struct {
QM_RW uint32_t sar_low; /**< SAR */
QM_RW uint32_t sar_high; /**< SAR */
@@ -1207,7 +1478,7 @@ typedef struct {
QM_RW uint32_t dst_sg_high; /**< DSR */
} qm_dma_chan_reg_t;
-/** DMA channel control register offsets and masks */
+/* DMA channel control register offsets and masks. */
#define QM_DMA_CTL_L_INT_EN_MASK BIT(0)
#define QM_DMA_CTL_L_DST_TR_WIDTH_OFFSET (1)
#define QM_DMA_CTL_L_DST_TR_WIDTH_MASK (0x7 << QM_DMA_CTL_L_DST_TR_WIDTH_OFFSET)
@@ -1230,7 +1501,7 @@ typedef struct {
#define QM_DMA_CTL_H_BLOCK_TS_MAX 4095
#define QM_DMA_CTL_H_BLOCK_TS_MIN 1
-/** DMA channel config register offsets and masks */
+/* DMA channel config register offsets and masks. */
#define QM_DMA_CFG_L_CH_SUSP_MASK BIT(8)
#define QM_DMA_CFG_L_FIFO_EMPTY_MASK BIT(9)
#define QM_DMA_CFG_L_HS_SEL_DST_OFFSET 10
@@ -1248,9 +1519,7 @@ typedef struct {
#define QM_DMA_CFG_H_DEST_PER_OFFSET (11)
#define QM_DMA_CFG_H_DEST_PER_MASK (0xf << QM_DMA_CFG_H_DEST_PER_OFFSET)
-/**
- * DMA interrupt register block type
- */
+/** DMA interrupt register map. */
typedef struct {
QM_RW uint32_t raw_tfr_low; /**< RawTfr */
QM_RW uint32_t raw_tfr_high; /**< RawTfr */
@@ -1296,13 +1565,11 @@ typedef struct {
QM_RW uint32_t status_int_high; /**< StatusInt */
} qm_dma_int_reg_t;
-/** DMA interrupt status register bits */
+/* DMA interrupt status register bits. */
#define QM_DMA_INT_STATUS_TFR BIT(0)
#define QM_DMA_INT_STATUS_ERR BIT(4)
-/**
- * DMA miscellaneous register block type
- */
+/** DMA miscellaneous register map. */
typedef struct {
QM_RW uint32_t cfg_low; /**< DmaCfgReg */
QM_RW uint32_t cfg_high; /**< DmaCfgReg */
@@ -1315,10 +1582,10 @@ typedef struct {
QM_RW uint32_t reserved[4]; /**< Reserved */
} qm_dma_misc_reg_t;
-/** Channel write enable in the misc channel enable register */
+/** Channel write enable in the misc channel enable register. */
#define QM_DMA_MISC_CHAN_EN_WE_OFFSET (8)
-/** Controller enable bit in the misc config register */
+/** Controller enable bit in the misc config register. */
#define QM_DMA_MISC_CFG_DMA_EN BIT(0)
typedef struct {
@@ -1338,148 +1605,12 @@ extern qm_dma_reg_t *qm_dma[QM_DMA_NUM];
#define QM_DMA qm_dma
#endif
-/** IRQs and interrupt vectors.
- *
- * Any IRQ > 1 actually has a SCSS mask register offset of +1.
- * The vector numbers must be defined without arithmetic expressions nor
- * parentheses because they are expanded as token concatenation.
- */
-
-#define QM_INT_VECTOR_DOUBLE_FAULT 8
-#define QM_INT_VECTOR_PIC_TIMER 32
-
-#define QM_IRQ_GPIO_0 (8)
-#define QM_IRQ_GPIO_0_MASK_OFFSET (9)
-#define QM_IRQ_GPIO_0_VECTOR 44
-
-#define QM_IRQ_PWM_0 (9)
-#define QM_IRQ_PWM_0_MASK_OFFSET (10)
-#define QM_IRQ_PWM_0_VECTOR 45
-
-#define QM_IRQ_USB_0 (10)
-#define QM_IRQ_USB_0_MASK_OFFSET (11)
-#define QM_IRQ_USB_0_VECTOR 46
-
-#define QM_IRQ_SPI_MASTER_0 (2)
-#define QM_IRQ_SPI_MASTER_0_MASK_OFFSET (3)
-#define QM_IRQ_SPI_MASTER_0_VECTOR 38
-
-#define QM_IRQ_SPI_MASTER_1 (3)
-#define QM_IRQ_SPI_MASTER_1_MASK_OFFSET (4)
-#define QM_IRQ_SPI_MASTER_1_VECTOR 39
-
-#define QM_IRQ_RTC_0 (11)
-#define QM_IRQ_RTC_0_MASK_OFFSET (12)
-#define QM_IRQ_RTC_0_VECTOR 47
-
-#define QM_IRQ_WDT_0 (12)
-#define QM_IRQ_WDT_0_MASK_OFFSET (13)
-#define QM_IRQ_WDT_0_VECTOR 48
-
-#define QM_IRQ_I2C_0 (0)
-#define QM_IRQ_I2C_0_MASK_OFFSET (0)
-#define QM_IRQ_I2C_0_VECTOR 36
-
-#define QM_IRQ_I2C_1 (1)
-#define QM_IRQ_I2C_1_MASK_OFFSET (1)
-#define QM_IRQ_I2C_1_VECTOR 37
-
-#define QM_IRQ_MBOX (21)
-#define QM_IRQ_MBOX_MASK_OFFSET (22)
-#define QM_IRQ_MBOX_VECTOR 57
-
-#define QM_IRQ_AC (22)
-#define QM_IRQ_AC_MASK_OFFSET (26)
-#define QM_IRQ_AC_VECTOR 58
-
-#define QM_IRQ_SRAM (25)
-#define QM_IRQ_SRAM_MASK_OFFSET (29)
-#define QM_IRQ_SRAM_VECTOR 61
-
-#define QM_IRQ_FLASH_0 (26)
-#define QM_IRQ_FLASH_0_MASK_OFFSET (30)
-#define QM_IRQ_FLASH_0_VECTOR 62
-
-#define QM_IRQ_FLASH_1 (27)
-#define QM_IRQ_FLASH_1_MASK_OFFSET (31)
-#define QM_IRQ_FLASH_1_VECTOR 63
-
-#define QM_IRQ_AONPT_0 (28)
-#define QM_IRQ_AONPT_0_MASK_OFFSET (32)
-#define QM_IRQ_AONPT_0_VECTOR 64
+/** @} */
-#define QM_IRQ_AONGPIO_0 (31)
-#define QM_IRQ_AONGPIO_0_MASK_OFFSET (35)
-#define QM_IRQ_AONGPIO_0_VECTOR 67
-
-#define QM_IRQ_UART_0 (5)
-#define QM_IRQ_UART_0_MASK_OFFSET (6)
-#define QM_IRQ_UART_0_VECTOR 41
-
-#define QM_IRQ_UART_1 (6)
-#define QM_IRQ_UART_1_MASK_OFFSET (7)
-#define QM_IRQ_UART_1_VECTOR 42
-
-#define QM_IRQ_DMA_0 (13)
-#define QM_IRQ_DMA_0_MASK_OFFSET (14)
-#define QM_IRQ_DMA_0_VECTOR 49
-
-#define QM_IRQ_DMA_1 (14)
-#define QM_IRQ_DMA_1_MASK_OFFSET (15)
-#define QM_IRQ_DMA_1_VECTOR 50
-
-#define QM_IRQ_DMA_2 (15)
-#define QM_IRQ_DMA_2_MASK_OFFSET (16)
-#define QM_IRQ_DMA_2_VECTOR 51
-
-#define QM_IRQ_DMA_3 (16)
-#define QM_IRQ_DMA_3_MASK_OFFSET (17)
-#define QM_IRQ_DMA_3_VECTOR 52
-
-#define QM_IRQ_DMA_4 (17)
-#define QM_IRQ_DMA_4_MASK_OFFSET (18)
-#define QM_IRQ_DMA_4_VECTOR 53
-
-#define QM_IRQ_DMA_5 (18)
-#define QM_IRQ_DMA_5_MASK_OFFSET (19)
-#define QM_IRQ_DMA_5_VECTOR 54
-
-#define QM_IRQ_DMA_6 (19)
-#define QM_IRQ_DMA_6_MASK_OFFSET (20)
-#define QM_IRQ_DMA_6_VECTOR 55
-
-#define QM_IRQ_DMA_7 (20)
-#define QM_IRQ_DMA_7_MASK_OFFSET (21)
-#define QM_IRQ_DMA_7_VECTOR 56
-
-#define QM_IRQ_DMA_ERR (24)
-#define QM_IRQ_DMA_ERR_MASK_OFFSET (28)
-#define QM_IRQ_DMA_ERR_VECTOR 60
-
-#define QM_SS_IRQ_ADC_PWR (29)
-#define QM_SS_IRQ_ADC_PWR_MASK_OFFSET (33)
-#define QM_SS_IRQ_ADC_PWR_VECTOR (65)
-
-#define QM_SS_IRQ_ADC_CAL (30)
-#define QM_SS_IRQ_ADC_CAL_MASK_OFFSET (34)
-#define QM_SS_IRQ_ADC_CAL_VECTOR (66)
-
-/* Hybrid oscillator output select select (0=Silicon, 1=Crystal)*/
-#define QM_OSC0_MODE_SEL BIT(3)
-/* Enable Crystal oscillator*/
-#define QM_OSC0_EN_CRYSTAL BIT(0)
-
-/* Crystal oscillator parameters */
-#define OSC0_CFG1_OSC0_FADJ_XTAL_MASK (0x000F0000)
-#define OSC0_CFG1_OSC0_FADJ_XTAL_OFFS (16)
-#define OSC0_CFG0_OSC0_XTAL_COUNT_VALUE_MASK (0x00600000)
-#define OSC0_CFG0_OSC0_XTAL_COUNT_VALUE_OFFS (21)
-
-/* Silicon Oscillator parameters */
-#define OSC0_CFG1_FTRIMOTP_MASK (0x3FF00000)
-#define OSC0_CFG1_FTRIMOTP_OFFS (20)
-#define OSC0_CFG1_SI_FREQ_SEL_MASK (0x00000300)
-#define OSC0_CFG1_SI_FREQ_SEL_OFFS (8)
+/**
+ * @name USB
+ * @{
+ */
/** USB register base address */
#define QM_USB_BASE (0xB0500000)
@@ -1495,24 +1626,14 @@ extern qm_dma_reg_t *qm_dma[QM_DMA_NUM];
/* USB clock enable bit*/
#define QM_CCU_USB_CLK_EN BIT(1)
-/* Clock enable/disable register*/
-#define QM_CCU_MLAYER_AHB_CTL (REG_VAL(0xB0800034))
-
-/* Ensure CLK divide by one is set*/
-#define QM_CCU_SYS_CLK_DIV_BY_ONE (0xFFFFFCFF)
-/* SYS CLK register*/
-#define QM_CCU_SYS_CLK_CTL (REG_VAL(0xB0800038))
-/* Pin MUX slew rate registers and settings */
-#define QM_PMUX_SLEW_4MA_DRIVER (0xFFFFFFFF)
-#define QM_PMUX_SLEW0 (REG_VAL(0xB0800910))
-#define QM_PMUX_SLEW1 (REG_VAL(0xB0800914))
-#define QM_PMUX_SLEW2 (REG_VAL(0xB0800918))
-#define QM_PMUX_SLEW3 (REG_VAL(0xB080091C))
+/** @} */
/**
- * Version variables.
+ * @name Versioning
+ * @{
*/
+
#if (UNIT_TEST)
uint32_t test_rom_version;
#define ROM_VERSION_ADDRESS &test_rom_version;
@@ -1520,4 +1641,8 @@ uint32_t test_rom_version;
#define ROM_VERSION_ADDRESS (0xFFFFFFEC);
#endif
+/** @} */
+
+/** @} */
+
#endif /* __REGISTERS_H__ */