mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-08 16:41:55 +00:00
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>
This commit is contained in:
committed by
chrome-internal-fetch
parent
e2e2f5d848
commit
9d5432bc74
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user