mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-13 03:15:06 +00:00
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 <scott.worley@microchip.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/1053867 Commit-Ready: Randall Spangler <rspangler@chromium.org> Tested-by: Scott Worley <scott.worley@microchip.corp-partner.google.com> Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user