diff options
-rw-r--r-- | chip/mchp/adc.c | 55 |
1 files 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; |