summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/build.mk1
-rw-r--r--common/usb_pd_protocol.c96
-rw-r--r--common/usbc/usbc_task.c100
-rw-r--r--common/usbc_intr_task.c105
4 files changed, 109 insertions, 193 deletions
diff --git a/common/build.mk b/common/build.mk
index 4ef78d57f5..ebaa3cc582 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -143,6 +143,7 @@ common-$(CONFIG_USB_CONSOLE_STREAM)+=usb_console_stream.o
common-$(CONFIG_USB_I2C)+=usb_i2c.o
common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o
common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o
+common-$(CONFIG_HAS_TASK_PD_INT)+=usbc_intr_task.o
ifneq ($(CONFIG_USB_POWER_DELIVERY),)
common-$(CONFIG_USB_POWER_DELIVERY)+=usb_common.o
ifneq ($(CONFIG_USB_PD_TCPMV1),)
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 45b91397b2..aed9e4dd86 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -2754,97 +2754,6 @@ static int pd_restart_tcpc(int port)
}
#endif
-/* High-priority interrupt tasks implementations */
-#ifdef CONFIG_HAS_TASK_PD_INT
-
-/* Used to conditionally compile code in main pd task. */
-#define HAS_DEFFERED_INTERRUPT_HANDLER
-
-/* Events for pd_interrupt_handler_task */
-#define PD_PROCESS_INTERRUPT BIT(0)
-
-static uint8_t pd_int_task_id[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void schedule_deferred_pd_interrupt(const int port)
-{
- task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT, 0);
-}
-
-/*
- * Theoretically, we may need to support up to 480 USB-PD packets per second for
- * intensive operations such as FW update over PD. This value has tested well
- * preventing watchdog resets with a single bad port partner plugged in.
- */
-#define ALERT_STORM_MAX_COUNT 480
-#define ALERT_STORM_INTERVAL SECOND
-
-/**
- * Main task entry point that handles PD interrupts for a single port
- *
- * @param p The PD port number for which to handle interrupts (pointer is
- * reinterpreted as an integer directly).
- */
-void pd_interrupt_handler_task(void *p)
-{
- const int port = (int) ((intptr_t) p);
- const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port);
- struct {
- int count;
- timestamp_t time;
- } storm_tracker[CONFIG_USB_PD_PORT_MAX_COUNT] = {};
-
- ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- pd_int_task_id[port] = task_get_current();
-
- while (1) {
- const int evt = task_wait_event(-1);
-
- if (evt & PD_PROCESS_INTERRUPT) {
- /*
- * While the interrupt signal is asserted; we have more
- * work to do. This effectively makes the interrupt a
- * level-interrupt instead of an edge-interrupt without
- * having to enable/disable a real level-interrupt in
- * multiple locations.
- *
- * Also, if the port is disabled do not process
- * interrupts. Upon existing suspend, we schedule a
- * PD_PROCESS_INTERRUPT to check if we missed anything.
- */
- while ((tcpc_get_alert_status() & port_mask) &&
- pd_is_port_enabled(port)) {
- timestamp_t now;
-
- tcpc_alert(port);
-
- now = get_time();
- if (timestamp_expired(
- storm_tracker[port].time, &now)) {
- /* Reset timer into future */
- storm_tracker[port].time.val =
- now.val + ALERT_STORM_INTERVAL;
-
- /*
- * Start at 1 since we are processing
- * an interrupt now
- */
- storm_tracker[port].count = 1;
- } else if (++storm_tracker[port].count >
- ALERT_STORM_MAX_COUNT) {
- CPRINTS("C%d Interrupt storm detected. "
- "Disabling port for 5 seconds.",
- port);
-
- pd_set_suspend(port, 1);
- pd_deferred_resume(port);
- }
- }
- }
- }
-}
-#endif /* CONFIG_HAS_TASK_PD_INT */
-
static void pd_send_enter_usb(int port, int *timeout)
{
uint32_t usb4_payload;
@@ -3100,7 +3009,6 @@ void pd_task(void *u)
charge_manager_update_dualrole(port, CAP_UNKNOWN);
#endif
-#ifdef HAS_DEFFERED_INTERRUPT_HANDLER
/*
* Since most boards configure the TCPC interrupt as edge
* and it is possible that the interrupt line was asserted between init
@@ -3108,8 +3016,8 @@ void pd_task(void *u)
* Otherwise future interrupts will never fire because another edge
* never happens. Note this needs to happen after set_state() is called.
*/
- schedule_deferred_pd_interrupt(port);
-#endif
+ if (IS_ENABLED(CONFIG_HAS_TASK_PD_INT))
+ schedule_deferred_pd_interrupt(port);
while (1) {
/* process VDM messages last */
diff --git a/common/usbc/usbc_task.c b/common/usbc/usbc_task.c
index f52d19ea0d..7099154f38 100644
--- a/common/usbc/usbc_task.c
+++ b/common/usbc/usbc_task.c
@@ -56,104 +56,6 @@ void tc_start_event_loop(int port)
}
}
-/* High-priority interrupt tasks implementations */
-#ifdef CONFIG_HAS_TASK_PD_INT
-
-/* Used to conditionally compile code in main pd task. */
-#define HAS_DEFFERED_INTERRUPT_HANDLER
-
-/* Events for pd_interrupt_handler_task */
-#define PD_PROCESS_INTERRUPT (1<<0)
-
-static uint8_t pd_int_task_id[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-void schedule_deferred_pd_interrupt(const int port)
-{
- task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT, 0);
-}
-
-/*
- * Theoretically, we may need to support up to 400 USB-PD packets per second for
- * intensive operations such as FW update over PD. This value has tested well
- * preventing watchdog resets with a single bad port partner plugged in.
- */
-#define ALERT_STORM_MAX_COUNT 400
-#define ALERT_STORM_INTERVAL SECOND
-
-/*
- * Main task entry point that handles PD interrupts for a single port
- *
- * @param p The PD port number for which to handle interrupts (pointer is
- * reinterpreted as an integer directly).
- */
-void pd_interrupt_handler_task(void *p)
-{
- const int port = (int) ((intptr_t) p);
- const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port);
- struct {
- int count;
- timestamp_t time;
- } storm_tracker[CONFIG_USB_PD_PORT_MAX_COUNT] = {};
-
- ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
-
- /*
- * If port does not exist, return
- */
- if (port >= board_get_usb_pd_port_count())
- return;
-
- pd_int_task_id[port] = task_get_current();
-
- while (1) {
- const int evt = task_wait_event(-1);
-
- if (evt & PD_PROCESS_INTERRUPT) {
- /*
- * While the interrupt signal is asserted; we have more
- * work to do. This effectively makes the interrupt a
- * level-interrupt instead of an edge-interrupt without
- * having to enable/disable a real level-interrupt in
- * multiple locations.
- *
- * Also, if the port is disabled do not process
- * interrupts. Upon existing suspend, we schedule a
- * PD_PROCESS_INTERRUPT to check if we missed anything.
- */
- while ((tcpc_get_alert_status() & port_mask) &&
- pd_is_port_enabled(port)) {
- timestamp_t now;
-
- tcpc_alert(port);
-
- now = get_time();
- if (timestamp_expired(storm_tracker[port].time,
- &now)) {
- /* Reset timer into future */
- storm_tracker[port].time.val =
- now.val + ALERT_STORM_INTERVAL;
-
- /*
- * Start at 1 since we are processing an
- * interrupt right now
- */
- storm_tracker[port].count = 1;
- } else if (++storm_tracker[port].count >
- ALERT_STORM_MAX_COUNT) {
- CPRINTS("C%d: Interrupt storm detected."
- " Disabling port temporarily",
- port);
-
- pd_set_suspend(port, 1);
- pd_deferred_resume(port);
- }
- }
- }
- }
-}
-#endif /* CONFIG_HAS_TASK_PD_INT */
-
-
static void pd_task_init(int port)
{
if (IS_ENABLED(CONFIG_USB_TYPEC_SM))
@@ -167,7 +69,7 @@ static void pd_task_init(int port)
* Otherwise future interrupts will never fire because another edge
* never happens. Note this needs to happen after set_state() is called.
*/
- if (IS_ENABLED(HAS_DEFFERED_INTERRUPT_HANDLER))
+ if (IS_ENABLED(CONFIG_HAS_TASK_PD_INT))
schedule_deferred_pd_interrupt(port);
}
diff --git a/common/usbc_intr_task.c b/common/usbc_intr_task.c
new file mode 100644
index 0000000000..ca410363f1
--- /dev/null
+++ b/common/usbc_intr_task.c
@@ -0,0 +1,105 @@
+/* Copyright 2020 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.
+ */
+
+/* High-priority interrupt tasks implementations */
+
+#include "console.h"
+#include "task.h"
+#include "timer.h"
+#include "usb_mux.h"
+#include "usb_pd.h"
+
+#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
+
+/* Events for pd_interrupt_handler_task */
+#define PD_PROCESS_INTERRUPT BIT(0)
+
+/*
+ * Theoretically, we may need to support up to 480 USB-PD packets per second for
+ * intensive operations such as FW update over PD. This value has tested well
+ * preventing watchdog resets with a single bad port partner plugged in.
+ */
+#define ALERT_STORM_MAX_COUNT 480
+#define ALERT_STORM_INTERVAL SECOND
+
+static uint8_t pd_int_task_id[CONFIG_USB_PD_PORT_MAX_COUNT];
+
+void schedule_deferred_pd_interrupt(const int port)
+{
+ task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT, 0);
+}
+
+/*
+ * Main task entry point that handles PD interrupts for a single port
+ *
+ * @param p The PD port number for which to handle interrupts (pointer is
+ * reinterpreted as an integer directly).
+ */
+void pd_interrupt_handler_task(void *p)
+{
+ const int port = (int) ((intptr_t) p);
+ const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port);
+ struct {
+ int count;
+ timestamp_t time;
+ } storm_tracker[CONFIG_USB_PD_PORT_MAX_COUNT] = {};
+
+ ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
+
+ /*
+ * If port does not exist, return
+ */
+ if (port >= board_get_usb_pd_port_count())
+ return;
+
+ pd_int_task_id[port] = task_get_current();
+
+ while (1) {
+ const int evt = task_wait_event(-1);
+
+ if (evt & PD_PROCESS_INTERRUPT) {
+ /*
+ * While the interrupt signal is asserted; we have more
+ * work to do. This effectively makes the interrupt a
+ * level-interrupt instead of an edge-interrupt without
+ * having to enable/disable a real level-interrupt in
+ * multiple locations.
+ *
+ * Also, if the port is disabled do not process
+ * interrupts. Upon existing suspend, we schedule a
+ * PD_PROCESS_INTERRUPT to check if we missed anything.
+ */
+ while ((tcpc_get_alert_status() & port_mask) &&
+ pd_is_port_enabled(port)) {
+ timestamp_t now;
+
+ tcpc_alert(port);
+
+ now = get_time();
+ if (timestamp_expired(storm_tracker[port].time,
+ &now)) {
+ /* Reset timer into future */
+ storm_tracker[port].time.val =
+ now.val + ALERT_STORM_INTERVAL;
+
+ /*
+ * Start at 1 since we are processing an
+ * interrupt right now
+ */
+ storm_tracker[port].count = 1;
+ } else if (++storm_tracker[port].count >
+ ALERT_STORM_MAX_COUNT) {
+ CPRINTS("C%d: Interrupt storm detected."
+ " Disabling port temporarily",
+ port);
+
+ pd_set_suspend(port, 1);
+ pd_deferred_resume(port);
+ }
+ }
+ }
+ }
+}