summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2018-11-29 15:29:46 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-12-04 00:11:28 -0800
commite3adb1de782a368aadacad78691ab7a4cd9c9178 (patch)
treef4eabd52e73e92da5c87dedbfbc79b51f776a329
parent1aeb203a2feb48536454d888469a6bb4e9fb3b46 (diff)
downloadchrome-ec-e3adb1de782a368aadacad78691ab7a4cd9c9178.tar.gz
wov: Detect I2S overrun/underrun bursts
This CL adds logic to detect when bursts of I2S overrun/underruns are ocurring. If this condiditon is ocurring then the ISR may consume all of the EC processing power resulint in watchdog events. BRANCH=none BUG=b:116766596 TEST=On Cheza, had BCLK on EC set 2x higher than AP. Without this CL, would consistently trigger watchdog reset. With CL, underrun storm is detected based on console print and watchdog reset no longer occurs. Change-Id: Ia398d5b36525a63d3341bf42fd3f6d12d93d41e0 Signed-off-by: Scott Collyer <scollyer@google.com> Reviewed-on: https://chromium-review.googlesource.com/1356180 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Wai-Hong Tam <waihong@google.com>
-rw-r--r--chip/npcx/wov.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/chip/npcx/wov.c b/chip/npcx/wov.c
index 57302fd01b..94cd8251d2 100644
--- a/chip/npcx/wov.c
+++ b/chip/npcx/wov.c
@@ -173,6 +173,14 @@ static wov_call_back_t callback_fun;
const uint32_t voice_buffer[VOICE_BUF_SIZE] = {0};
+#define WOV_RATE_ERROR_THRESH_MSEC 10
+#define WOV_RATE_ERROR_THRESH 5
+
+static int irq_underrun_count;
+static int irq_overrun_count;
+static uint32_t wov_i2s_underrun_tstamp;
+static uint32_t wov_i2s_overrun_tstamp;
+
#define WOV_CALLBACK(event) \
{ \
if (callback_fun != NULL) \
@@ -536,6 +544,36 @@ static enum ec_error_list wov_set_mic_source_l(void)
return EC_SUCCESS;
}
+static void wov_over_under_deferred(void)
+{
+ CPRINTS("wov: Under/Over run error: under = %d, over = %d",
+ irq_underrun_count, irq_overrun_count);
+}
+DECLARE_DEFERRED(wov_over_under_deferred);
+
+static void wov_under_over_error_handler(int *count, uint32_t *last_time)
+{
+ uint32_t time_delta_msec;
+ uint32_t current_time = get_time().le.lo;
+
+ if (!(*count)) {
+ *last_time = current_time;
+ (*count)++;
+ } else {
+ time_delta_msec = (current_time - *last_time) / MSEC;
+ *last_time = current_time;
+ if (time_delta_msec < WOV_RATE_ERROR_THRESH_MSEC)
+ (*count)++;
+ else
+ *count = 0;
+
+ if (*count >= WOV_RATE_ERROR_THRESH) {
+ wov_stop_i2s_capture();
+ hook_call_deferred(&wov_over_under_deferred_data, 0);
+ }
+ }
+}
+
/**
* WoV interrupt handler.
*
@@ -586,12 +624,16 @@ void wov_interrupt_handler(void)
/* I2S FIFO is overrun. Reset the I2S FIFO and inform the FW. */
if (WOV_IS_I2S_FIFO_OVERRUN(wov_status)) {
WOV_CALLBACK(WOV_EVENT_ERROR_I2S_FIFO_OVERRUN);
+ wov_under_over_error_handler(&irq_overrun_count,
+ &wov_i2s_overrun_tstamp);
wov_i2s_fifo_reset();
}
/* I2S FIFO is underrun. Reset the I2S FIFO and inform the FW. */
if (WOV_IS_I2S_FIFO_UNDERRUN(wov_status)) {
WOV_CALLBACK(WOV_EVENT_ERROR_I2S_FIFO_UNDERRUN);
+ wov_under_over_error_handler(&irq_underrun_count,
+ &wov_i2s_underrun_tstamp);
wov_i2s_fifo_reset();
}
@@ -1166,6 +1208,10 @@ void wov_i2s_fifo_reset(void)
*/
void wov_start_i2s_capture(void)
{
+ /* Clear counters used to track for underrun/overrun errors */
+ irq_underrun_count = 0;
+ irq_overrun_count = 0;
+
/* Clear the I2S status bits in WoV status register. */
SET_FIELD(NPCX_WOV_STATUS, NPCX_WOV_STATUS_BITS, 0x18);