summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChromeOS Developer <dparker@chromium.org>2014-03-23 09:25:03 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-03-26 19:31:17 +0000
commit9d5432bc74f040d3f130def809a06979191baf40 (patch)
tree5605bfea31f22fa0e31c891a0d99a41f586dfff0
parente2e2f5d848b1d763b8a0f420ee0878cbc395856f (diff)
downloadchrome-ec-9d5432bc74f040d3f130def809a06979191baf40.tar.gz
lm4: Use a special task event for ADC conversions
This prevents other task events from continuing the ADC conversion prematurely; potentially leading to a panic if the conversion interrupt occurs after the ADC has been powered down. BUG=chrome-os-partner:26919 BRANCH=rambi TEST=Perform ADC conversions while running a deferred function calling itself on a 10mSec delay. Verify no panics after ~6 hours. Change-Id: Ic3894849c154b3f058e812b2da816e7cffb12cbf Signed-off-by: Dave Parker <dparker@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/191302 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/lm4/adc.c21
-rw-r--r--include/task.h4
2 files changed, 19 insertions, 6 deletions
diff --git a/chip/lm4/adc.c b/chip/lm4/adc.c
index e58945605e..f797317688 100644
--- a/chip/lm4/adc.c
+++ b/chip/lm4/adc.c
@@ -18,6 +18,9 @@
#include "timer.h"
#include "util.h"
+/* Maximum time we allow for an ADC conversion */
+#define ADC_TIMEOUT_US SECOND
+
static task_id_t task_waiting_on_ss[LM4_ADC_SEQ_COUNT];
static void configure_gpio(void)
@@ -74,13 +77,21 @@ static int flush_and_read(enum lm4_adc_sequencer seq)
/* Clear the interrupt status */
LM4_ADC_ADCISC |= 0x01 << seq;
+ /* Enable interrupt */
+ LM4_ADC_ADCIM |= 0x01 << seq;
+
/* Initiate sample sequence */
LM4_ADC_ADCPSSI |= 0x01 << seq;
/* Wait for interrupt */
- event = task_wait_event(SECOND);
+ event = task_wait_event_mask(TASK_EVENT_ADC_DONE, ADC_TIMEOUT_US);
+
+ /* Disable interrupt */
+ LM4_ADC_ADCIM &= ~(0x01 << seq);
+
task_waiting_on_ss[seq] = TASK_ID_INVALID;
- if (event == TASK_EVENT_TIMER)
+
+ if (!(event & TASK_EVENT_ADC_DONE))
return ADC_READ_ERROR;
/* Read the FIFO and convert to temperature */
@@ -159,6 +170,7 @@ int adc_read_channel(enum adc_channel ch)
if (rv == ADC_READ_ERROR)
return ADC_READ_ERROR;
+
return rv * adc->factor_mul / adc->factor_div + adc->shift;
}
@@ -189,7 +201,7 @@ static void handle_interrupt(int ss)
/* Wake up the task which was waiting on the interrupt, if any */
if (id != TASK_ID_INVALID)
- task_wake(id);
+ task_set_event(id, TASK_EVENT_ADC_DONE, 0);
}
void ss0_interrupt(void) { handle_interrupt(0); }
@@ -255,8 +267,7 @@ static void adc_init(void)
for (i = 0; i < LM4_ADC_SEQ_COUNT; i++)
task_waiting_on_ss[i] = TASK_ID_INVALID;
- /* Enable interrupt */
- LM4_ADC_ADCIM = 0xF;
+ /* Enable IRQs */
task_enable_irq(LM4_IRQ_ADC0_SS0);
task_enable_irq(LM4_IRQ_ADC0_SS1);
task_enable_irq(LM4_IRQ_ADC0_SS2);
diff --git a/include/task.h b/include/task.h
index 6b10c649b1..00368fbc34 100644
--- a/include/task.h
+++ b/include/task.h
@@ -13,7 +13,9 @@
/* Task event bitmasks */
/* Tasks may use the bits in TASK_EVENT_CUSTOM for their own events */
-#define TASK_EVENT_CUSTOM(x) (x & 0x0fffffff)
+#define TASK_EVENT_CUSTOM(x) (x & 0x07ffffff)
+/* ADC interrupt handler event */
+#define TASK_EVENT_ADC_DONE (1 << 27)
/* I2C interrupt handler event */
#define TASK_EVENT_I2C_IDLE (1 << 28)
/* task_wake() called on task */