summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorDino Li <Dino.Li@ite.com.tw>2020-09-25 14:08:14 +0800
committerCommit Bot <commit-bot@chromium.org>2020-10-30 04:55:21 +0000
commitdeef4e1aa7c347740e6c12e2ca3d6893ec19c2fb (patch)
tree5c7567a5cc1bc56db5f0b9848ed13a3434b7a54b /chip
parente70ecea5d6101bc6af159c5f7790f3111bd6e393 (diff)
downloadchrome-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>
Diffstat (limited to 'chip')
-rw-r--r--chip/it83xx/adc.c46
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) {