diff options
author | Andrew McRae <amcrae@google.com> | 2022-04-08 10:43:06 +1000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-04-12 01:17:34 +0000 |
commit | 4a7cea931e8980ed1b4e431e8bc06f03137d54fd (patch) | |
tree | 1a62d02799df79a357d944951480cbc4ab659bc3 | |
parent | 9f3f9b0cd55493f93c86cb8f239eb9f6a3a49303 (diff) | |
download | chrome-ec-4a7cea931e8980ed1b4e431e8bc06f03137d54fd.tar.gz |
ap_pwrseq: Add ADC interrupt enable/disable
Add interrupt enable/disable to the ADC power signal
handling, so that the ADC can be turned off when the
CPU is off, to save power.
BUG=b:228535753
TEST=zmake build nivviks; flash & run
BRANCH=none
Signed-off-by: Andrew McRae <amcrae@google.com>
Change-Id: If1cc4b52e215115d2a0eb3b30dae29a7a0fa8833
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3577313
Reviewed-by: Peter Marheine <pmarheine@chromium.org>
-rw-r--r-- | zephyr/subsys/ap_pwrseq/include/signal_adc.h | 24 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/power_signals.c | 8 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/signal_adc.c | 118 |
3 files changed, 114 insertions, 36 deletions
diff --git a/zephyr/subsys/ap_pwrseq/include/signal_adc.h b/zephyr/subsys/ap_pwrseq/include/signal_adc.h index 92570beef1..294a3455a3 100644 --- a/zephyr/subsys/ap_pwrseq/include/signal_adc.h +++ b/zephyr/subsys/ap_pwrseq/include/signal_adc.h @@ -41,6 +41,30 @@ DT_FOREACH_STATUS_OKAY(intel_ap_pwrseq_adc, PWR_ADC_ENUM) int power_signal_adc_get(enum pwr_sig_adc adc); /** + * @brief Enable the ADC interrupt + * + * This will not only enable the interrupt driven update + * of this signal, but will also enable the ADC itself. + * + * @param signal The pwr_sig_adc to enable. + * @return 0 if successful + * @return -error if failed + */ +int power_signal_adc_enable_int(enum pwr_sig_adc adc); + +/** + * @brief Disable the ADC interrupt + * + * This will disable the interrupt updating of this signal, and will + * also disable the ADC from running. + * + * @param signal The pwr_sig_adc to disable. + * @return 0 if successful + * @return -error if failed + */ +int power_signal_adc_disable_int(enum pwr_sig_adc adc); + +/** * @brief Initialize the ADCs for the power signals. */ void power_signal_adc_init(void); diff --git a/zephyr/subsys/ap_pwrseq/power_signals.c b/zephyr/subsys/ap_pwrseq/power_signals.c index e6bdb05954..d103c4c56b 100644 --- a/zephyr/subsys/ap_pwrseq/power_signals.c +++ b/zephyr/subsys/ap_pwrseq/power_signals.c @@ -246,6 +246,10 @@ int power_signal_enable_interrupt(enum power_signal signal) case PWR_SIG_SRC_GPIO: return power_signal_gpio_enable_int(cp->src_enum); #endif +#if HAS_ADC_SIGNALS + case PWR_SIG_SRC_ADC: + return power_signal_adc_enable_int(cp->src_enum); +#endif } } @@ -265,6 +269,10 @@ int power_signal_disable_interrupt(enum power_signal signal) case PWR_SIG_SRC_GPIO: return power_signal_gpio_disable_int(cp->src_enum); #endif +#if HAS_ADC_SIGNALS + case PWR_SIG_SRC_ADC: + return power_signal_adc_disable_int(cp->src_enum); +#endif } } diff --git a/zephyr/subsys/ap_pwrseq/signal_adc.c b/zephyr/subsys/ap_pwrseq/signal_adc.c index 9f07b73964..7ee394a623 100644 --- a/zephyr/subsys/ap_pwrseq/signal_adc.c +++ b/zephyr/subsys/ap_pwrseq/signal_adc.c @@ -33,42 +33,70 @@ static const struct adc_config config[] = { DT_FOREACH_STATUS_OKAY(MY_COMPAT, INIT_ADC_CONFIG) }; -static atomic_t value[ARRAY_SIZE(config)]; +/* + * Bit allocations for atomic state + */ +enum { + ADC_BIT_VALUE = 0, + ADC_BIT_LOW_ENABLED = 1, + ADC_BIT_HIGH_ENABLED = 2 +}; + +atomic_t adc_state[ARRAY_SIZE(config)]; + +static void set_trigger(const struct device *dev, + atomic_t *state, + int bit, + bool enable) +{ + /* + * Only enable or disable if the trigger is not + * already enabled or disabled. + */ + if (enable + ? !atomic_test_and_set_bit(state, bit) + : atomic_test_and_clear_bit(state, bit)) { + struct sensor_value val; + + val.val1 = enable; + sensor_attr_set(dev, + SENSOR_CHAN_VOLTAGE, + SENSOR_ATTR_ALERT, + &val); + } +} + +static void set_low_trigger(enum pwr_sig_adc adc, bool enable) +{ + set_trigger(config[adc].dev_trig_low, + &adc_state[adc], + ADC_BIT_LOW_ENABLED, + enable); + +} + +static void set_high_trigger(enum pwr_sig_adc adc, bool enable) +{ + set_trigger(config[adc].dev_trig_high, + &adc_state[adc], + ADC_BIT_HIGH_ENABLED, + enable); +} static void trigger_high(enum pwr_sig_adc adc) { - struct sensor_value val; - - atomic_set_bit(&value[adc], 0); - val.val1 = false; - sensor_attr_set(config[adc].dev_trig_high, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); - val.val1 = true; - sensor_attr_set(config[adc].dev_trig_low, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); + atomic_set_bit(&adc_state[adc], ADC_BIT_VALUE); + set_low_trigger(adc, true); + set_high_trigger(adc, false); LOG_DBG("power signal adc%d is HIGH", adc); power_signal_interrupt(config[adc].signal, 1); } static void trigger_low(enum pwr_sig_adc adc) { - struct sensor_value val; - - atomic_clear_bit(&value[adc], 0); - val.val1 = false; - sensor_attr_set(config[adc].dev_trig_low, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); - val.val1 = true; - sensor_attr_set(config[adc].dev_trig_high, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); + atomic_clear_bit(&adc_state[adc], ADC_BIT_VALUE); + set_low_trigger(adc, false); + set_high_trigger(adc, true); LOG_DBG("power signal adc%d is LOW", adc); power_signal_interrupt(config[adc].signal, 0); } @@ -78,7 +106,32 @@ int power_signal_adc_get(enum pwr_sig_adc adc) if (adc < 0 || adc >= ARRAY_SIZE(config)) { return -EINVAL; } - return !!value[adc]; + return atomic_test_bit(&adc_state[adc], ADC_BIT_VALUE); +} + +int power_signal_adc_enable_int(enum pwr_sig_adc adc) +{ + if (adc < 0 || adc >= ARRAY_SIZE(config)) { + return -EINVAL; + } + + /* Only need to enable relevant trigger depending on current state */ + if (atomic_test_bit(&adc_state[adc], ADC_BIT_VALUE)) { + set_low_trigger(adc, true); + } else { + set_high_trigger(adc, true); + } + return 0; +} + +int power_signal_adc_disable_int(enum pwr_sig_adc adc) +{ + if (adc < 0 || adc >= ARRAY_SIZE(config)) { + return -EINVAL; + } + set_low_trigger(adc, false); + set_high_trigger(adc, false); + return 0; } /* @@ -110,7 +163,6 @@ void power_signal_adc_init(void) .type = SENSOR_TRIG_THRESHOLD, .chan = SENSOR_CHAN_VOLTAGE }; - struct sensor_value val; sensor_trigger_handler_t low_cb[] = { DT_FOREACH_STATUS_OKAY_VARGS(MY_COMPAT, ADC_CB_COMMA, low) }; @@ -123,13 +175,7 @@ void power_signal_adc_init(void) /* Set high and low trigger callbacks */ sensor_trigger_set(config[i].dev_trig_high, &trig, high_cb[i]); sensor_trigger_set(config[i].dev_trig_low, &trig, low_cb[i]); - - /* Enable high trigger callback only */ - val.val1 = true; - sensor_attr_set(config[i].dev_trig_high, - SENSOR_CHAN_VOLTAGE, - SENSOR_ATTR_ALERT, - &val); + power_signal_adc_enable_int(i); } } |