summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Short <keithshort@chromium.org>2022-04-27 09:48:45 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-28 23:37:57 +0000
commita123436acbb7aa28bf31986beb703a3007c63d85 (patch)
tree53d8a401cf9fcc0f97381a12abaadd2c7d8fc15e
parentd2e7a65e711220ca1faab4b815b0cf9244ca9ced (diff)
downloadchrome-ec-a123436acbb7aa28bf31986beb703a3007c63d85.tar.gz
throttle_ap: Add option to gate PROCHOT based on C10
For some x86 boards, the PROCHOT signal is not valid once the AP enters the C10 state. Add an option to gate PROCHOT detection if the C10 state is asserted. When the AP exits C10, the EC rechecks the PROCHOT state. Note that only the Volteer baseboard enables the PROCHOT interrupt, so it is the only board that is updated to call throttle_ap_config_prochot(). All gpio.inc files that connect to throttle_ap_prochot_input_interrupt() all use the pin name EC_PROCHOT_IN_L. Confirmed with these searches: $ grep -r "GPIO_INT.*throttle_ap_prochot_input_interrupt" . \ | wc -l 31 $ grep -r "EC_PROCHOT_IN_L.*throttle_ap_prochot_input_interrupt" . \ | wc -l 31 $ grep -r "gpio_enable_interrupt.*EC_PROCHOT_IN_L" . ./baseboard/volteer/power.c: \ gpio_enable_interrupt(GPIO_EC_PROCHOT_IN_L); BUG=b:185810479 BRANCH=volteer TEST=make buildall Signed-off-by: Keith Short <keithshort@chromium.org> Change-Id: I73fb328675d9faade13fe0192570dc838de028a6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3615479 Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
-rw-r--r--baseboard/volteer/power.c6
-rw-r--r--common/throttle_ap.c62
-rw-r--r--include/config.h8
-rw-r--r--include/throttle_ap.h33
-rw-r--r--util/config_allowed.txt1
-rw-r--r--zephyr/Kconfig.powerseq9
-rw-r--r--zephyr/shim/include/config_chip.h5
7 files changed, 112 insertions, 12 deletions
diff --git a/baseboard/volteer/power.c b/baseboard/volteer/power.c
index fa20cfa93f..005319c3fa 100644
--- a/baseboard/volteer/power.c
+++ b/baseboard/volteer/power.c
@@ -6,6 +6,7 @@
#include "gpio.h"
#include "hooks.h"
#include "power/icelake.h"
+#include "throttle_ap.h"
/*
* PWROK signal configuration, see the PWROK Generation Flow Diagram (Figure
@@ -48,9 +49,14 @@ const struct intel_x86_pwrok_signal pwrok_signal_deassert_list[] = {
};
const int pwrok_signal_deassert_count = ARRAY_SIZE(pwrok_signal_deassert_list);
+static const struct prochot_cfg volteer_prochot_cfg = {
+ .gpio_prochot_in = GPIO_EC_PROCHOT_IN_L,
+};
+
static void baseboard_init(void)
{
/* Enable monitoring of the PROCHOT input to the EC */
+ throttle_ap_config_prochot(&volteer_prochot_cfg);
gpio_enable_interrupt(GPIO_EC_PROCHOT_IN_L);
}
DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_DEFAULT);
diff --git a/common/throttle_ap.c b/common/throttle_ap.c
index 6d794916ae..33e004ba7b 100644
--- a/common/throttle_ap.c
+++ b/common/throttle_ap.c
@@ -21,14 +21,20 @@
#define CPUTS(outstr) cputs(CC_THERMAL, outstr)
#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args)
+/*
+ * When C10 deasserts, PROCHOT may also change state when the corresponding
+ * power rail is turned back on. Recheck PROCHOT directly from the C10 exit
+ * using a shorter debounce than the PROCHOT interrupt.
+ */
#define PROCHOT_IN_DEBOUNCE_US (100 * MSEC)
+#define C10_IN_DEBOUNCE_US (10 * MSEC)
/*****************************************************************************/
/* This enforces the virtual OR of all throttling sources. */
K_MUTEX_DEFINE(throttle_mutex);
static uint32_t throttle_request[NUM_THROTTLE_TYPES];
static int debounced_prochot_in;
-static enum gpio_signal gpio_prochot_in = GPIO_COUNT;
+static const struct prochot_cfg *prochot_cfg;
void throttle_ap(enum throttle_level level,
enum throttle_type type,
@@ -78,17 +84,36 @@ void throttle_ap(enum throttle_level level,
}
+void throttle_ap_config_prochot(const struct prochot_cfg *cfg)
+{
+ prochot_cfg = cfg;
+}
+
+__maybe_unused static bool prochot_is_gated_by_c10(int prochot_in)
+{
+#ifdef CONFIG_CPU_PROCHOT_GATE_ON_C10
+ int c10_in = gpio_get_level(prochot_cfg->gpio_c10_in);
+
+ if (!prochot_cfg->c10_active_high)
+ c10_in = !c10_in;
+
+ if (c10_in && prochot_in) {
+ return true;
+ }
+#endif
+ return false;
+}
+
static void prochot_input_deferred(void)
{
int prochot_in;
/*
- * Shouldn't be possible, but better to protect against buffer
- * overflow
+ * Validate board called throttle_ap_config_prochot().
*/
- ASSERT(signal_is_gpio(gpio_prochot_in));
+ ASSERT(prochot_cfg);
- prochot_in = gpio_get_level(gpio_prochot_in);
+ prochot_in = gpio_get_level(prochot_cfg->gpio_prochot_in);
if (IS_ENABLED(CONFIG_CPU_PROCHOT_ACTIVE_LOW))
prochot_in = !prochot_in;
@@ -106,6 +131,14 @@ static void prochot_input_deferred(void)
if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
return;
+ /*
+ * b/185810479 When the AP enters C10, the PROCHOT signal may not be
+ * valid. Refer to the CONFIG_CPU_PROCHOT_GATE_ON_C10 documentation
+ * for details.
+ */
+ if (prochot_is_gated_by_c10(prochot_in))
+ return;
+
debounced_prochot_in = prochot_in;
if (debounced_prochot_in) {
@@ -126,13 +159,6 @@ DECLARE_DEFERRED(prochot_input_deferred);
void throttle_ap_prochot_input_interrupt(enum gpio_signal signal)
{
/*
- * Save the PROCHOT signal that generated the interrupt so we don't
- * rely on a specific pin name.
- */
- if (gpio_prochot_in == GPIO_COUNT)
- gpio_prochot_in = signal;
-
- /*
* Trigger deferred notification of PROCHOT change so we can ignore
* any pulses that are too short.
*/
@@ -140,6 +166,18 @@ void throttle_ap_prochot_input_interrupt(enum gpio_signal signal)
PROCHOT_IN_DEBOUNCE_US);
}
+#ifdef CONFIG_CPU_PROCHOT_GATE_ON_C10
+void throttle_ap_c10_input_interrupt(enum gpio_signal signal)
+{
+ /*
+ * This interrupt is configured to fire only when the AP exits C10
+ * and de-asserts the C10 signal. Recheck the PROCHOT signal in case
+ * another PROCHOT source is active when the AP exits C10.
+ */
+ hook_call_deferred(&prochot_input_deferred_data, C10_IN_DEBOUNCE_US);
+}
+#endif
+
/*****************************************************************************/
/* Console commands */
#ifdef CONFIG_CMD_APTHROTTLE
diff --git a/include/config.h b/include/config.h
index 8ba8a4de0c..f7a507655b 100644
--- a/include/config.h
+++ b/include/config.h
@@ -3623,6 +3623,14 @@
*/
#undef CONFIG_CPU_PROCHOT_ACTIVE_LOW
+/*
+ * When the AP enters C10, the power rails VCCIO, VCCSTG, and VCCPLL_OC may be
+ * turned off by the board. If the PROCHOT# signal is pulled up by any of
+ * these rails, PROCHOT cannot be relied upon while C10 is active.
+ * Enable this option to gate PROCHOT detection when C10 is active.
+ */
+#undef CONFIG_CPU_PROCHOT_GATE_ON_C10
+
/* Support PS/2 interface */
#undef CONFIG_PS2
diff --git a/include/throttle_ap.h b/include/throttle_ap.h
index fbfa36aed3..09669d70b1 100644
--- a/include/throttle_ap.h
+++ b/include/throttle_ap.h
@@ -35,6 +35,19 @@ enum throttle_sources {
};
/**
+ * PROCHOT detection GPIOs. PROCHOT in assumed to be active high unless
+ * CONFIG_CPU_PROCHOT_ACTIVE_LOW is enabled.
+ * C10 input polarity is explicitly specified in the struct below.
+ */
+struct prochot_cfg {
+ enum gpio_signal gpio_prochot_in;
+#ifdef CONFIG_CPU_PROCHOT_GATE_ON_C10
+ enum gpio_signal gpio_c10_in;
+ bool c10_active_high;
+#endif
+};
+
+/**
* Enable/disable CPU throttling.
*
* This is a virtual "OR" operation. Any caller can enable CPU throttling of
@@ -53,6 +66,14 @@ void throttle_ap(enum throttle_level level,
enum throttle_sources source);
/**
+ * Configure the GPIOs used to monitor the PROCHOT signal.
+ *
+ * @param cfg GPIO configuration for the PROCHOT and optional C10
+ * signals.
+ */
+void throttle_ap_config_prochot(const struct prochot_cfg *cfg);
+
+/**
* Interrupt handler to monitor PROCHOT input to the EC. The PROCHOT signal
* can be asserted by the AP or by other devices on the board, such as chargers
* and voltage regulators.
@@ -65,6 +86,18 @@ void throttle_ap(enum throttle_level level,
*/
void throttle_ap_prochot_input_interrupt(enum gpio_signal signal);
+/**
+ * Interrupt handler to monitor the C10 input to the EC. The C10 signal
+ * can be asserted by the AP when entering an idle state. This interrupt
+ * is configured for the edge indicating C10 is de-asserting (GPIO_INT_RISING
+ * if the signal is active low, GPIO_INT_FALLING for an active high signal).
+ *
+ * The board initialization is responsible for enabling the interrupt.
+ *
+ * @param signal GPIO signal connected to C10 input.
+ */
+void throttle_ap_c10_input_interrupt(enum gpio_signal signal);
+
#else
static inline void throttle_ap(enum throttle_level level,
enum throttle_type type,
diff --git a/util/config_allowed.txt b/util/config_allowed.txt
index f34197d4b6..d8e6959794 100644
--- a/util/config_allowed.txt
+++ b/util/config_allowed.txt
@@ -338,6 +338,7 @@ CONFIG_CONSOLE_INPUT_LINE_SIZE
CONFIG_CONSOLE_UART
CONFIG_CONSOLE_VERBOSE
CONFIG_CPU_PROCHOT_ACTIVE_LOW
+CONFIG_CPU_PROCHOT_GATE_ON_C10
CONFIG_CRC8
CONFIG_CROS_EC_RO_MEM_SIZE
CONFIG_CROS_EC_RW_MEM_SIZE
diff --git a/zephyr/Kconfig.powerseq b/zephyr/Kconfig.powerseq
index a99453f5a7..cee5be53a4 100644
--- a/zephyr/Kconfig.powerseq
+++ b/zephyr/Kconfig.powerseq
@@ -104,6 +104,15 @@ config PLATFORM_EC_POWERSEQ_CPU_PROCHOT_ACTIVE_LOW
If CPU_PROCHOT should be treated as active-low, enable this
configuration option.
+config PLATFORM_EC_POWERSEQ_CPU_PROCHOT_GATE_ON_C10
+ bool "Gate PROCHOT detection based on the AP C10 state"
+ default y if PLATFORM_EC_POWERSEQ_CPU_PROCHOT_ACTIVE_LOW
+ help
+ When the AP enters C10, the power rails VCCIO, VCCSTG, and VCCPLL_OC
+ may be turned off by the board. If the PROCHOT# signal is pulled up
+ by any of these rails, PROCHOT is not valid while the AP is in C10,
+ Enable this option to gate PROCHOT detection when C10 is active.
+
config PLATFORM_EC_POWERSEQ_RTC_RESET
bool "Board has an RTC reset"
help
diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h
index 416e1f397a..ceaaa17193 100644
--- a/zephyr/shim/include/config_chip.h
+++ b/zephyr/shim/include/config_chip.h
@@ -816,6 +816,11 @@ extern struct jump_data mock_jump_data;
#define CONFIG_CPU_PROCHOT_ACTIVE_LOW
#endif
+#undef CONFIG_CPU_PROCHOT_GATE_ON_C10
+#ifdef CONFIG_PLATFORM_EC_POWERSEQ_CPU_PROCHOT_GATE_ON_C10
+#define CONFIG_CPU_PROCHOT_GATE_ON_C10
+#endif
+
#undef CONFIG_POWER_TRACK_HOST_SLEEP_STATE
#if defined(CONFIG_PLATFORM_EC_POWERSEQ_HOST_SLEEP) || \
defined(CONFIG_AP_PWRSEQ_HOST_SLEEP)