summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew McRae <amcrae@google.com>2022-04-08 10:43:06 +1000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-12 01:17:34 +0000
commit4a7cea931e8980ed1b4e431e8bc06f03137d54fd (patch)
tree1a62d02799df79a357d944951480cbc4ab659bc3
parent9f3f9b0cd55493f93c86cb8f239eb9f6a3a49303 (diff)
downloadchrome-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.h24
-rw-r--r--zephyr/subsys/ap_pwrseq/power_signals.c8
-rw-r--r--zephyr/subsys/ap_pwrseq/signal_adc.c118
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);
}
}