diff options
Diffstat (limited to 'common/usbc_intr_task.c')
-rw-r--r-- | common/usbc_intr_task.c | 213 |
1 files changed, 0 insertions, 213 deletions
diff --git a/common/usbc_intr_task.c b/common/usbc_intr_task.c deleted file mode 100644 index 0532645a35..0000000000 --- a/common/usbc_intr_task.c +++ /dev/null @@ -1,213 +0,0 @@ -/* 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 <stdint.h> - -#include "assert.h" -#include "common.h" -#include "compile_time_macros.h" -#include "console.h" -#include "ec_commands.h" -#include "task.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.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) -{ - /* - * Don't set event to idle task if task id is 0. This happens when - * not all the port have pd int task, the pd_int_task_id of port - * that doesn't have pd int task is 0. - */ - if (pd_int_task_id[port] != 0) - task_set_event(pd_int_task_id[port], PD_PROCESS_INTERRUPT); -} - -static struct { - int count; - timestamp_t time; -} storm_tracker[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static void service_one_port(int 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); - } -} - -__overridable void board_process_pd_alert(int port) -{ -} - -/* - * Main task entry point that handles PD interrupts for a single port. These - * interrupts usually come from a TCPC, but may also come from PD-related chips - * sharing the TCPC interrupt line. - * - * @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); - - 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) == 0) - continue; - /* - * 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)) { - - service_one_port(port); - } - - board_process_pd_alert(port); - } -} - -/* - * This code assumes port alert masks are adjacent to each other. - */ -BUILD_ASSERT(PD_STATUS_TCPC_ALERT_3 == (PD_STATUS_TCPC_ALERT_0 << 3)); - -/* - * Shared TCPC interrupt handler. The function argument in ec.tasklist - * is the mask of ports to handle. For example: - * - * BIT(USBC_PORT_C2) | BIT(USBC_PORT_C0) - * - * Note that this bitmask is 0-based while PD_STATUS_TCPC_ALERT_<port> - * is not. - */ - -void pd_shared_alert_task(void *p) -{ - const int sources_mask = (int) ((intptr_t) p); - int want_alerts = 0; - int port; - int port_mask; - - CPRINTS("%s: port mask 0x%02x", __func__, sources_mask); - - for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) { - if ((sources_mask & BIT(port)) == 0) - continue; - if (!board_is_usb_pd_port_present(port)) - continue; - - port_mask = PD_STATUS_TCPC_ALERT_0 << port; - want_alerts |= port_mask; - pd_int_task_id[port] = task_get_current(); - } - - if (want_alerts == 0) { - /* - * None of the configured alert sources are available. - */ - return; - } - - while (1) { - const int evt = task_wait_event(-1); - int have_alerts; - - if ((evt & PD_PROCESS_INTERRUPT) == 0) - continue; - - /* - * 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. - */ - do { - have_alerts = tcpc_get_alert_status(); - have_alerts &= want_alerts; - - for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; - ++port) { - port_mask = PD_STATUS_TCPC_ALERT_0 << port; - if ((have_alerts & port_mask) == 0) { - /* skip quiet port */ - continue; - } - if (!pd_is_port_enabled(port)) { - /* filter out disabled port */ - have_alerts &= ~port_mask; - continue; - } - service_one_port(port); - } - } while (have_alerts != 0); - } -} |