summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/battery_fuel_gauge.c110
-rw-r--r--common/build.mk3
-rw-r--r--common/button.c7
-rw-r--r--common/charge_manager.c4
-rw-r--r--common/charge_ramp.c21
-rw-r--r--common/charge_state_v2.c13
-rw-r--r--common/device_event.c8
-rw-r--r--common/dptf.c8
-rw-r--r--common/ec_features.c3
-rw-r--r--common/fmap.c2
-rw-r--r--common/fpsensor/fpsensor.c2
-rw-r--r--common/fpsensor/fpsensor_state.c3
-rw-r--r--common/host_event_commands.c4
-rw-r--r--common/i2c_controller.c4
-rw-r--r--common/i2c_trace.c4
-rw-r--r--common/keyboard_scan.c8
-rw-r--r--common/led_common.c12
-rw-r--r--common/mkbp_fifo.c2
-rw-r--r--common/mock/usb_pd_dpm_mock.c4
-rw-r--r--common/motion_sense.c2
-rw-r--r--common/ocpc.c1
-rw-r--r--common/peripheral_charger.c2
-rw-r--r--common/system.c6
-rw-r--r--common/thermal.c4
-rw-r--r--common/timer.c6
-rw-r--r--common/usb_common.c8
-rw-r--r--common/usb_pd_host_cmd.c2
-rw-r--r--common/usb_pd_protocol.c4
-rw-r--r--common/usbc/dp_alt_mode.c8
-rw-r--r--common/usbc/usb_pd_dpm.c60
-rw-r--r--common/usbc/usb_pd_timer.c38
-rw-r--r--common/usbc/usb_pe_drp_sm.c314
-rw-r--r--common/usbc/usb_prl_sm.c10
-rw-r--r--common/usbc/usb_retimer_fw_update.c40
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c23
-rw-r--r--common/usbc_ocp.c4
36 files changed, 620 insertions, 134 deletions
diff --git a/common/battery_fuel_gauge.c b/common/battery_fuel_gauge.c
index 528713d68f..5555255188 100644
--- a/common/battery_fuel_gauge.c
+++ b/common/battery_fuel_gauge.c
@@ -14,11 +14,83 @@
#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
+/*
+ * Authenticate the battery connected.
+ *
+ * Compare the manufacturer name read from the fuel gauge to the
+ * manufacturer names defined in the board_battery_info table. If
+ * a device name has been specified in the board_battery_info table,
+ * then both the manufacturer and device name must match.
+ */
+static bool authenticate_battery_type(int index, char *manuf_name)
+{
+ char device_name[32];
+
+ const struct fuel_gauge_info * const fuel_gauge =
+ &board_battery_info[index].fuel_gauge;
+ int len = 0;
+
+ /* check for valid index */
+ if (index >= BATTERY_TYPE_COUNT)
+ return false;
+
+ /* manufacturer name mismatch */
+ if (strcasecmp(manuf_name, fuel_gauge->manuf_name))
+ return false;
+
+ /* device name is specified in table */
+ if (fuel_gauge->device_name != NULL) {
+
+ /* Get the device name */
+ if (battery_device_name(device_name,
+ sizeof(device_name)))
+ return false;
+
+ len = strlen(fuel_gauge->device_name);
+
+ /* device name mismatch */
+ if (strncasecmp(device_name, fuel_gauge->device_name,
+ len))
+ return false;
+ }
+
+ CPRINTS("found batt:%s", fuel_gauge->manuf_name);
+ return true;
+}
+
+#ifdef CONFIG_BATTERY_TYPE_NO_AUTO_DETECT
+
+/* Variable to decide the battery type */
+static int fixed_battery_type = BATTERY_TYPE_UNINITIALIZED;
+
+/*
+ * Function to get the fixed battery type.
+ */
+static int battery_get_fixed_battery_type(void)
+{
+ if (fixed_battery_type == BATTERY_TYPE_UNINITIALIZED) {
+ CPRINTS("Warning: Battery type is not Initialized! "
+ "Setting to default battery type.\n");
+ fixed_battery_type = DEFAULT_BATTERY_TYPE;
+ }
+
+ return fixed_battery_type;
+}
+
+/*
+ * Function to set the battery type, when auto-detection cannot be used.
+ */
+void battery_set_fixed_battery_type(int type)
+{
+ if (type < BATTERY_TYPE_COUNT)
+ fixed_battery_type = type;
+}
+#endif /* CONFIG_BATTERY_TYPE_NO_AUTO_DETECT */
/* Get type of the battery connected on the board */
static int get_battery_type(void)
{
- char manuf_name[32], device_name[32];
+ char manuf_name[32];
int i;
static enum battery_type battery_type = BATTERY_TYPE_COUNT;
@@ -33,36 +105,18 @@ static int get_battery_type(void)
if (battery_manufacturer_name(manuf_name, sizeof(manuf_name)))
return battery_type;
- /*
- * Compare the manufacturer name read from the fuel gauge to the
- * manufacturer names defined in the board_battery_info table. If
- * a device name has been specified in the board_battery_info table,
- * then both the manufacturer and device name must match.
- */
+#if defined(CONFIG_BATTERY_TYPE_NO_AUTO_DETECT)
+ i = battery_get_fixed_battery_type();
+ if (authenticate_battery_type(i, manuf_name))
+ battery_type = i;
+#else
for (i = 0; i < BATTERY_TYPE_COUNT; i++) {
- const struct fuel_gauge_info * const fuel_gauge =
- &board_battery_info[i].fuel_gauge;
- int len = 0;
-
- if (strcasecmp(manuf_name, fuel_gauge->manuf_name))
- continue;
-
- if (fuel_gauge->device_name != NULL) {
-
- if (battery_device_name(device_name,
- sizeof(device_name)))
- continue;
-
- len = strlen(fuel_gauge->device_name);
- if (strncasecmp(device_name, fuel_gauge->device_name,
- len))
- continue;
+ if (authenticate_battery_type(i, manuf_name)) {
+ battery_type = i;
+ break;
}
-
- CPRINTS("found batt:%s", fuel_gauge->manuf_name);
- battery_type = i;
- break;
}
+#endif
return battery_type;
}
diff --git a/common/build.mk b/common/build.mk
index 901d0d3c9d..d00a7f8bb1 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -30,6 +30,7 @@ common-$(CONFIG_ACCEL_LIS2DS)+=math_util.o
common-$(CONFIG_ACCEL_KXCJ9)+=math_util.o
common-$(CONFIG_ACCEL_KX022)+=math_util.o
common-$(CONFIG_TEMP_SENSOR_TMP112)+=math_util.o
+common-$(CONFIG_TEMP_SENSOR_PCT2075)+=math_util.o
ifneq ($(CORE),cortex-m)
common-$(CONFIG_AES)+=aes.o
endif
@@ -83,7 +84,7 @@ common-$(CONFIG_DEVICE_STATE)+=device_state.o
common-$(CONFIG_DPTF)+=dptf.o
common-$(CONFIG_EC_EC_COMM_CLIENT)+=ec_ec_comm_client.o
common-$(CONFIG_EC_EC_COMM_SERVER)+=ec_ec_comm_server.o
-common-$(CONFIG_HOSTCMD_ESPI)+=espi.o
+common-$(CONFIG_HOST_INTERFACE_ESPI)+=espi.o
common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o
common-$(CONFIG_EXTPOWER)+=extpower_common.o
common-$(CONFIG_FANS)+=fan.o pwm.o
diff --git a/common/button.c b/common/button.c
index d30115066d..145cd9db74 100644
--- a/common/button.c
+++ b/common/button.c
@@ -43,7 +43,7 @@ static uint64_t next_deferred_time;
/* Bitmask to keep track of simulated state of each button.
* Bit numbers are aligned to enum button.
*/
-static int sim_button_state;
+static atomic_t sim_button_state;
/*
* Flip state of associated button type in sim_button_state bitmask.
@@ -62,7 +62,7 @@ static int sim_button_state;
*/
static int simulated_button_pressed(const struct button_config *button)
{
- return !!(sim_button_state & BIT(button->type));
+ return !!((uint32_t)sim_button_state & BIT(button->type));
}
#endif
@@ -389,7 +389,8 @@ static void simulate_button_release_deferred(void)
/* Release the button */
for (button_idx = 0; button_idx < BUTTON_COUNT; button_idx++) {
/* Check state for button pressed */
- if (sim_button_state & BIT(buttons[button_idx].type)) {
+ if ((uint32_t)sim_button_state &
+ BIT(buttons[button_idx].type)) {
/* Set state of the button as released */
atomic_clear_bits(&sim_button_state,
BIT(buttons[button_idx].type));
diff --git a/common/charge_manager.c b/common/charge_manager.c
index 3d41c3a08d..041f41f1bc 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -1388,9 +1388,9 @@ void charge_manager_source_port(int port, int enable)
int p, rp;
if (enable)
- atomic_or((uint32_t *)&source_port_bitmap, 1 << port);
+ atomic_or((atomic_t *)&source_port_bitmap, 1 << port);
else
- atomic_clear_bits((uint32_t *)&source_port_bitmap, 1 << port);
+ atomic_clear_bits((atomic_t *)&source_port_bitmap, 1 << port);
/* No change, exit early. */
if (prev_bitmap == source_port_bitmap)
diff --git a/common/charge_ramp.c b/common/charge_ramp.c
index a408771f40..32e0d21ddb 100644
--- a/common/charge_ramp.c
+++ b/common/charge_ramp.c
@@ -18,16 +18,29 @@ test_mockable int chg_ramp_allowed(int port, int supplier)
return 0;
switch (supplier) {
- /* Use ramping for USB-C DTS suppliers (debug accessory eg suzy-q). */
+ /*
+ * Use ramping for USB-C DTS suppliers (debug accessory eg suzy-q).
+ * The suzy-q simply passes through the VBUS. The power supplier behind
+ * may be a SDP/CDP which requires ramping.
+ */
case CHARGE_SUPPLIER_TYPEC_DTS:
return 1;
/*
- * Use HW ramping for USB-C chargers. Don't use SW ramping since the
- * slow ramp causes issues with auto power on (b/169634979).
+ * Don't regulate the input voltage for USB-C chargers. It is
+ * unnecessary as the USB-C compliant adapters should never trigger it
+ * active.
+ *
+ * The USB-C spec defines their load curves should not be below
+ * 4.75V @0A and 4V @3A. We can't define the voltage regulation value
+ * higher than 4V since it limits the current reaching its max 3A. If
+ * we define the voltage regulation value lower than 4V, their load
+ * curves will never be below the voltage regulation line.
+ *
+ * Check go/charge_ramp_typec for detail.
*/
case CHARGE_SUPPLIER_PD:
case CHARGE_SUPPLIER_TYPEC:
- return IS_ENABLED(CONFIG_CHARGE_RAMP_HW);
+ return 0;
/* default: fall through */
}
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index abb271cad4..75ffad576b 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -1200,7 +1200,12 @@ static int shutdown_on_critical_battery(void)
switch (board_critical_shutdown_check(&curr)) {
case CRITICAL_SHUTDOWN_HIBERNATE:
if (IS_ENABLED(CONFIG_HIBERNATE)) {
- if (power_get_state() == POWER_S3S5)
+ /*
+ * If the chipset is on its way down but not
+ * quite there yet, give it a little time to
+ * get there.
+ */
+ if (!chipset_in_state(CHIPSET_STATE_ANY_OFF))
sleep(1);
CPRINTS("Hibernate due to critical battery");
cflush();
@@ -1208,7 +1213,11 @@ static int shutdown_on_critical_battery(void)
}
break;
case CRITICAL_SHUTDOWN_CUTOFF:
- if (power_get_state() == POWER_S3S5)
+ /*
+ * Give the chipset just a sec to get to off if
+ * it's trying.
+ */
+ if (!chipset_in_state(CHIPSET_STATE_ANY_OFF))
sleep(1);
CPRINTS("Cutoff due to critical battery");
cflush();
diff --git a/common/device_event.c b/common/device_event.c
index f7944ae930..748a98ae8f 100644
--- a/common/device_event.c
+++ b/common/device_event.c
@@ -17,8 +17,8 @@
#define CPUTS(outstr) cputs(CC_EVENTS, outstr)
#define CPRINTS(format, args...) cprints(CC_EVENTS, format, ## args)
-static uint32_t device_current_events;
-static uint32_t device_enabled_events;
+static atomic_t device_current_events;
+static atomic_t device_enabled_events;
uint32_t device_get_current_events(void)
{
@@ -40,7 +40,7 @@ void device_set_events(uint32_t mask)
/* Ignore events that are not enabled */
mask &= device_enabled_events;
- if ((device_current_events & mask) != mask) {
+ if (((uint32_t)device_current_events & mask) != mask) {
CPRINTS("device event set 0x%08x", mask);
} else {
/*
@@ -64,7 +64,7 @@ void device_set_events(uint32_t mask)
void device_clear_events(uint32_t mask)
{
/* Only print if something's about to change */
- if (device_current_events & mask)
+ if ((uint32_t)device_current_events & mask)
CPRINTS("device event clear 0x%08x", mask);
atomic_clear_bits(&device_current_events, mask);
diff --git a/common/dptf.c b/common/dptf.c
index 33a42ba5af..28ccff34f2 100644
--- a/common/dptf.c
+++ b/common/dptf.c
@@ -28,6 +28,8 @@ static struct {
int temp; /* degrees K, negative for disabled */
cond_t over; /* watch for crossings */
} dptf_threshold[TEMP_SENSOR_COUNT][DPTF_THRESHOLDS_PER_SENSOR];
+_STATIC_ASSERT(TEMP_SENSOR_COUNT > 0,
+ "CONFIG_PLATFORM_EC_DPTF enabled, but no temp sensors");
static void dptf_init(void)
{
@@ -43,14 +45,14 @@ static void dptf_init(void)
DECLARE_HOOK(HOOK_INIT, dptf_init, HOOK_PRIO_DEFAULT);
/* Keep track of which triggered sensor thresholds the AP has seen */
-static uint32_t dptf_seen;
+static atomic_t dptf_seen;
int dptf_query_next_sensor_event(void)
{
int id;
for (id = 0; id < TEMP_SENSOR_COUNT; id++)
- if (dptf_seen & BIT(id)) { /* atomic? */
+ if ((uint32_t)dptf_seen & BIT(id)) {
atomic_clear_bits(&dptf_seen, BIT(id));
return id;
}
@@ -196,7 +198,7 @@ static int command_dptftemp(int argc, char **argv)
ccprintf(" %s\n", temp_sensors[id].name);
}
- ccprintf("AP seen mask: 0x%08x\n", dptf_seen);
+ ccprintf("AP seen mask: 0x%08x\n", (int)dptf_seen);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(dptftemp, command_dptftemp,
diff --git a/common/ec_features.c b/common/ec_features.c
index a7e097e733..2147c1b48a 100644
--- a/common/ec_features.c
+++ b/common/ec_features.c
@@ -147,6 +147,9 @@ uint32_t get_feature_flags1(void)
#ifdef CONFIG_USB_MUX_AP_ACK_REQUEST
| EC_FEATURE_MASK_1(EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK)
#endif
+#ifdef CONFIG_POWER_S4_RESIDENCY
+ | EC_FEATURE_MASK_1(EC_FEATURE_S4_RESIDENCY)
+#endif
;
return board_override_feature_flags1(result);
}
diff --git a/common/fmap.c b/common/fmap.c
index 47fa75f0e9..6bae9c7f85 100644
--- a/common/fmap.c
+++ b/common/fmap.c
@@ -13,7 +13,7 @@
/*
* FMAP structs.
- * See https://chromium.googlesource.com/chromiumos/third_party/flashmap/+/master/lib/fmap.h
+ * See https://chromium.googlesource.com/chromiumos/third_party/flashmap/+/HEAD/lib/fmap.h
*/
#define FMAP_NAMELEN 32
#define FMAP_SIGNATURE "__FMAP__"
diff --git a/common/fpsensor/fpsensor.c b/common/fpsensor/fpsensor.c
index 8d4f88c8eb..58b1bd71cf 100644
--- a/common/fpsensor/fpsensor.c
+++ b/common/fpsensor/fpsensor.c
@@ -754,7 +754,7 @@ static enum ec_error_list fp_console_action(uint32_t mode)
while (tries--) {
if (!(sensor_mode & FP_MODE_ANY_CAPTURE)) {
- CPRINTS("done (events:%x)", fp_events);
+ CPRINTS("done (events:%x)", (int)fp_events);
return 0;
}
usleep(100 * MSEC);
diff --git a/common/fpsensor/fpsensor_state.c b/common/fpsensor/fpsensor_state.c
index db64110b56..bd907e2c00 100644
--- a/common/fpsensor/fpsensor_state.c
+++ b/common/fpsensor/fpsensor_state.c
@@ -3,6 +3,7 @@
* found in the LICENSE file.
*/
+#include "atomic.h"
#include "common.h"
#include "cryptoc/util.h"
#include "ec_commands.h"
@@ -51,7 +52,7 @@ uint8_t tpm_seed[FP_CONTEXT_TPM_BYTES];
/* Status of the FP encryption engine. */
static uint32_t fp_encryption_status;
-uint32_t fp_events;
+atomic_t fp_events;
uint32_t sensor_mode;
diff --git a/common/host_event_commands.c b/common/host_event_commands.c
index 1856c88c37..532cfe3be3 100644
--- a/common/host_event_commands.c
+++ b/common/host_event_commands.c
@@ -264,7 +264,7 @@ static struct lazy_wake_masks {
static void host_events_atomic_or(host_event_t *e, host_event_t m)
{
- uint32_t *ptr = (uint32_t *)e;
+ atomic_t *ptr = (atomic_t *)e;
atomic_or(ptr, (uint32_t)m);
#ifdef CONFIG_HOST_EVENT64
@@ -274,7 +274,7 @@ static void host_events_atomic_or(host_event_t *e, host_event_t m)
static void host_events_atomic_clear(host_event_t *e, host_event_t m)
{
- uint32_t *ptr = (uint32_t *)e;
+ atomic_t *ptr = (atomic_t *)e;
atomic_clear_bits(ptr, (uint32_t)m);
#ifdef CONFIG_HOST_EVENT64
diff --git a/common/i2c_controller.c b/common/i2c_controller.c
index 90d8a8da80..a99952943e 100644
--- a/common/i2c_controller.c
+++ b/common/i2c_controller.c
@@ -272,8 +272,8 @@ int i2c_xfer_unlocked(const int port,
num_msgs++;
}
-
- if (no_pec_af & ~I2C_ADDR_MASK)
+ /* Big endian flag is used in wrappers for this call */
+ if (no_pec_af & ~(I2C_ADDR_MASK | I2C_FLAG_BIG_ENDIAN))
ccprintf("Ignoring flags from i2c addr_flags: %04x",
no_pec_af);
diff --git a/common/i2c_trace.c b/common/i2c_trace.c
index 67b8864b22..e853a834bd 100644
--- a/common/i2c_trace.c
+++ b/common/i2c_trace.c
@@ -67,7 +67,11 @@ static int command_i2ctrace_list(void)
ccprintf("%-2zd %d %-8s 0x%X",
i,
trace_entries[i].port,
+#ifndef CONFIG_ZEPHYR
i2c_port->name,
+#else
+ "",
+#endif /* CONFIG_ZEPHYR */
trace_entries[i].addr_lo);
if (trace_entries[i].addr_hi
!= trace_entries[i].addr_lo)
diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c
index 071b441cfa..8d59fb0a33 100644
--- a/common/keyboard_scan.c
+++ b/common/keyboard_scan.c
@@ -140,9 +140,9 @@ void keyboard_scan_enable(int enable, enum kb_scan_disable_masks mask)
{
/* Access atomically */
if (enable) {
- atomic_clear_bits((uint32_t *)&disable_scanning_mask, mask);
+ atomic_clear_bits((atomic_t *)&disable_scanning_mask, mask);
} else {
- atomic_or((uint32_t *)&disable_scanning_mask, mask);
+ atomic_or((atomic_t *)&disable_scanning_mask, mask);
clear_typematic_key();
}
@@ -954,9 +954,9 @@ int keyboard_factory_test_scan(void)
gpio_set_flags_by_mask(port, 1 << id, GPIO_OUT_LOW);
- for (j = 0; j < i; j++) {
+ for (j = 0; j < keyboard_factory_scan_pins_used; j++) {
- if (keyboard_factory_scan_pins[j][0] < 0)
+ if (keyboard_factory_scan_pins[j][0] < 0 || i == j)
continue;
if (keyboard_raw_is_input_low(
diff --git a/common/led_common.c b/common/led_common.c
index 85879b148f..6c0e2ac426 100644
--- a/common/led_common.c
+++ b/common/led_common.c
@@ -47,6 +47,16 @@ int led_auto_control_is_enabled(enum ec_led_id led_id)
return (led_auto_control_flags & LED_AUTO_CONTROL_FLAG(led_id)) != 0;
}
+__attribute__((weak)) void board_led_auto_control(void)
+{
+ /*
+ * The projects have only power led won't change the led
+ * state immediately as the auto command is called for
+ * they only check the led state while the power state
+ * is changed.
+ */
+}
+
static enum ec_status led_command_control(struct host_cmd_handler_args *args)
{
const struct ec_params_led_control *p = args->params;
@@ -69,6 +79,8 @@ static enum ec_status led_command_control(struct host_cmd_handler_args *args)
if (p->flags & EC_LED_FLAGS_AUTO) {
led_auto_control(p->led_id, 1);
+ if (!IS_ENABLED(CONFIG_LED_ONOFF_STATES))
+ board_led_auto_control();
} else {
if (led_set_brightness(p->led_id, p->brightness) != EC_SUCCESS)
return EC_RES_INVALID_PARAM;
diff --git a/common/mkbp_fifo.c b/common/mkbp_fifo.c
index 428d6412fc..c394d9fc77 100644
--- a/common/mkbp_fifo.c
+++ b/common/mkbp_fifo.c
@@ -28,7 +28,7 @@
static uint32_t fifo_start; /* first entry */
static uint32_t fifo_end; /* last entry */
-static uint32_t fifo_entries; /* number of existing entries */
+static atomic_t fifo_entries; /* number of existing entries */
static uint8_t fifo_max_depth = FIFO_DEPTH;
static struct ec_response_get_next_event fifo[FIFO_DEPTH];
diff --git a/common/mock/usb_pd_dpm_mock.c b/common/mock/usb_pd_dpm_mock.c
index 8b6fbaa30e..766cdcecf4 100644
--- a/common/mock/usb_pd_dpm_mock.c
+++ b/common/mock/usb_pd_dpm_mock.c
@@ -31,6 +31,10 @@ void dpm_init(int port)
dpm[port].mode_exit_request = false;
}
+void dpm_mode_exit_complete(int port)
+{
+}
+
void dpm_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count,
uint32_t *vdm)
{
diff --git a/common/motion_sense.c b/common/motion_sense.c
index a9b15fd071..afffb02e78 100644
--- a/common/motion_sense.c
+++ b/common/motion_sense.c
@@ -73,7 +73,7 @@ STATIC_IF(CONFIG_MOTION_FILL_LPC_SENSE_DATA) void update_sense_data(
uint8_t *lpc_status, int *psample_id);
/* Flags to control whether to send an ODR change event for a sensor */
-static uint32_t odr_event_required;
+static atomic_t odr_event_required;
/* Whether or not the FIFO interrupt should be enabled (set from the AP). */
__maybe_unused static int fifo_int_enabled;
diff --git a/common/ocpc.c b/common/ocpc.c
index 3bc2a265d3..d63e6f8793 100644
--- a/common/ocpc.c
+++ b/common/ocpc.c
@@ -379,6 +379,7 @@ int ocpc_config_secondary_charger(int *desired_input_current,
if (batt.desired_voltage) {
if (((batt.voltage < batt_info->voltage_min) ||
((batt.voltage < batt_info->voltage_normal) &&
+ (current_ma >= 0) &&
(current_ma <= batt_info->precharge_current))) &&
(ph != PHASE_PRECHARGE)) {
/*
diff --git a/common/peripheral_charger.c b/common/peripheral_charger.c
index 0a597ad6bd..9ed8d8394d 100644
--- a/common/peripheral_charger.c
+++ b/common/peripheral_charger.c
@@ -22,7 +22,7 @@
#define CPRINTS(fmt, args...) cprints(CC_PCHG, "PCHG: " fmt, ##args)
/* Currently only used for FW update. */
-static uint32_t pchg_host_events;
+static atomic_t pchg_host_events;
static void pchg_queue_event(struct pchg *ctx, enum pchg_event event)
{
diff --git a/common/system.c b/common/system.c
index 5e18170b59..8f85e85e3c 100644
--- a/common/system.c
+++ b/common/system.c
@@ -72,11 +72,11 @@ STATIC_IF(CONFIG_HIBERNATE) uint32_t hibernate_seconds;
STATIC_IF(CONFIG_HIBERNATE) uint32_t hibernate_microseconds;
/* On-going actions preventing going into deep-sleep mode */
-uint32_t sleep_mask;
+atomic_t sleep_mask;
#ifdef CONFIG_LOW_POWER_IDLE_LIMITED
/* Set it to prevent going into idle mode */
-uint32_t idle_disabled;
+atomic_t idle_disabled;
#endif
/* SKU ID sourced from AP */
@@ -1491,7 +1491,7 @@ static int command_sleepmask(int argc, char **argv)
}
}
#endif
- ccprintf("sleep mask: %08x\n", sleep_mask);
+ ccprintf("sleep mask: %08x\n", (int)sleep_mask);
return EC_SUCCESS;
}
diff --git a/common/thermal.c b/common/thermal.c
index dba7334b74..50bf3e27f1 100644
--- a/common/thermal.c
+++ b/common/thermal.c
@@ -54,7 +54,7 @@ BUILD_ASSERT(EC_TEMP_THRESH_COUNT == 3);
static cond_t cond_hot[EC_TEMP_THRESH_COUNT];
/* thermal sensor read delay */
-#if defined(CONFIG_TEMP_SENSOR_POWER_GPIO) && \
+#if defined(CONFIG_TEMP_SENSOR_POWER) && \
defined(CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS)
static int first_read_delay = CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS;
#endif
@@ -77,7 +77,7 @@ static void thermal_control(void)
#endif
/* add delay to ensure thermal sensor is ready when EC boot */
-#if defined(CONFIG_TEMP_SENSOR_POWER_GPIO) && \
+#if defined(CONFIG_TEMP_SENSOR_POWER) && \
defined(CONFIG_TEMP_SENSOR_FIRST_READ_DELAY_MS)
if (first_read_delay != 0) {
msleep(first_read_delay);
diff --git a/common/timer.c b/common/timer.c
index 0490741c4c..0cb0d97289 100644
--- a/common/timer.c
+++ b/common/timer.c
@@ -49,7 +49,7 @@ static int timer_irq;
static void expire_timer(task_id_t tskid)
{
/* we are done with this timer */
- atomic_clear_bits(&timer_running, 1 << tskid);
+ atomic_clear_bits((atomic_t *)&timer_running, 1 << tskid);
/* wake up the taks waiting for this timer */
task_set_event(tskid, TASK_EVENT_TIMER);
}
@@ -142,7 +142,7 @@ int timer_arm(timestamp_t event, task_id_t tskid)
return EC_ERROR_BUSY;
timer_deadline[tskid] = event;
- atomic_or(&timer_running, BIT(tskid));
+ atomic_or((atomic_t *)&timer_running, BIT(tskid));
/* Modify the next event if needed */
if ((event.le.hi < now.le.hi) ||
@@ -156,7 +156,7 @@ void timer_cancel(task_id_t tskid)
{
ASSERT(tskid < TASK_ID_COUNT);
- atomic_clear_bits(&timer_running, BIT(tskid));
+ atomic_clear_bits((atomic_t *)&timer_running, BIT(tskid));
/*
* Don't need to cancel the hardware timer interrupt, instead do
* timer-related housekeeping when the next timer interrupt fires.
diff --git a/common/usb_common.c b/common/usb_common.c
index d5f42edca2..be54c62eff 100644
--- a/common/usb_common.c
+++ b/common/usb_common.c
@@ -132,7 +132,7 @@ int remote_flashing(int argc, char **argv)
struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES];
#endif /* CONFIG_COMMON_RUNTIME */
-static __maybe_unused uint32_t pd_host_event_status __aligned(4);
+static __maybe_unused atomic_t pd_host_event_status __aligned(4);
bool pd_firmware_upgrade_check_power_readiness(int port)
{
@@ -578,7 +578,7 @@ static void pd_send_hard_reset(int port)
#ifdef CONFIG_USBC_OCP
-static uint32_t port_oc_reset_req;
+static atomic_t port_oc_reset_req;
static void re_enable_ports(void)
{
@@ -838,7 +838,7 @@ void pd_set_vbus_discharge(int port, int enable)
if (get_usb_pd_discharge() == USB_PD_DISCHARGE_GPIO) {
gpio_discharge_vbus(port, enable);
} else if (get_usb_pd_discharge() == USB_PD_DISCHARGE_TCPC) {
-#ifdef CONFIG_USB_PD_DISCHARGE_PPC
+#ifdef CONFIG_USB_PD_DISCHARGE_TCPC
tcpc_discharge_vbus(port, enable);
#endif
} else if (get_usb_pd_discharge() == USB_PD_DISCHARGE_PPC) {
@@ -852,7 +852,7 @@ void pd_set_vbus_discharge(int port, int enable)
#endif /* CONFIG_USB_PD_DISCHARGE */
#ifdef CONFIG_USB_PD_TCPM_TCPCI
-static uint32_t pd_ports_to_resume;
+static atomic_t pd_ports_to_resume;
static void resume_pd_port(void)
{
uint32_t port;
diff --git a/common/usb_pd_host_cmd.c b/common/usb_pd_host_cmd.c
index 47ec36ad5f..3cc3584e92 100644
--- a/common/usb_pd_host_cmd.c
+++ b/common/usb_pd_host_cmd.c
@@ -548,7 +548,7 @@ DECLARE_HOST_COMMAND(EC_CMD_PD_CONTROL, pd_control, EC_VER_MASK(0));
* Note: this variable must be aligned on 4-byte boundary because we pass the
* address to atomic_ functions which use assembly to access them.
*/
-static uint32_t pd_host_event_status __aligned(4);
+static atomic_t pd_host_event_status __aligned(4);
static enum ec_status
hc_pd_host_event_status(struct host_cmd_handler_args *args)
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index abf75e8004..94eb1a3aa7 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -243,9 +243,9 @@ static struct pd_protocol {
/* Time to debounce exit low power mode */
uint64_t low_power_exit_time;
/* Tasks to notify after TCPC has been reset */
- int tasks_waiting_on_reset;
+ atomic_t tasks_waiting_on_reset;
/* Tasks preventing TCPC from entering low power mode */
- int tasks_preventing_lpm;
+ atomic_t tasks_preventing_lpm;
#endif
#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
diff --git a/common/usbc/dp_alt_mode.c b/common/usbc/dp_alt_mode.c
index 2a532466ac..1ebc5d3d04 100644
--- a/common/usbc/dp_alt_mode.c
+++ b/common/usbc/dp_alt_mode.c
@@ -58,10 +58,12 @@ static const uint8_t state_vdm_cmd[DP_STATE_COUNT] = {
*/
#define DP_FLAG_RETRY BIT(0)
-static uint32_t dpm_dp_flags[CONFIG_USB_PD_PORT_MAX_COUNT];
+static atomic_t dpm_dp_flags[CONFIG_USB_PD_PORT_MAX_COUNT];
-#define DP_SET_FLAG(port, flag) atomic_or(&dpm_dp_flags[port], (flag))
-#define DP_CLR_FLAG(port, flag) atomic_clear_bits(&dpm_dp_flags[port], (flag))
+#define DP_SET_FLAG(port, flag) \
+ atomic_or(&dpm_dp_flags[port], (flag))
+#define DP_CLR_FLAG(port, flag) \
+ atomic_clear_bits(&dpm_dp_flags[port], (flag))
#define DP_CHK_FLAG(port, flag) (dpm_dp_flags[port] & (flag))
bool dp_is_active(int port)
diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c
index 36cfdf0f75..5deea53d5d 100644
--- a/common/usbc/usb_pd_dpm.c
+++ b/common/usbc/usb_pd_dpm.c
@@ -37,7 +37,7 @@
#define DPM_ATTENION_MAX_VDO 2
static struct {
- uint32_t flags;
+ atomic_t flags;
uint32_t vdm_attention[DPM_ATTENION_MAX_VDO];
int vdm_cnt;
mutex_t vdm_attention_mutex;
@@ -48,12 +48,16 @@ static struct {
#define DPM_CHK_FLAG(port, flag) (dpm[(port)].flags & (flag))
/* Flags for internal DPM state */
-#define DPM_FLAG_MODE_ENTRY_DONE BIT(0)
-#define DPM_FLAG_EXIT_REQUEST BIT(1)
-#define DPM_FLAG_ENTER_DP BIT(2)
-#define DPM_FLAG_ENTER_TBT BIT(3)
-#define DPM_FLAG_ENTER_USB4 BIT(4)
-#define DPM_FLAG_SEND_ATTENTION BIT(5)
+#define DPM_FLAG_MODE_ENTRY_DONE BIT(0)
+#define DPM_FLAG_EXIT_REQUEST BIT(1)
+#define DPM_FLAG_ENTER_DP BIT(2)
+#define DPM_FLAG_ENTER_TBT BIT(3)
+#define DPM_FLAG_ENTER_USB4 BIT(4)
+#define DPM_FLAG_ENTER_ANY (DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT \
+ | DPM_FLAG_ENTER_USB4)
+#define DPM_FLAG_SEND_ATTENTION BIT(5)
+#define DPM_FLAG_DATA_RESET_REQUESTED BIT(6)
+#define DPM_FLAG_DATA_RESET_DONE BIT(7)
#ifdef CONFIG_ZEPHYR
static int init_vdm_attention_mutex(const struct device *dev)
@@ -134,6 +138,7 @@ enum ec_status pd_request_enter_mode(int port, enum typec_mode mode)
DPM_CLR_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE);
DPM_CLR_FLAG(port, DPM_FLAG_EXIT_REQUEST);
+ DPM_CLR_FLAG(port, DPM_FLAG_DATA_RESET_DONE);
return EC_RES_SUCCESS;
}
@@ -143,6 +148,12 @@ void dpm_init(int port)
dpm[port].flags = 0;
}
+void dpm_mode_exit_complete(int port)
+{
+ DPM_CLR_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE | DPM_FLAG_EXIT_REQUEST |
+ DPM_FLAG_SEND_ATTENTION);
+}
+
static void dpm_set_mode_entry_done(int port)
{
DPM_SET_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE);
@@ -155,6 +166,13 @@ void dpm_set_mode_exit_request(int port)
DPM_SET_FLAG(port, DPM_FLAG_EXIT_REQUEST);
}
+void dpm_data_reset_complete(int port)
+{
+ DPM_CLR_FLAG(port, DPM_FLAG_DATA_RESET_REQUESTED);
+ DPM_SET_FLAG(port, DPM_FLAG_DATA_RESET_DONE);
+ DPM_CLR_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE);
+}
+
static void dpm_clear_mode_exit_request(int port)
{
DPM_CLR_FLAG(port, DPM_FLAG_EXIT_REQUEST);
@@ -287,6 +305,22 @@ static void dpm_attempt_mode_entry(int port)
if (IS_ENABLED(CONFIG_USBC_SS_MUX) && !usb_mux_set_completed(port))
return;
+ if (IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) &&
+ IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) &&
+ DPM_CHK_FLAG(port, DPM_FLAG_ENTER_ANY) &&
+ !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_REQUESTED) &&
+ !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) {
+ pd_dpm_request(port, DPM_REQUEST_DATA_RESET);
+ DPM_SET_FLAG(port, DPM_FLAG_DATA_RESET_REQUESTED);
+ return;
+ }
+
+ if (IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) &&
+ IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) &&
+ !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) {
+ return;
+ }
+
/* Check if port, port partner and cable support USB4. */
if (IS_ENABLED(CONFIG_USB_PD_USB4) &&
board_is_tbt_usb4_port(port) &&
@@ -469,11 +503,11 @@ static uint32_t max_current_claimed;
K_MUTEX_DEFINE(max_current_claimed_lock);
/* Ports with PD sink needing > 1.5 A */
-static uint32_t sink_max_pdo_requested;
+static atomic_t sink_max_pdo_requested;
/* Ports with FRS source needing > 1.5 A */
-static uint32_t source_frs_max_requested;
+static atomic_t source_frs_max_requested;
/* Ports with non-PD sinks, so current requirements are unknown */
-static uint32_t non_pd_sink_max_requested;
+static atomic_t non_pd_sink_max_requested;
#define LOWEST_PORT(p) __builtin_ctz(p) /* Undefined behavior if p == 0 */
@@ -674,8 +708,8 @@ void dpm_remove_sink(int port)
if (CONFIG_USB_PD_3A_PORTS == 0)
return;
- if (!(BIT(port) & sink_max_pdo_requested) &&
- !(BIT(port) & non_pd_sink_max_requested))
+ if (!(BIT(port) & (uint32_t)sink_max_pdo_requested) &&
+ !(BIT(port) & (uint32_t)non_pd_sink_max_requested))
return;
atomic_clear_bits(&sink_max_pdo_requested, BIT(port));
@@ -696,7 +730,7 @@ void dpm_remove_source(int port)
if (!IS_ENABLED(CONFIG_USB_PD_FRS))
return;
- if (!(BIT(port) & source_frs_max_requested))
+ if (!(BIT(port) & (uint32_t)source_frs_max_requested))
return;
atomic_clear_bits(&source_frs_max_requested, BIT(port));
diff --git a/common/usbc/usb_pd_timer.c b/common/usbc/usb_pd_timer.c
index 97aa699737..4d284024be 100644
--- a/common/usbc/usb_pd_timer.c
+++ b/common/usbc/usb_pd_timer.c
@@ -21,30 +21,35 @@
#define NO_TIMEOUT (-1)
#define EXPIRE_NOW (0)
-#define PD_SET_ACTIVE(p, m) pd_timer_atomic_op( \
- atomic_or, \
- timer_active[p], \
+#define PD_SET_ACTIVE(p, m) pd_timer_atomic_op( \
+ atomic_or, \
+ (atomic_t *)timer_active[p], \
(m))
-#define PD_CLR_ACTIVE(p, m) pd_timer_atomic_op( \
- atomic_clear_bits, \
- timer_active[p], \
+#define PD_CLR_ACTIVE(p, m) pd_timer_atomic_op( \
+ atomic_clear_bits, \
+ (atomic_t *)timer_active[p], \
(m))
-#define PD_CHK_ACTIVE(p, m) ((timer_active[p][0] & ((m) >> 32)) | \
+#define PD_CHK_ACTIVE(p, m) ((timer_active[p][0] & ((m) >> 32)) | \
(timer_active[p][1] & (m)))
-#define PD_SET_DISABLED(p, m) pd_timer_atomic_op( \
- atomic_or, \
- timer_disabled[p], \
+#define PD_SET_DISABLED(p, m) pd_timer_atomic_op( \
+ atomic_or, \
+ (atomic_t *)timer_disabled[p], \
(m))
-#define PD_CLR_DISABLED(p, m) pd_timer_atomic_op( \
- atomic_clear_bits, \
- timer_disabled[p], \
+#define PD_CLR_DISABLED(p, m) pd_timer_atomic_op( \
+ atomic_clear_bits, \
+ (atomic_t *)timer_disabled[p], \
(m))
#define PD_CHK_DISABLED(p, m) ((timer_disabled[p][0] & ((m) >> 32)) | \
(timer_disabled[p][1] & (m)))
#define TIMER_FIELD_NUM_UINT32S 2
+/*
+ * Use uint32_t for timer_active and timer_disabled instead of atomic_t,
+ * because mixing types signed and unsigned around shifting may lead to
+ * undefined behavior.
+ */
test_mockable_static
uint32_t timer_active[MAX_PD_PORTS][TIMER_FIELD_NUM_UINT32S];
test_mockable_static
@@ -77,6 +82,9 @@ __maybe_unused static __const_data const char * const pd_timer_names[] = {
[PE_TIMER_VCONN_ON] = "PE-VCONN_ON",
[PE_TIMER_VDM_RESPONSE] = "PE-VDM_RESPONSE",
[PE_TIMER_WAIT_AND_ADD_JITTER] = "PE-WAIT_AND_ADD_JITTER",
+ [PE_TIMER_VCONN_DISCHARGE] = "PE-VCONN_DISCHARGE",
+ [PE_TIMER_VCONN_REAPPLIED] = "PE-VCONN_REAPPLIED",
+ [PE_TIMER_DATA_RESET_FAIL] = "PE-DATA_RESET_FAIL",
[PR_TIMER_CHUNK_SENDER_REQUEST] = "PR-CHUNK_SENDER_REQUEST",
[PR_TIMER_CHUNK_SENDER_RESPONSE] = "PR-CHUNK_SENDER_RESPONSE",
@@ -116,9 +124,9 @@ __maybe_unused static __const_data const char * const pd_timer_names[] = {
*/
test_mockable_static void pd_timer_atomic_op(
atomic_val_t (*op)(atomic_t*, atomic_val_t),
- uint32_t *const timer_field, const uint64_t mask_val)
+ atomic_t *const timer_field, const uint64_t mask_val)
{
- uint32_t *atomic_timer_field;
+ atomic_t *atomic_timer_field;
union mask64_t {
struct {
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 431dcdc9af..60a2255215 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -20,9 +20,11 @@
#include "task.h"
#include "tcpm/tcpm.h"
#include "util.h"
+#include "usb_charge.h"
#include "usb_common.h"
#include "usb_dp_alt_mode.h"
#include "usb_mode.h"
+#include "usb_mux.h"
#include "usb_pd_dpm.h"
#include "usb_pd_policy.h"
#include "usb_pd.h"
@@ -153,6 +155,8 @@
#define PE_FLAGS_MSG_DISCARDED BIT(29)
/* FLAG to note that hard reset can't be performed due to battery low */
#define PE_FLAGS_SNK_WAITING_BATT BIT(30)
+/* FLAG to note that a data reset is complete */
+#define PE_FLAGS_DATA_RESET_COMPLETE BIT(31)
/* Message flags which should not persist on returning to ready state */
#define PE_FLAGS_READY_CLR (PE_FLAGS_LOCALLY_INITIATED_AMS \
@@ -171,7 +175,6 @@
*/
#define PE_CHK_REPLY(port) (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED) && \
!PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED))
-
/* 6.7.3 Hard Reset Counter */
#define N_HARD_RESET_COUNT 2
@@ -319,6 +322,13 @@ enum usb_pe_state {
PE_DR_SRC_GET_SOURCE_CAP,
/* PD3.0 only states below here*/
+#ifdef CONFIG_USB_PD_DATA_RESET_MSG
+ /* DFP Data Reset States */
+ PE_DDR_SEND_DATA_RESET,
+ PE_DDR_WAIT_FOR_VCONN_OFF,
+ PE_DDR_PERFORM_DATA_RESET,
+#endif /* CONFIG_USB_PD_DATA_RESET_MSG */
+
PE_FRS_SNK_SRC_START_AMS,
PE_GIVE_BATTERY_CAP,
PE_GIVE_BATTERY_STATUS,
@@ -452,6 +462,11 @@ __maybe_unused static __const_data const char * const pe_state_names[] = {
#ifdef CONFIG_USBC_VCONN
[PE_VCS_FORCE_VCONN] = "PE_VCS_Force_Vconn",
#endif
+#ifdef CONFIG_USB_PD_DATA_RESET_MSG
+ [PE_DDR_SEND_DATA_RESET] = "PE_DDR_Send_Data_Reset",
+ [PE_DDR_WAIT_FOR_VCONN_OFF] = "PE_DDR_Wait_For_VCONN_Off",
+ [PE_DDR_PERFORM_DATA_RESET] = "PE_DDR_Perform_Data_Reset",
+#endif /* CONFIG_USB_PD_DATA_RESET_MSG */
#endif /* CONFIG_USB_PD_REV30 */
};
@@ -562,9 +577,9 @@ static struct policy_engine {
/* current port data role (DFP or UFP) */
enum pd_data_role data_role;
/* state machine flags */
- uint32_t flags;
+ atomic_t flags;
/* Device Policy Manager Request */
- uint32_t dpm_request;
+ atomic_t dpm_request;
uint32_t dpm_curr_request;
/* last requested voltage PDO index */
int requested_idx;
@@ -573,7 +588,7 @@ static struct policy_engine {
* Port events - PD_STATUS_EVENT_* values
* Set from PD task but may be cleared by host command
*/
- uint32_t events;
+ atomic_t events;
/* port address where soft resets are sent */
enum tcpci_msg_type soft_reset_sop;
@@ -1172,6 +1187,11 @@ void pe_report_error(int port, enum pe_error e, enum tcpci_msg_type type)
get_state_pe(port) == PE_SRC_DISCOVERY ||
get_state_pe(port) == PE_VCS_CBL_SEND_SOFT_RESET ||
get_state_pe(port) == PE_VDM_IDENTITY_REQUEST_CBL) ||
+#ifdef CONFIG_USB_PD_DATA_RESET_MSG
+ get_state_pe(port) == PE_DDR_SEND_DATA_RESET ||
+ get_state_pe(port) == PE_DDR_WAIT_FOR_VCONN_OFF ||
+ get_state_pe(port) == PE_DDR_PERFORM_DATA_RESET ||
+#endif
(pe_in_frs_mode(port) &&
get_state_pe(port) == PE_PRS_SNK_SRC_SEND_SWAP)
) {
@@ -1529,7 +1549,21 @@ static bool common_src_snk_dpm_requests(int port)
set_state_pe(port, PE_VCS_CBL_SEND_SOFT_RESET);
return true;
}
+#ifdef CONFIG_USB_PD_DATA_RESET_MSG
+ else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_DATA_RESET)) {
+ if (prl_get_rev(port, TCPCI_MSG_SOP) < PD_REV30) {
+ dpm_data_reset_complete(port);
+ return false;
+ }
+ pe_set_dpm_curr_request(port, DPM_REQUEST_DATA_RESET);
+ if (pe[port].data_role == PD_ROLE_DFP)
+ set_state_pe(port, PE_DDR_SEND_DATA_RESET);
+ else
+ return false;
+ return true;
+ }
+#endif /* CONFIG_USB_PD_DATA_RESET_MSG */
return false;
}
@@ -2167,6 +2201,7 @@ static void pe_src_startup_entry(int port)
/* Clear port discovery/mode flags */
pd_dfp_discovery_init(port);
pd_dfp_mode_init(port);
+ dpm_init(port);
pe[port].ama_vdo = PD_VDO_INVALID;
pe[port].vpd_vdo = PD_VDO_INVALID;
pe[port].discover_identity_counter = 0;
@@ -3021,6 +3056,7 @@ static void pe_snk_startup_entry(int port)
/* Clear port discovery/mode flags */
pd_dfp_discovery_init(port);
pd_dfp_mode_init(port);
+ dpm_init(port);
pe[port].discover_identity_counter = 0;
/* Reset dr swap attempt counter */
@@ -6974,6 +7010,255 @@ static void pe_dr_src_get_source_cap_exit(int port)
pe_sender_response_msg_exit(port);
}
+#ifdef CONFIG_USB_PD_DATA_RESET_MSG
+/*
+ * PE_DDR_Send_Data_Reset
+ * See PD rev 3.1, v. 1.2, Figure 8-88.
+ */
+static void pe_ddr_send_data_reset_entry(int port)
+{
+ print_current_state(port);
+ /* Send Data Reset message */
+ send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_DATA_RESET);
+ pe_sender_response_msg_entry(port);
+}
+
+static void pe_ddr_send_data_reset_run(int port)
+{
+ enum pe_msg_check msg_check = pe_sender_response_msg_run(port);
+
+ /* Handle Discarded message, return to PE_SNK/SRC_READY */
+ if (msg_check & PE_MSG_DISCARDED) {
+ pe_set_ready_state(port);
+ return;
+ } else if (msg_check == PE_MSG_SEND_PENDING) {
+ /* Wait until message is sent */
+ return;
+ }
+
+ /*
+ * Transition to the next Data Reset state after receiving Accept.
+ * Return to the ready state after receiving Not Supported. After
+ * receiving Reject or any other message type (Protocol Error),
+ * transition to Error Recovery.
+ */
+ if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
+ const uint32_t hdr = rx_emsg[port].header;
+
+ PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
+
+ if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP &&
+ PD_HEADER_CNT(hdr) == 0 &&
+ !PD_HEADER_EXT(hdr) &&
+ PD_HEADER_TYPE(hdr) == PD_CTRL_ACCEPT) {
+ /*
+ * Start DataResetFailTimer NOTE: This timer continues
+ * to run in every state until it is stopped or it times
+ * out.
+ */
+ pd_timer_enable(port, PE_TIMER_DATA_RESET_FAIL,
+ PD_T_DATA_RESET_FAIL);
+ set_state_pe(port, tc_is_vconn_src(port) ?
+ PE_DDR_PERFORM_DATA_RESET :
+ PE_DDR_WAIT_FOR_VCONN_OFF);
+ return;
+ } else if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP &&
+ PD_HEADER_CNT(hdr) == 0 &&
+ !PD_HEADER_EXT(hdr) &&
+ PD_HEADER_TYPE(hdr) == PD_CTRL_NOT_SUPPORTED) {
+ /* Just pretend it worked. */
+ dpm_data_reset_complete(port);
+ pe_set_ready_state(port);
+ return;
+ }
+
+ /* Otherwise, it's a protocol error. */
+ PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
+ }
+
+ if (pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE) ||
+ PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
+ PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
+ set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
+ return;
+ }
+}
+
+static void pe_ddr_send_data_reset_exit(int port)
+{
+ pe_sender_response_msg_exit(port);
+}
+
+/*
+ * PE_DDR_Wait_For_VCONN_Off
+ */
+static void pe_ddr_wait_for_vconn_off_entry(int port)
+{
+ print_current_state(port);
+ /* Initialize and start VCONNDischargeTimer */
+ pd_timer_enable(port, PE_TIMER_VCONN_DISCHARGE, PD_T_VCONN_DISCHARGE);
+}
+
+static void pe_ddr_wait_for_vconn_off_run(int port)
+{
+ if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
+ const uint32_t hdr = rx_emsg[port].header;
+
+ PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
+
+ if (PD_HEADER_GET_SOP(hdr) == TCPCI_MSG_SOP &&
+ PD_HEADER_CNT(hdr) == 0 &&
+ !PD_HEADER_EXT(hdr) &&
+ PD_HEADER_TYPE(hdr) == PD_CTRL_PS_RDY) {
+ /* PS_RDY message received */
+ pd_timer_enable(port, PE_TIMER_VCONN_REAPPLIED,
+ PD_T_VCONN_REAPPLIED);
+ set_state_pe(port, PE_DDR_PERFORM_DATA_RESET);
+ return;
+ }
+
+ /* Otherwise, it's a protocol error. */
+ PE_SET_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
+ }
+
+ if (pd_timer_is_expired(port, PE_TIMER_VCONN_DISCHARGE) ||
+ PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
+ PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
+ set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
+ return;
+ }
+}
+
+static void pe_ddr_wait_for_vconn_off_exit(int port)
+{
+ pd_timer_disable(port, PE_TIMER_VCONN_DISCHARGE);
+}
+
+/*
+ * PE_DDR_Perform_Data_Reset
+ * See PD rev 3.1, v. 1.2, section 6.3.14.
+ */
+static void pe_ddr_perform_data_reset_entry(int port)
+{
+ print_current_state(port);
+
+ /*
+ * 1) The DFP shall:
+ * a) Disconnect the Port’s USB 2.0 D+/D- signals.
+ * b) If operating in USB 3.2 remove the port’s Rx Terminations.
+ * c) If operating in [USB4] drive the port’s SBTX to a logic low.
+ */
+ usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_DISCONNECT,
+ polarity_rm_dts(pd_get_polarity(port)));
+
+ /* 2) Both the DFP and UFP Shall exit all Alternate Modes if any. */
+ if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
+ pd_dfp_exit_mode(port, TCPCI_MSG_SOP, 0, 0);
+ pd_dfp_exit_mode(port, TCPCI_MSG_SOP_PRIME, 0, 0);
+ pd_dfp_exit_mode(port, TCPCI_MSG_SOP_PRIME_PRIME, 0, 0);
+ }
+
+ /* 3) Reset the cable */
+ /*
+ * TODO(b/141363146): The PD spec is ambiguous about which state the PE
+ * should be in during the cable reset (step 3 in section 6.3.14). If
+ * the DFP is not the initial VCONN Source, the cable reset presumably
+ * starts in PE_DDR_Wait_for_VCONN_Off and finishes in
+ * PE_DDR_Perform_Data_Reset. To be consistent with the steps in 6.3.14,
+ * that would imply that steps 1 and 2 take place in
+ * PE_DDR_Send_Data_Reset. However, this would be inconsistent with the,
+ * "Tell the Policy Manager to Perform Data Reset," action in
+ * PE_DDR_Perform_Data_Reset in figure 8-88, DFP Data_Reset Message
+ * State Diagram, since the Data Reset process would have had to start
+ * before then. Resolve this ambiguity and update this implementation.
+ */
+ if (IS_ENABLED(CONFIG_USBC_VCONN) && tc_is_vconn_src(port))
+ pd_request_vconn_swap_off(port);
+ else
+ PE_SET_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE);
+}
+
+static void pe_ddr_perform_data_reset_run(int port)
+{
+ /*
+ * PE_FLAGS_VCONN_SWAP_COMPLETE may be set in 2 cases:
+ * a) If the PE requested to turn VCONN off while entering this state,
+ * i.e. if the TCPM was VCONN Source at that time. If the TCPM did not
+ * start out as VCONN Source, then PE_DDR_Wait_For_VCONN_Off will have
+ * already started the VCONN reapplied timer.
+ * b) When this state requests to turn VCONN on after tVCONNReapplied
+ * expires. At this point, the Data Reset process is complete.
+ */
+ if (IS_ENABLED(CONFIG_USBC_VCONN) && !tc_is_vconn_src(port) &&
+ PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE)) {
+ PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
+ pd_timer_enable(port, PE_TIMER_VCONN_REAPPLIED,
+ PD_T_VCONN_REAPPLIED);
+ } else if (IS_ENABLED(CONFIG_USBC_VCONN) &&
+ pd_timer_is_expired(port, PE_TIMER_VCONN_REAPPLIED)) {
+ pd_request_vconn_swap_on(port);
+ pd_timer_disable(port, PE_TIMER_VCONN_REAPPLIED);
+
+ /*
+ * 4) After tDataReset the DFP shall:
+ * a) Reconnect the [USB 2.0] D+/D- signals
+ * b) If the Port was operating in [USB 3.2] or [USB4]
+ * reapply the port’s Rx Terminations
+ * TODO: Section 6.3.14 implies that tDataReset is a minimum
+ * time for the DFP to leave the lines disconnected during Data
+ * Reset, possibly starting after the cable reset. Section
+ * 6.6.10.2 implies that tDataReset is the maximum time for the
+ * DFP to send Data_Reset_Complete after receiving Accept. These
+ * interpretations are mutually exclusive. Resolve that
+ * ambiguity and update this implementation.
+ */
+ usb_mux_set(port, USB_PD_MUX_NONE, USB_SWITCH_DISCONNECT,
+ polarity_rm_dts(pd_get_polarity(port)));
+ } else if (IS_ENABLED(CONFIG_USBC_VCONN) &&
+ PE_CHK_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE) &&
+ tc_is_vconn_src(port)) {
+ PE_CLR_FLAG(port, PE_FLAGS_VCONN_SWAP_COMPLETE);
+ PE_SET_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE);
+ } else if (PE_CHK_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE) &&
+ !pd_timer_is_disabled(port, PE_TIMER_DATA_RESET_FAIL)) {
+ pd_timer_disable(port, PE_TIMER_DATA_RESET_FAIL);
+ send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_DATA_RESET_COMPLETE);
+ } else if (PE_CHK_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE)) {
+ /*
+ * There is no specified response to Data_Reset_Complete, but
+ * make sure the port partner receives it before returning to a
+ * ready state.
+ */
+ if (PE_CHK_FLAG(port, PE_FLAGS_MSG_DISCARDED))
+ set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
+ else if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE))
+ pe_set_ready_state(port);
+ return;
+ } else if (pd_timer_is_expired(port, PE_TIMER_DATA_RESET_FAIL) ||
+ PE_CHK_FLAG(port, PE_FLAGS_PROTOCOL_ERROR)) {
+ PE_CLR_FLAG(port, PE_FLAGS_PROTOCOL_ERROR);
+ set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
+ return;
+ }
+
+ /*
+ * No messages are expected, so any received would be a protocol error.
+ */
+ if (PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) {
+ PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED);
+ set_state_pe(port, PE_WAIT_FOR_ERROR_RECOVERY);
+ }
+}
+
+static void pe_ddr_perform_data_reset_exit(int port)
+{
+ pd_timer_disable(port, PE_TIMER_VCONN_REAPPLIED);
+ pd_timer_disable(port, PE_TIMER_DATA_RESET_FAIL);
+ PE_CLR_FLAG(port, PE_FLAGS_DATA_RESET_COMPLETE);
+ dpm_data_reset_complete(port);
+}
+#endif /* CONFIG_USB_PD_DATA_RESET_MSG */
+
const uint32_t * const pd_get_src_caps(int port)
{
return pe[port].src_caps;
@@ -6998,7 +7283,7 @@ uint8_t pd_get_src_cap_cnt(int port)
}
/* Track access to the PD discovery structures during HC execution */
-uint32_t task_access[CONFIG_USB_PD_PORT_MAX_COUNT][DISCOVERY_TYPE_COUNT];
+atomic_t task_access[CONFIG_USB_PD_PORT_MAX_COUNT][DISCOVERY_TYPE_COUNT];
void pd_dfp_discovery_init(int port)
{
@@ -7022,7 +7307,7 @@ void pd_dfp_mode_init(int port)
memset(pe[port].partner_amodes, 0, sizeof(pe[port].partner_amodes));
/* Reset the DPM and DP modules to enable alternate mode entry. */
- dpm_init(port);
+ dpm_mode_exit_complete(port);
dp_init(port);
if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
@@ -7446,6 +7731,23 @@ static __const_data const struct usb_state pe_states[] = {
.exit = pe_vcs_force_vconn_exit,
},
#endif /* CONFIG_USBC_VCONN */
+#ifdef CONFIG_USB_PD_DATA_RESET_MSG
+ [PE_DDR_SEND_DATA_RESET] = {
+ .entry = pe_ddr_send_data_reset_entry,
+ .run = pe_ddr_send_data_reset_run,
+ .exit = pe_ddr_send_data_reset_exit,
+ },
+ [PE_DDR_WAIT_FOR_VCONN_OFF] = {
+ .entry = pe_ddr_wait_for_vconn_off_entry,
+ .run = pe_ddr_wait_for_vconn_off_run,
+ .exit = pe_ddr_wait_for_vconn_off_exit,
+ },
+ [PE_DDR_PERFORM_DATA_RESET] = {
+ .entry = pe_ddr_perform_data_reset_entry,
+ .run = pe_ddr_perform_data_reset_run,
+ .exit = pe_ddr_perform_data_reset_exit,
+ },
+#endif /* CONFIG_USB_PD_DATA_RESET_MSG */
#endif /* CONFIG_USB_PD_REV30 */
};
diff --git a/common/usbc/usb_prl_sm.c b/common/usbc/usb_prl_sm.c
index b85a7ee553..d9c3849f58 100644
--- a/common/usbc/usb_prl_sm.c
+++ b/common/usbc/usb_prl_sm.c
@@ -294,7 +294,7 @@ static struct rx_chunked {
/* state machine context */
struct sm_ctx ctx;
/* PRL_FLAGS */
- uint32_t flags;
+ atomic_t flags;
/* error to report when moving to rch_report_error state */
enum pe_error error;
} rch[CONFIG_USB_PD_PORT_MAX_COUNT];
@@ -304,7 +304,7 @@ static struct tx_chunked {
/* state machine context */
struct sm_ctx ctx;
/* state machine flags */
- uint32_t flags;
+ atomic_t flags;
/* error to report when moving to tch_report_error state */
enum pe_error error;
} tch[CONFIG_USB_PD_PORT_MAX_COUNT];
@@ -322,7 +322,7 @@ static struct protocol_layer_tx {
/* state machine context */
struct sm_ctx ctx;
/* state machine flags */
- uint32_t flags;
+ atomic_t flags;
/* last message type we transmitted */
enum tcpci_msg_type last_xmit_type;
/* message id counters for all 6 port partners */
@@ -336,13 +336,13 @@ static struct protocol_hard_reset {
/* state machine context */
struct sm_ctx ctx;
/* state machine flags */
- uint32_t flags;
+ atomic_t flags;
} prl_hr[CONFIG_USB_PD_PORT_MAX_COUNT];
/* Chunking Message Object */
static struct pd_message {
/* message status flags */
- uint32_t flags;
+ atomic_t flags;
/* SOP* */
enum tcpci_msg_type xmit_type;
/* type of message */
diff --git a/common/usbc/usb_retimer_fw_update.c b/common/usbc/usb_retimer_fw_update.c
index 1ff198c78f..87a8f786c5 100644
--- a/common/usbc/usb_retimer_fw_update.c
+++ b/common/usbc/usb_retimer_fw_update.c
@@ -96,8 +96,29 @@ static inline mux_state_t retimer_fw_update_usb_mux_get(int port)
return usb_mux_get(port) & USB_RETIMER_FW_UPDATE_MUX_MASK;
}
+/* Allow mux results to be filled in during HOOKS if needed */
+static void last_result_mux_get(void);
+DECLARE_DEFERRED(last_result_mux_get);
+
+static void last_result_mux_get(void)
+{
+ if (!usb_mux_set_completed(cur_port)) {
+ hook_call_deferred(&last_result_mux_get_data, 20 * MSEC);
+ return;
+ }
+
+ last_result = retimer_fw_update_usb_mux_get(cur_port);
+}
+
void usb_retimer_fw_update_process_op_cb(int port)
{
+ bool result_mux_get = false;
+
+ if (port != cur_port) {
+ CPRINTS("Unexpected FW op: port %d, cur %d", port, cur_port);
+ return;
+ }
+
switch (last_op) {
case USB_RETIMER_FW_UPDATE_SUSPEND_PD:
last_result = 0;
@@ -123,30 +144,37 @@ void usb_retimer_fw_update_process_op_cb(int port)
pd_set_suspend(port, RESUME);
break;
case USB_RETIMER_FW_UPDATE_GET_MUX:
- last_result = retimer_fw_update_usb_mux_get(port);
+ result_mux_get = true;
break;
case USB_RETIMER_FW_UPDATE_SET_USB:
usb_mux_set(port, USB_PD_MUX_USB_ENABLED,
USB_SWITCH_CONNECT, pd_get_polarity(port));
- last_result = retimer_fw_update_usb_mux_get(port);
+ result_mux_get = true;
break;
case USB_RETIMER_FW_UPDATE_SET_SAFE:
usb_mux_set_safe_mode(port);
- last_result = retimer_fw_update_usb_mux_get(port);
+ result_mux_get = true;
break;
case USB_RETIMER_FW_UPDATE_SET_TBT:
usb_mux_set(port, USB_PD_MUX_TBT_COMPAT_ENABLED,
USB_SWITCH_CONNECT, pd_get_polarity(port));
- last_result = retimer_fw_update_usb_mux_get(port);
+ result_mux_get = true;
break;
case USB_RETIMER_FW_UPDATE_DISCONNECT:
usb_mux_set(port, USB_PD_MUX_NONE,
USB_SWITCH_DISCONNECT, pd_get_polarity(port));
- last_result = retimer_fw_update_usb_mux_get(port);
+ result_mux_get = true;
break;
default:
break;
}
+
+ /*
+ * Fill in our mux result if available, or set up a deferred retrieval
+ * if the set is still pending.
+ */
+ if (result_mux_get)
+ last_result_mux_get();
}
void usb_retimer_fw_update_process_op(int port, int op)
@@ -158,6 +186,7 @@ void usb_retimer_fw_update_process_op(int port, int op)
* not change cur_port if retimer scan is in progress
*/
last_op = op;
+ cur_port = port;
switch (op) {
case USB_RETIMER_FW_UPDATE_QUERY_PORT:
@@ -169,7 +198,6 @@ void usb_retimer_fw_update_process_op(int port, int op)
break;
case USB_RETIMER_FW_UPDATE_SUSPEND_PD:
case USB_RETIMER_FW_UPDATE_RESUME_PD:
- cur_port = port;
tc_usb_firmware_fw_update_run(port);
break;
case USB_RETIMER_FW_UPDATE_SET_USB:
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index 3fa9528699..726958ba03 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -401,7 +401,7 @@ static struct type_c {
* else they're disabled if bits PD_DISABLED_NO_CONNECTION or
* PD_DISABLED_BY_POLICY are set.
*/
- uint32_t pd_disabled_mask;
+ atomic_t pd_disabled_mask;
/*
* Timer for handling TOGGLE_OFF/FORCE_SINK mode when auto-toggle
* enabled. See drp_auto_toggle_next_state() for details.
@@ -414,13 +414,13 @@ static struct type_c {
/* Port polarity */
enum tcpc_cc_polarity polarity;
/* port flags, see TC_FLAGS_* */
- uint32_t flags;
+ atomic_t flags;
/* The cc state */
enum pd_cc_states cc_state;
/* Tasks to notify after TCPC has been reset */
- int tasks_waiting_on_reset;
+ atomic_t tasks_waiting_on_reset;
/* Tasks preventing TCPC from entering low power mode */
- int tasks_preventing_lpm;
+ atomic_t tasks_preventing_lpm;
/* Voltage on CC pin */
enum tcpc_cc_voltage_status cc_voltage;
/* Type-C current */
@@ -457,7 +457,7 @@ static void set_state_tc(const int port, const enum usb_tc_state new_state);
test_export_static enum usb_tc_state get_state_tc(const int port);
/* Enable variable for Try.SRC states */
-static uint32_t pd_try_src;
+static atomic_t pd_try_src;
static volatile enum try_src_override_t pd_try_src_override;
static void pd_update_try_source(void);
@@ -825,6 +825,10 @@ int tc_is_attached_snk(int port)
return IS_ATTACHED_SNK(port);
}
+__overridable void tc_update_pd_sleep_mask(int port)
+{
+}
+
void tc_pd_connection(int port, int en)
{
if (en) {
@@ -836,9 +840,10 @@ void tc_pd_connection(int port, int en)
TC_SET_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE);
/* If a PD device is attached then disable deep sleep */
if (IS_ENABLED(CONFIG_LOW_POWER_IDLE) &&
- !IS_ENABLED(CONFIG_USB_PD_TCPC_ON_CHIP)) {
+ IS_ENABLED(CONFIG_USB_PD_TCPC_ON_CHIP))
+ tc_update_pd_sleep_mask(port);
+ else if (IS_ENABLED(CONFIG_LOW_POWER_IDLE))
disable_sleep(SLEEP_MASK_USB_PD);
- }
/*
* Update the mux state, only when the PD capable flag
@@ -852,7 +857,9 @@ void tc_pd_connection(int port, int en)
TC_CLR_FLAG(port, TC_FLAGS_PARTNER_PD_CAPABLE);
/* If a PD device isn't attached then enable deep sleep */
if (IS_ENABLED(CONFIG_LOW_POWER_IDLE) &&
- !IS_ENABLED(CONFIG_USB_PD_TCPC_ON_CHIP)) {
+ IS_ENABLED(CONFIG_USB_PD_TCPC_ON_CHIP))
+ tc_update_pd_sleep_mask(port);
+ else if (IS_ENABLED(CONFIG_LOW_POWER_IDLE)) {
int i;
/* If all ports are not connected, allow the sleep */
diff --git a/common/usbc_ocp.c b/common/usbc_ocp.c
index e20cf9f1f8..c7c977bf12 100644
--- a/common/usbc_ocp.c
+++ b/common/usbc_ocp.c
@@ -42,7 +42,7 @@
static uint8_t oc_event_cnt_tbl[CONFIG_USB_PD_PORT_MAX_COUNT];
/* A flag for ports with sink device connected. */
-static uint32_t snk_connected_ports;
+static atomic_t snk_connected_ports;
static void clear_oc_tbl(void)
{
@@ -53,7 +53,7 @@ static void clear_oc_tbl(void)
* Only clear the table if the port partner is no longer
* attached after debouncing.
*/
- if ((!(BIT(port) & snk_connected_ports)) &&
+ if ((!(BIT(port) & (uint32_t)snk_connected_ports)) &&
oc_event_cnt_tbl[port]) {
oc_event_cnt_tbl[port] = 0;
CPRINTS("C%d: OC events cleared", port);