diff options
author | Dino Li <Dino.Li@ite.com.tw> | 2020-09-25 14:08:14 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-10-30 04:55:21 +0000 |
commit | deef4e1aa7c347740e6c12e2ca3d6893ec19c2fb (patch) | |
tree | 5c7567a5cc1bc56db5f0b9848ed13a3434b7a54b | |
parent | e70ecea5d6101bc6af159c5f7790f3111bd6e393 (diff) | |
download | chrome-ec-deef4e1aa7c347740e6c12e2ca3d6893ec19c2fb.tar.gz |
it83xx/adc: ADC read is successful if valid bit is set
In task_wait_event_mask(), if task woke up by an event which isn't
what we want (events |= __wait_evt(time_remaining_us, TASK_ID_IDLE)),
and timeout occurs (time_remaining_us = deadline - get_time().val).
EC will post timeout event to task even if the event we want
((eg.TASK_EVENT_ADC_DONE)) has been set.
We fix this symptom with checking data valid bit of ADC's register.
So we won't miss ADC read.
BUG=b:171731189
BRANCH=none
TEST=No ADC read error on RunInStressCountdown
Signed-off-by: Dino Li <Dino.Li@ite.com.tw>
Change-Id: I56b301a0f58b64833ae17e2b6e789c879e48cc5c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2501091
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Diana Z <dzigterman@chromium.org>
Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r-- | chip/it83xx/adc.c | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/chip/it83xx/adc.c b/chip/it83xx/adc.c index f8a113beab..b3eb6e25a0 100644 --- a/chip/it83xx/adc.c +++ b/chip/it83xx/adc.c @@ -145,26 +145,32 @@ int adc_read_channel(enum adc_channel ch) /* Wait for interrupt */ events = task_wait_event_mask(TASK_EVENT_ADC_DONE, ADC_TIMEOUT_US); task_waiting = TASK_ID_INVALID; - - if (events & TASK_EVENT_ADC_DONE) { - /* data valid of adc channel[x] */ - if (adc_data_valid(adc_ch)) { - /* read adc raw data msb and lsb */ - adc_raw_data = (*adc_ctrl_regs[adc_ch].adc_datm << 8) + - *adc_ctrl_regs[adc_ch].adc_datl; - - /* W/C data valid flag */ - if (adc_ch <= CHIP_ADC_CH7) - IT83XX_ADC_ADCDVSTS = BIT(adc_ch); - else - IT83XX_ADC_ADCDVSTS2 = - (1 << (adc_ch - CHIP_ADC_CH13)); - - mv = adc_raw_data * adc_channels[ch].factor_mul / - adc_channels[ch].factor_div + - adc_channels[ch].shift; - valid = 1; - } + /* + * Ensure EC won't post the adc done event which is set after getting + * events (events |= __wait_evt() in task_wait_event_mask()) to next + * adc read. + * NOTE: clear TASK_EVENT_ADC_DONE event must happen after setting + * task_waiting to invalid. So TASK_EVENT_ADC_DONE would not set until + * next read. + */ + atomic_clear_bits(task_get_event_bitmap(task_get_current()), + TASK_EVENT_ADC_DONE); + + /* data valid of adc channel[x] */ + if (adc_data_valid(adc_ch)) { + /* read adc raw data msb and lsb */ + adc_raw_data = (*adc_ctrl_regs[adc_ch].adc_datm << 8) + + *adc_ctrl_regs[adc_ch].adc_datl; + + /* W/C data valid flag */ + if (adc_ch <= CHIP_ADC_CH7) + IT83XX_ADC_ADCDVSTS = BIT(adc_ch); + else + IT83XX_ADC_ADCDVSTS2 = (1 << (adc_ch - CHIP_ADC_CH13)); + + mv = adc_raw_data * adc_channels[ch].factor_mul / + adc_channels[ch].factor_div + adc_channels[ch].shift; + valid = 1; } if (!valid) { |