summaryrefslogtreecommitdiff
path: root/chip/npcx/adc.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /chip/npcx/adc.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-stabilize-voshyr-14637.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'chip/npcx/adc.c')
-rw-r--r--chip/npcx/adc.c390
1 files changed, 0 insertions, 390 deletions
diff --git a/chip/npcx/adc.c b/chip/npcx/adc.c
deleted file mode 100644
index ea16589d9b..0000000000
--- a/chip/npcx/adc.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/* Copyright 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* NPCX-specific ADC module for Chrome EC */
-
-#include "adc.h"
-#include "atomic.h"
-#include "clock.h"
-#include "clock_chip.h"
-#include "console.h"
-#include "common.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
-
-/* Maximum time we allow for an ADC conversion */
-#define ADC_TIMEOUT_US SECOND
-#define ADC_CLK 2000000
-#define ADC_REGULAR_DLY 0x11
-#define ADC_REGULAR_ADCCNF2 0x8B07
-#define ADC_REGULAR_GENDLY 0x0100
-#define ADC_REGULAR_MEAST 0x0001
-
-/* ADC conversion mode */
-enum npcx_adc_conversion_mode {
- ADC_CHN_CONVERSION_MODE = 0,
- ADC_SCAN_CONVERSION_MODE = 1
-};
-
-/* Global variables */
-static volatile task_id_t task_waiting;
-
-struct mutex adc_lock;
-
-/**
- * Preset ADC operation clock.
- *
- * @param none
- * @return none
- * @notes changed when initial or HOOK_FREQ_CHANGE command
- */
-void adc_freq_changed(void)
-{
- uint8_t prescaler_divider = 0;
-
- /* Set clock prescaler divider to ADC module*/
- prescaler_divider = (uint8_t)(clock_get_apb1_freq() / ADC_CLK);
- if (prescaler_divider >= 1)
- prescaler_divider = prescaler_divider - 1;
- if (prescaler_divider > 0x3F)
- prescaler_divider = 0x3F;
-
- /* Set Core Clock Division Factor in order to obtain the ADC clock */
- SET_FIELD(NPCX_ATCTL, NPCX_ATCTL_SCLKDIV_FIELD, prescaler_divider);
-}
-DECLARE_HOOK(HOOK_FREQ_CHANGE, adc_freq_changed, HOOK_PRIO_DEFAULT);
-
-/**
- * Flush an ADC sequencer and initiate a read.
- *
- * @param input_ch operation channel
- * @param timeout preset timeout
- * @return TRUE/FALSE success/fail
- * @notes set SW-triggered interrupt conversion and one-shot mode in npcx chip
- */
-static int start_single_and_wait(enum npcx_adc_input_channel input_ch
- , int timeout)
-{
- int event;
-
- task_waiting = task_get_current();
-
- /* Stop ADC conversion first */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_STOP);
-
- /* Set ADC conversion code to SW conversion mode */
- SET_FIELD(NPCX_ADCCNF, NPCX_ADCCNF_ADCMD_FIELD,
- ADC_CHN_CONVERSION_MODE);
-
- /* Set conversion type to one-shot type */
- CLEAR_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCRPTC);
-
- /* Update number of channel to be converted */
- SET_FIELD(NPCX_ASCADD, NPCX_ASCADD_SADDR_FIELD, input_ch);
-
- /* Clear End-of-Conversion Event status */
- SET_BIT(NPCX_ADCSTS, NPCX_ADCSTS_EOCEV);
-
- /* Enable ADC End-of-Conversion Interrupt if applicable */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_INTECEN);
-
- /* Start conversion */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_START);
-
- /* Wait for interrupt */
- event = task_wait_event_mask(TASK_EVENT_ADC_DONE, timeout);
-
- task_waiting = TASK_ID_INVALID;
-
- return (event == TASK_EVENT_ADC_DONE);
-
-}
-
-static uint16_t repetitive_enabled;
-void npcx_set_adc_repetitive(enum npcx_adc_input_channel input_ch, int enable)
-{
- mutex_lock(&adc_lock);
-
- /* Stop ADC conversion */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_STOP);
-
- if (enable) {
- /* Forbid EC enter deep sleep during conversion. */
- disable_sleep(SLEEP_MASK_ADC);
- /* Turn on ADC */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCEN);
- /* Set ADC conversion code to SW conversion mode */
- SET_FIELD(NPCX_ADCCNF, NPCX_ADCCNF_ADCMD_FIELD,
- ADC_SCAN_CONVERSION_MODE);
- /* Update number of channel to be converted */
- SET_BIT(NPCX_ADCCS, input_ch);
- /* Set conversion type to repetitive (runs continuously) */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCRPTC);
- repetitive_enabled |= BIT(input_ch);
-
- /* Start conversion */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_START);
- } else {
- CLEAR_BIT(NPCX_ADCCS, input_ch);
- repetitive_enabled &= ~BIT(input_ch);
-
- if (!repetitive_enabled) {
- /* Turn off ADC */
- CLEAR_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCEN);
- /* Set ADC to one-shot mode */
- CLEAR_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCRPTC);
- /* Allow ec enter deep sleep */
- enable_sleep(SLEEP_MASK_ADC);
- } else {
- /* Start conversion again */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_START);
- }
- }
-
- mutex_unlock(&adc_lock);
-}
-
-/**
- * Return the ADC value from CHNDAT register directly.
- *
- * @param input_ch channel number
- * @return ADC data
- */
-int adc_read_data(enum npcx_adc_input_channel input_ch)
-{
- const struct adc_t *adc = adc_channels + input_ch;
- int value;
- uint16_t chn_data;
-
- chn_data = NPCX_CHNDAT(adc->input_ch);
- value = GET_FIELD(chn_data, NPCX_CHNDAT_CHDAT_FIELD) *
- adc->factor_mul / adc->factor_div + adc->shift;
- return value;
-}
-
-/**
- * Start a single conversion and return the result
- *
- * @param ch operation channel
- * @return ADC converted voltage or error message
- */
-int adc_read_channel(enum adc_channel ch)
-{
- const struct adc_t *adc = adc_channels + ch;
- int value;
- uint16_t chn_data;
-
- mutex_lock(&adc_lock);
-
- /* Forbid ec enter deep sleep during ADC conversion is proceeding. */
- disable_sleep(SLEEP_MASK_ADC);
-
- /* Turn on ADC */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCEN);
-
- if (start_single_and_wait(adc->input_ch, ADC_TIMEOUT_US)) {
- chn_data = NPCX_CHNDAT(adc->input_ch);
- if ((adc->input_ch ==
- GET_FIELD(NPCX_ASCADD, NPCX_ASCADD_SADDR_FIELD))
- && (IS_BIT_SET(chn_data,
- NPCX_CHNDAT_NEW))) {
- value = GET_FIELD(chn_data, NPCX_CHNDAT_CHDAT_FIELD) *
- adc->factor_mul / adc->factor_div + adc->shift;
- } else {
- value = ADC_READ_ERROR;
- }
- } else {
- value = ADC_READ_ERROR;
- }
-
- if (!repetitive_enabled) {
- /* Turn off ADC */
- CLEAR_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCEN);
- /* Allow ec enter deep sleep */
- enable_sleep(SLEEP_MASK_ADC);
- } else {
- /* Set ADC conversion code to SW conversion mode */
- SET_FIELD(NPCX_ADCCNF, NPCX_ADCCNF_ADCMD_FIELD,
- ADC_SCAN_CONVERSION_MODE);
- /* Set conversion type to repetitive (runs continuously) */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCRPTC);
- /* Start conversion */
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_START);
- }
-
- mutex_unlock(&adc_lock);
-
- return value;
-}
-
-/* Board should register these callbacks with npcx_adc_cfg_thresh_int(). */
-static void (*adc_thresh_irqs[NPCX_ADC_THRESH_CNT])(void);
-
-void npcx_adc_thresh_int_enable(int threshold_idx, int enable)
-{
- uint16_t thrcts;
-
- enable = !!enable;
-
- if ((threshold_idx < 1) || (threshold_idx > NPCX_ADC_THRESH_CNT)) {
- CPRINTS("Invalid ADC thresh index! (%d)",
- threshold_idx);
- return;
- }
- threshold_idx--; /* convert to 0-based */
-
- /* avoid clearing other threshold status */
- thrcts = NPCX_THRCTS & ~GENMASK(NPCX_ADC_THRESH_CNT - 1, 0);
-
- if (enable) {
- /* clear threshold status */
- SET_BIT(thrcts, threshold_idx);
- /* set enable threshold status */
- SET_BIT(thrcts, NPCX_THRCTS_THR1_IEN + threshold_idx);
- } else {
- CLEAR_BIT(thrcts, NPCX_THRCTS_THR1_IEN + threshold_idx);
- }
- NPCX_THRCTS = thrcts;
-}
-
-void npcx_adc_register_thresh_irq(int threshold_idx,
- const struct npcx_adc_thresh_t *thresh_cfg)
-{
- int npcx_adc_ch;
- int raw_val;
- int mul;
- int div;
- int shift;
-
- if ((threshold_idx < 1) || (threshold_idx > NPCX_ADC_THRESH_CNT)) {
- CPRINTS("Invalid ADC thresh index! (%d)",
- threshold_idx);
- return;
- }
- npcx_adc_ch = adc_channels[thresh_cfg->adc_ch].input_ch;
-
- if (!thresh_cfg->adc_thresh_cb) {
- CPRINTS("No callback for ADC Threshold %d!",
- threshold_idx);
- return;
- }
-
- /* Fill in the table */
- adc_thresh_irqs[threshold_idx-1] = thresh_cfg->adc_thresh_cb;
-
- /* Select the channel */
- SET_FIELD(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_CHNSEL,
- npcx_adc_ch);
-
- if (thresh_cfg->lower_or_higher)
- SET_BIT(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_L_H);
- else
- CLEAR_BIT(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_L_H);
-
- /* Set the threshold value. */
- mul = adc_channels[thresh_cfg->adc_ch].factor_mul;
- div = adc_channels[thresh_cfg->adc_ch].factor_div;
- shift = adc_channels[thresh_cfg->adc_ch].shift;
-
- raw_val = (thresh_cfg->thresh_assert - shift) * div / mul;
- CPRINTS("ADC THR%d: Setting THRVAL = %d, L_H: %d", threshold_idx,
- raw_val, thresh_cfg->lower_or_higher);
- SET_FIELD(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_THRVAL,
- raw_val);
-
-#if NPCX_FAMILY_VERSION <= NPCX_FAMILY_NPCX7
- /* Disable deassertion threshold function */
- CLEAR_BIT(NPCX_THR_DCTL(threshold_idx), NPCX_THR_DCTL_THRD_EN);
-#endif
-
- /* Enable threshold detection */
- SET_BIT(NPCX_THRCTL(threshold_idx), NPCX_THRCTL_THEN);
-}
-
-/**
- * ADC interrupt handler
- *
- * @param none
- * @return none
- * @notes Only handle SW-triggered conversion in npcx chip
- */
-void adc_interrupt(void)
-{
- int i;
- uint16_t thrcts;
-
- if (IS_BIT_SET(NPCX_ADCCNF, NPCX_ADCCNF_INTECEN) &&
- IS_BIT_SET(NPCX_ADCSTS, NPCX_ADCSTS_EOCEV)) {
- /* Disable End-of-Conversion Interrupt */
- CLEAR_BIT(NPCX_ADCCNF, NPCX_ADCCNF_INTECEN);
-
- /* Stop conversion for single-shot mode */
- if (!repetitive_enabled)
- SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_STOP);
-
- /* Clear End-of-Conversion Event status */
- SET_BIT(NPCX_ADCSTS, NPCX_ADCSTS_EOCEV);
-
- /* Wake up the task which was waiting for the interrupt */
- if (task_waiting != TASK_ID_INVALID)
- task_set_event(task_waiting, TASK_EVENT_ADC_DONE);
- }
-
- for (i = NPCX_THRCTS_THR1_STS; i < NPCX_ADC_THRESH_CNT; i++) {
- if (IS_BIT_SET(NPCX_THRCTS, NPCX_THRCTS_THR1_IEN + i) &&
- IS_BIT_SET(NPCX_THRCTS, i)) {
- /* avoid clearing other threshold status */
- thrcts = NPCX_THRCTS &
- ~GENMASK(NPCX_ADC_THRESH_CNT - 1, 0);
- /* Clear threshold status */
- SET_BIT(thrcts, i);
- NPCX_THRCTS = thrcts;
- if (adc_thresh_irqs[i])
- adc_thresh_irqs[i]();
- }
- }
-}
-DECLARE_IRQ(NPCX_IRQ_ADC, adc_interrupt, 4);
-
-/**
- * ADC initial.
- *
- * @param none
- * @return none
- */
-static void adc_init(void)
-{
- /* Configure pins from GPIOs to ADCs */
- gpio_config_module(MODULE_ADC, 1);
-
- /* Enable ADC clock (bit4 mask = 0x10) */
- clock_enable_peripheral(CGC_OFFSET_ADC, CGC_ADC_MASK,
- CGC_MODE_RUN | CGC_MODE_SLEEP);
-
- /* Set Core Clock Division Factor in order to obtain the ADC clock */
- adc_freq_changed();
-
- /* Set regular speed */
- SET_FIELD(NPCX_ATCTL, NPCX_ATCTL_DLY_FIELD, (ADC_REGULAR_DLY - 1));
-
- /* Set the other ADC settings */
- NPCX_ADCCNF2 = ADC_REGULAR_ADCCNF2;
- NPCX_GENDLY = ADC_REGULAR_GENDLY;
- NPCX_MEAST = ADC_REGULAR_MEAST;
-
- task_waiting = TASK_ID_INVALID;
-
- /* Enable IRQs */
- task_enable_irq(NPCX_IRQ_ADC);
-}
-DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_INIT_ADC);