From 038e75cd855fdbc63aebed53270e51bf6169b052 Mon Sep 17 00:00:00 2001 From: scott worley Date: Thu, 10 May 2018 10:03:37 -0400 Subject: ec_chip_mchp: Clear ADC sticky hardware status before starting. Before starting an ADC conversion clear sticky hardware status in ADC and interrupt aggregator. BRANCH=none BUG= TEST=Build boards using chip mchp and check for spurious ADC interrupts. CQ-DEPEND=CL:1053576 Change-Id: I48b07ecaac2976c5e06e23a4ecf4397ed41c89d1 Signed-off-by: scott worley Reviewed-on: https://chromium-review.googlesource.com/1053867 Commit-Ready: Randall Spangler Tested-by: Scott Worley Reviewed-by: Randall Spangler --- chip/mchp/adc.c | 55 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/chip/mchp/adc.c b/chip/mchp/adc.c index 4fe1a384c0..6278bc1ebd 100644 --- a/chip/mchp/adc.c +++ b/chip/mchp/adc.c @@ -7,6 +7,7 @@ #include "adc_chip.h" #include "common.h" #include "console.h" +#include "gpio.h" #include "hooks.h" #include "registers.h" #include "task.h" @@ -30,16 +31,37 @@ struct mutex adc_lock; */ static task_id_t task_waiting; +/* + * Start ADC single-shot conversion. + * 1. Disable ADC interrupt. + * 2. Clear sticky hardware status. + * 3. Start conversion. + * 4. Enable interrupt. + * 5. Wait with timeout for ADC ISR to + * to set TASK_EVENT_TIMER. + */ static int start_single_and_wait(int timeout) { int event; + MCHP_INT_DISABLE(MCHP_ADC_GIRQ) = MCHP_ADC_GIRQ_SINGLE_BIT; task_waiting = task_get_current(); + /* clear all R/W1C channel status */ + MCHP_ADC_STS = 0xffffu; + /* clear R/W1C single done status */ + MCHP_ADC_CTRL |= (1 << 7); + /* clear GIRQ single status */ + MCHP_INT_SOURCE(MCHP_ADC_GIRQ) = MCHP_ADC_GIRQ_SINGLE_BIT; + /* make sure all writes are issued before starting conversion */ + asm volatile ("dsb"); + /* Start conversion */ MCHP_ADC_CTRL |= 1 << 1; - /* Wait for interrupt */ + MCHP_INT_ENABLE(MCHP_ADC_GIRQ) = MCHP_ADC_GIRQ_SINGLE_BIT; + + /* Wait for interrupt, ISR disables interrupt */ event = task_wait_event(timeout); task_waiting = TASK_ID_INVALID; return event != TASK_EVENT_TIMER; @@ -50,25 +72,16 @@ int adc_read_channel(enum adc_channel ch) const struct adc_t *adc = adc_channels + ch; int value; - trace1(0, ADC, 0, "adc_read_channel %d", ch); - mutex_lock(&adc_lock); - trace1(0, ADC, 0, - "adc_read_channel acquired mutex. Physical channel = %d", - adc->channel); - MCHP_ADC_SINGLE = 1 << adc->channel; if (start_single_and_wait(ADC_SINGLE_READ_TIME)) - value = MCHP_ADC_READ(adc->channel) * adc->factor_mul / + value = (MCHP_ADC_READ(adc->channel) * adc->factor_mul) / adc->factor_div + adc->shift; else value = ADC_READ_ERROR; - trace11(0, ADC, 0, - "adc_read_channel value = 0x%08X. Releasing mutex", value); - mutex_unlock(&adc_lock); return value; } @@ -79,12 +92,8 @@ int adc_read_all_channels(int *data) int ret = EC_SUCCESS; const struct adc_t *adc; - trace0(0, ADC, 0, "adc_read_all_channels"); - mutex_lock(&adc_lock); - trace0(0, ADC, 0, "adc_read_all_channels acquired mutex"); - MCHP_ADC_SINGLE = 0; for (i = 0; i < ADC_CH_COUNT; ++i) MCHP_ADC_SINGLE |= 1 << adc_channels[i].channel; @@ -96,25 +105,28 @@ int adc_read_all_channels(int *data) for (i = 0; i < ADC_CH_COUNT; ++i) { adc = adc_channels + i; - data[i] = MCHP_ADC_READ(adc->channel) * adc->factor_mul / + data[i] = (MCHP_ADC_READ(adc->channel) * adc->factor_mul) / adc->factor_div + adc->shift; - trace12(0, ADC, 0, "adc all: data[%d] = 0x%08X", i, data[i]); } exit_all_channels: mutex_unlock(&adc_lock); - trace0(0, ADC, 0, "adc_read_all_channels released mutex"); return ret; } /* - * Using MEC1701 direct mode interrupts. Do not + * Enable GPIO pins. + * Using MEC17xx direct mode interrupts. Do not * set Interrupt Aggregator Block Enable bit * for GIRQ containing ADC. */ static void adc_init(void) { + trace0(0, ADC, 0, "adc_init"); + + gpio_config_module(MODULE_ADC, 1); + /* clear ADC sleep enable */ MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_ADC); @@ -130,6 +142,11 @@ DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_INIT_ADC); void adc_interrupt(void) { + MCHP_INT_DISABLE(MCHP_ADC_GIRQ) = MCHP_ADC_GIRQ_SINGLE_BIT; + + /* clear individual chan conversion status */ + MCHP_ADC_STS = 0xffffu; + /* Clear interrupt status bit */ MCHP_ADC_CTRL |= 1 << 7; -- cgit v1.2.1