diff options
author | ChromeOS Developer <dparker@chromium.org> | 2014-03-23 09:25:03 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-03-26 19:31:17 +0000 |
commit | 9d5432bc74f040d3f130def809a06979191baf40 (patch) | |
tree | 5605bfea31f22fa0e31c891a0d99a41f586dfff0 | |
parent | e2e2f5d848b1d763b8a0f420ee0878cbc395856f (diff) | |
download | chrome-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.c | 21 | ||||
-rw-r--r-- | include/task.h | 4 |
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 */ |